Update Node controller to make it generic

This commit updates node controller code to use generic manager
interface instead of redfish directly

Partially-Implements blueprint add-vendor-extensible-framework
Change-Id: Ic551167798306a1ed6b5c609117e6d19e6de6574
This commit is contained in:
Anusha Ramineni 2017-08-22 16:04:39 +05:30
parent 570086d34a
commit 1afb9f0cbf
8 changed files with 136 additions and 113 deletions

View File

@ -30,8 +30,12 @@ class Nodes(Resource):
@validator.check_input('compose_node_schema') @validator.check_input('compose_node_schema')
def post(self): def post(self):
# TODO(): podm_id should be passed in request body, if not passed
# scheduler will decide on podm_id
req = request.get_json()
return utils.make_response( return utils.make_response(
http_client.OK, nodes.Node.compose_node(request.get_json())) http_client.OK,
nodes.Node(podm_id=req['podm_id']).compose_node(req))
class Node(Resource): class Node(Resource):
@ -39,11 +43,12 @@ class Node(Resource):
def get(self, node_uuid): def get(self, node_uuid):
return utils.make_response( return utils.make_response(
http_client.OK, http_client.OK,
nodes.Node.get_composed_node_by_uuid(node_uuid)) nodes.Node(node_id=node_uuid).get_composed_node_by_uuid(node_uuid))
def delete(self, node_uuid): def delete(self, node_uuid):
return utils.make_response( return utils.make_response(
http_client.OK, nodes.Node.delete_composed_node(node_uuid)) http_client.OK,
nodes.Node(node_id=node_uuid).delete_composed_node(node_uuid))
class NodeAction(Resource): class NodeAction(Resource):
@ -52,15 +57,18 @@ class NodeAction(Resource):
def post(self, node_uuid): def post(self, node_uuid):
return utils.make_response( return utils.make_response(
http_client.NO_CONTENT, http_client.NO_CONTENT,
nodes.Node.node_action(node_uuid, request.get_json())) nodes.Node(node_id=node_uuid).node_action(node_uuid,
request.get_json()))
class NodeManage(Resource): class NodeManage(Resource):
@validator.check_input('node_manage_schema') @validator.check_input('node_manage_schema')
def post(self): def post(self):
req = request.get_json()
return utils.make_response( return utils.make_response(
http_client.OK, nodes.Node.manage_node(request.get_json())) http_client.OK,
nodes.Node(podm_id=req['podm_id']).manage_node(req))
class NodesStorage(Resource): class NodesStorage(Resource):

View File

@ -18,18 +18,36 @@ from valence.common import exception
from valence.common import utils from valence.common import utils
from valence.controller import flavors from valence.controller import flavors
from valence.db import api as db_api from valence.db import api as db_api
from valence.podmanagers import manager
from valence.provision import driver from valence.provision import driver
from valence.redfish import redfish
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class Node(object): class Node(object):
def __init__(self, node_id=None, podm_id=None):
"""Create node object
node uuid or podmanager uuid is required to create the
podmanager connection object.
:param node_id Node uuid
:param podm_id podmanager id
"""
self.podm_id = podm_id
if node_id:
self.node = db_api.Connection.get_composed_node_by_uuid(node_id).\
as_dict()
self.podm_id = self.node['podm_id']
self.connection = manager.get_connection(self.podm_id)
@staticmethod @staticmethod
def _show_node_brief_info(node_info): def _show_node_brief_info(node_info):
return {key: node_info[key] for key in node_info.keys() return {key: node_info[key] for key in node_info.keys()
if key in ["uuid", "name", "index", "uri"]} if key in ["uuid", "name", "podm_id", "index", "resource_uri"]}
@staticmethod @staticmethod
def _create_compose_request(name, description, requirements): def _create_compose_request(name, description, requirements):
@ -57,8 +75,7 @@ class Node(object):
return request return request
@classmethod def compose_node(self, request_body):
def compose_node(cls, request_body):
"""Compose new node """Compose new node
param request_body: parameter for node composition param request_body: parameter for node composition
@ -80,28 +97,25 @@ class Node(object):
# "description" is optional # "description" is optional
description = request_body.get("description", "") description = request_body.get("description", "")
compose_request = cls._create_compose_request(name, compose_request = self._create_compose_request(name, description,
description, requirements)
requirements)
# Call redfish to compose new node
composed_node = redfish.compose_node(compose_request)
composed_node = self.connection.compose_node(compose_request)
composed_node["uuid"] = utils.generate_uuid() composed_node["uuid"] = utils.generate_uuid()
# Only store the minimum set of composed node info into backend db, # Only store the minimum set of composed node info into backend db,
# since other fields like power status may be changed and valence is # since other fields like power status may be changed and valence is
# not aware. # not aware.
node_db = {"uuid": composed_node["uuid"], node_db = {"uuid": composed_node["uuid"],
"podm_id": self.podm_id,
"name": composed_node["name"], "name": composed_node["name"],
"index": composed_node["index"], "index": composed_node["index"],
"uri": composed_node["resource_uri"]} "resource_uri": composed_node["resource_uri"]}
db_api.Connection.create_composed_node(node_db) db_api.Connection.create_composed_node(node_db)
return cls._show_node_brief_info(composed_node) return self._show_node_brief_info(composed_node)
@classmethod def manage_node(self, request_body):
def manage_node(cls, request_body):
"""Manage existing RSD node. """Manage existing RSD node.
param request_body: Parameters for node to manage. param request_body: Parameters for node to manage.
@ -110,32 +124,34 @@ class Node(object):
{ {
'node_index': <Redfish index of node to manage> 'node_index': <Redfish index of node to manage>
'podm_id': <podmanager id with which node is managed>
} }
return: Info on managed node. return: Info on managed node.
""" """
composed_node = redfish.get_node_by_id(request_body["node_index"])
# Check to see that the node to manage doesn't already exist in the # Check to see that the node to manage doesn't already exist in the
# Valence database. # Valence database.
node_index = request_body["node_index"]
error_msg = ("Node '%s' already managed by Valence") error_msg = ("Node '%s' already managed by Valence")
current_nodes = cls.list_composed_nodes() current_nodes = self.list_composed_nodes()
for node in current_nodes: for node in current_nodes:
if node['index'] == composed_node['index']: if node['index'] == node_index:
raise exception.ResourceExists( raise exception.ResourceExists(error_msg % node_index)
error_msg % node['index'])
# Get podm connection with which node should be managed
composed_node = self.connection.get_node_info(node_index)
composed_node["uuid"] = utils.generate_uuid() composed_node["uuid"] = utils.generate_uuid()
node_db = {"uuid": composed_node["uuid"], node_db = {"uuid": composed_node["uuid"],
"name": composed_node["name"], "name": composed_node["name"],
"podm_id": self.podm_id,
"index": composed_node["index"], "index": composed_node["index"],
"uri": composed_node["resource_uri"]} "resource_uri": composed_node["resource_uri"]}
db_api.Connection.create_composed_node(node_db) db_api.Connection.create_composed_node(node_db)
return cls._show_node_brief_info(composed_node) return self._show_node_brief_info(composed_node)
@classmethod def get_composed_node_by_uuid(self, node_uuid):
def get_composed_node_by_uuid(cls, node_uuid):
"""Get composed node details """Get composed node details
Get the detail of specific composed node. In some cases db data may be Get the detail of specific composed node. In some cases db data may be
@ -147,28 +163,20 @@ class Node(object):
return: detail of this composed node return: detail of this composed node
""" """
node_db = db_api.Connection.get_composed_node_by_uuid(node_uuid)\ # Get podm connection to retrieve details
.as_dict() node_hw = self.connection.get_node_info(self.node['index'])
node_hw = redfish.get_node_by_id(node_db["index"])
# Add those fields of composed node from db # Add those fields of composed node from db
node_hw.update(node_db) node_hw.update(self.node)
return node_hw return node_hw
@classmethod def delete_composed_node(self, node_uuid):
def delete_composed_node(cls, node_uuid):
"""Delete a composed node """Delete a composed node
param node_uuid: uuid of composed node param node_uuid: uuid of composed node
return: message of this deletion return: message of this deletion
""" """
# Call podmanager to delete node, and delete corresponding entry in db
# Get node detail from db, and map node uuid to index message = self.connection.delete_composed_node(self.node['index'])
index = db_api.Connection.get_composed_node_by_uuid(node_uuid).index
# Call redfish to delete node, and delete corresponding entry in db
message = redfish.delete_composed_node(index)
db_api.Connection.delete_composed_node(node_uuid) db_api.Connection.delete_composed_node(node_uuid)
return message return message
@ -182,17 +190,15 @@ class Node(object):
return [cls._show_node_brief_info(node_info.as_dict()) return [cls._show_node_brief_info(node_info.as_dict())
for node_info in db_api.Connection.list_composed_nodes()] for node_info in db_api.Connection.list_composed_nodes()]
@classmethod def node_action(self, node_uuid, request_body):
def node_action(cls, node_uuid, request_body):
"""Post action to a composed node """Post action to a composed node
param node_uuid: uuid of composed node param node_uuid: uuid of composed node
param request_body: parameter of node action param request_body: parameter of node action
return: message of this deletion return: message of this deletion
""" """
# Get node detail from db, and map node uuid to index node_index = self.node['index']
index = db_api.Connection.get_composed_node_by_uuid(node_uuid).index return self.connection.node_action(node_index, request_body)
return redfish.node_action(index, request_body)
@classmethod @classmethod
def node_register(cls, node_uuid, request_body): def node_register(cls, node_uuid, request_body):

View File

@ -17,7 +17,7 @@ podm_connections = {}
podm_modules = {} podm_modules = {}
def get_podm_connection(podm_id): def get_connection(podm_id):
podm_connection = podm_connections.get(podm_id, None) podm_connection = podm_connections.get(podm_id, None)
if podm_connection: if podm_connection:
return podm_connection return podm_connection
@ -25,7 +25,7 @@ def get_podm_connection(podm_id):
username, password = utils.get_basic_auth_credentials( username, password = utils.get_basic_auth_credentials(
podm_db['authentication']) podm_db['authentication'])
podm_connection = Manager(podm_db['url'], username, password, podm_connection = Manager(podm_db['url'], username, password,
podm_db['driver']) podm_db['driver']).podm
podm_connections[podm_id] = podm_connection podm_connections[podm_id] = podm_connection
return podm_connection return podm_connection

View File

@ -26,6 +26,18 @@ class PodManagerBase(object):
def get_podm_info(self): def get_podm_info(self):
return self.get_resource_info_by_url(self.podm_url) return self.get_resource_info_by_url(self.podm_url)
# TODO(): use rsd_lib here
def compose_node(self, request_body):
pass
# TODO(): use rsd_lib here
def delete_composed_node(self, node_id):
pass
# TODO(): use rsd_lib here
def node_action(self, index, request_body):
pass
def get_resource_info_by_url(self, resource_url): def get_resource_info_by_url(self, resource_url):
return self.driver.get_resources_by_url(resource_url) return self.driver.get_resources_by_url(resource_url)

View File

@ -18,6 +18,7 @@ import mock
from valence.common import exception from valence.common import exception
from valence.controller import nodes from valence.controller import nodes
from valence.podmanagers import podm_base
from valence.tests.unit.db import utils as test_utils from valence.tests.unit.db import utils as test_utils
from valence.tests.unit.fakes import flavor_fakes from valence.tests.unit.fakes import flavor_fakes
from valence.tests.unit.fakes import node_fakes from valence.tests.unit.fakes import node_fakes
@ -25,15 +26,22 @@ from valence.tests.unit.fakes import node_fakes
class TestAPINodes(unittest.TestCase): class TestAPINodes(unittest.TestCase):
@mock.patch('valence.podmanagers.manager.get_connection')
@mock.patch('valence.redfish.sushy.sushy_instance.RedfishInstance')
def setUp(self, mock_redfish, mock_connection):
self.node_controller = nodes.Node(podm_id='test-podm-1')
self.node_controller.connection = podm_base.PodManagerBase(
'fake', 'fake-pass', 'http://fake-url')
def test_show_node_brief_info(self): def test_show_node_brief_info(self):
"""Test only show node brief info""" """Test only show node brief info"""
node_info = node_fakes.get_test_composed_node() node_info = node_fakes.get_test_composed_node()
node_info['uri'] = 'nodes/7be5bc10-dcdf-11e6-bd86-934bc6947c55/'
expected = { expected = {
"index": "1", "index": "1",
"name": "fake_name", "name": "fake_name",
"podm_id": "78e2a25-2901-438d-8157-de7ffd68d05",
"uuid": "ea8e2a25-2901-438d-8157-de7ffd68d051", "uuid": "ea8e2a25-2901-438d-8157-de7ffd68d051",
"uri": 'nodes/7be5bc10-dcdf-11e6-bd86-934bc6947c55/', "resource_uri": 'nodes/7be5bc10-dcdf-11e6-bd86-934bc6947c55/',
} }
self.assertEqual(expected, self.assertEqual(expected,
nodes.Node._show_node_brief_info(node_info)) nodes.Node._show_node_brief_info(node_info))
@ -72,10 +80,11 @@ class TestAPINodes(unittest.TestCase):
@mock.patch("valence.db.api.Connection.create_composed_node") @mock.patch("valence.db.api.Connection.create_composed_node")
@mock.patch("valence.common.utils.generate_uuid") @mock.patch("valence.common.utils.generate_uuid")
@mock.patch("valence.controller.nodes.Node.list_composed_nodes") @mock.patch("valence.controller.nodes.Node.list_composed_nodes")
@mock.patch("valence.redfish.redfish.get_node_by_id") @mock.patch("valence.podmanagers.podm_base.PodManagerBase.get_node_info")
def test_manage_node(self, mock_get_node, mock_list_nodes, def test_manage_node(self, mock_get_node, mock_list_nodes,
mock_generate_uuid, mock_db_create_composed_node): mock_generate_uuid, mock_db_create_composed_node):
manage_node = node_fakes.get_test_composed_node() manage_node = node_fakes.get_test_composed_node()
manage_node['podm_id'] = 'test-podm-1'
mock_get_node.return_value = manage_node mock_get_node.return_value = manage_node
node_list = node_fakes.get_test_node_list() node_list = node_fakes.get_test_node_list()
# Change the index of node 1 so that the node to manage # Change the index of node 1 so that the node to manage
@ -85,47 +94,45 @@ class TestAPINodes(unittest.TestCase):
uuid = "ea8e2a25-2901-438d-8157-de7ffd68d051" uuid = "ea8e2a25-2901-438d-8157-de7ffd68d051"
mock_generate_uuid.return_value = uuid mock_generate_uuid.return_value = uuid
node_db = {"uuid": manage_node["uuid"], node_db = {"uuid": manage_node["uuid"],
"index": manage_node["index"], "index": manage_node["index"],
"podm_id": manage_node["podm_id"],
"name": manage_node["name"], "name": manage_node["name"],
"uri": manage_node["resource_uri"]} "resource_uri": manage_node["resource_uri"]}
nodes.Node.manage_node({"node_index": "1"}) req = {"node_index": "1"}
self.node_controller.manage_node(req)
mock_db_create_composed_node.assert_called_once_with(node_db) mock_db_create_composed_node.assert_called_once_with(node_db)
@mock.patch("valence.controller.nodes.Node.list_composed_nodes") @mock.patch("valence.controller.nodes.Node.list_composed_nodes")
@mock.patch("valence.redfish.redfish.get_node_by_id") def test_manage_already_managed_node(self, mock_list_nodes):
def test_manage_already_managed_node(self, mock_get_node, mock_list_nodes):
manage_node = node_fakes.get_test_composed_node()
mock_get_node.return_value = manage_node
# Leave the index of node 1 as '1' so that it conflicts with the node # Leave the index of node 1 as '1' so that it conflicts with the node
# being managed, meaning we're trying to manage a node that already # being managed, meaning we're trying to manage a node that already
# exists in the Valence DB. # exists in the Valence DB.
node_list = node_fakes.get_test_node_list() node_list = node_fakes.get_test_node_list()
mock_list_nodes.return_value = node_list mock_list_nodes.return_value = node_list
self.assertRaises(exception.ResourceExists, self.assertRaises(exception.ResourceExists,
nodes.Node.manage_node, self.node_controller.manage_node,
{"node_index": "1"}) {"node_index": "1"})
@mock.patch("valence.db.api.Connection.create_composed_node") @mock.patch("valence.db.api.Connection.create_composed_node")
@mock.patch("valence.common.utils.generate_uuid") @mock.patch("valence.common.utils.generate_uuid")
@mock.patch("valence.redfish.redfish.compose_node") @mock.patch("valence.podmanagers.podm_base.PodManagerBase.compose_node")
def test_compose_node(self, mock_redfish_compose_node, mock_generate_uuid, def test_compose_node(self, mock_redfish_compose_node, mock_generate_uuid,
mock_db_create_composed_node): mock_db_create_composed_node):
"""Test compose node successfully""" """Test compose node successfully"""
node_hw = node_fakes.get_test_composed_node() node_hw = node_fakes.get_test_composed_node()
node_db = {"uuid": node_hw["uuid"], node_db = {"uuid": node_hw["uuid"],
"podm_id": 'test-podm-1',
"index": node_hw["index"], "index": node_hw["index"],
"name": node_hw["name"], "name": node_hw["name"],
"uri": node_hw["resource_uri"]} "resource_uri": node_hw["resource_uri"]}
mock_redfish_compose_node.return_value = node_hw mock_redfish_compose_node.return_value = node_hw
uuid = 'ea8e2a25-2901-438d-8157-de7ffd68d051' uuid = 'ea8e2a25-2901-438d-8157-de7ffd68d051'
mock_generate_uuid.return_value = uuid mock_generate_uuid.return_value = uuid
result = nodes.Node.compose_node( result = self.node_controller.compose_node(
{"name": node_hw["name"], {"name": node_hw["name"],
"description": node_hw["description"]}) "description": node_hw["description"]})
expected = nodes.Node._show_node_brief_info(node_hw) expected = nodes.Node._show_node_brief_info(node_hw)
@ -135,7 +142,7 @@ class TestAPINodes(unittest.TestCase):
@mock.patch("valence.db.api.Connection.create_composed_node") @mock.patch("valence.db.api.Connection.create_composed_node")
@mock.patch("valence.common.utils.generate_uuid") @mock.patch("valence.common.utils.generate_uuid")
@mock.patch("valence.redfish.redfish.compose_node") @mock.patch("valence.podmanagers.podm_base.PodManagerBase.compose_node")
@mock.patch("valence.controller.flavors.get_flavor") @mock.patch("valence.controller.flavors.get_flavor")
def test_compose_node_with_flavor(self, mock_get_flavor, def test_compose_node_with_flavor(self, mock_get_flavor,
mock_redfish_compose_node, mock_redfish_compose_node,
@ -144,9 +151,10 @@ class TestAPINodes(unittest.TestCase):
"""Test node composition using a flavor for requirements""" """Test node composition using a flavor for requirements"""
node_hw = node_fakes.get_test_composed_node() node_hw = node_fakes.get_test_composed_node()
node_db = {"uuid": node_hw["uuid"], node_db = {"uuid": node_hw["uuid"],
"podm_id": 'test-podm-1',
"index": node_hw["index"], "index": node_hw["index"],
"name": node_hw["name"], "name": node_hw["name"],
"uri": node_hw["resource_uri"]} "resource_uri": node_hw["resource_uri"]}
mock_redfish_compose_node.return_value = node_hw mock_redfish_compose_node.return_value = node_hw
uuid = 'ea8e2a25-2901-438d-8157-de7ffd68d051' uuid = 'ea8e2a25-2901-438d-8157-de7ffd68d051'
@ -155,7 +163,7 @@ class TestAPINodes(unittest.TestCase):
flavor = flavor_fakes.fake_flavor() flavor = flavor_fakes.fake_flavor()
mock_get_flavor.return_value = flavor mock_get_flavor.return_value = flavor
result = nodes.Node.compose_node( result = self.node_controller.compose_node(
{"name": node_hw["name"], {"name": node_hw["name"],
"description": node_hw["description"], "description": node_hw["description"],
"flavor_id": flavor["uuid"]}) "flavor_id": flavor["uuid"]})
@ -165,43 +173,26 @@ class TestAPINodes(unittest.TestCase):
mock_db_create_composed_node.assert_called_once_with(node_db) mock_db_create_composed_node.assert_called_once_with(node_db)
mock_get_flavor.assert_called_once_with(flavor["uuid"]) mock_get_flavor.assert_called_once_with(flavor["uuid"])
@mock.patch("valence.redfish.redfish.get_node_by_id") @mock.patch("valence.podmanagers.podm_base.PodManagerBase.get_node_info")
@mock.patch("valence.db.api.Connection.get_composed_node_by_uuid") def test_get_composed_node_by_uuid(self, mock_redfish_get_node):
def test_get_composed_node_by_uuid(
self, mock_db_get_composed_node, mock_redfish_get_node):
"""Test get composed node detail""" """Test get composed node detail"""
node_hw = node_fakes.get_test_composed_node() node_hw = node_fakes.get_test_composed_node()
node_db = test_utils.get_test_composed_node_db_info() node_db = test_utils.get_test_composed_node_db_info()
mock_db_model = mock.MagicMock() self.node_controller.node = node_db
mock_db_model.as_dict.return_value = node_db
mock_db_get_composed_node.return_value = mock_db_model
mock_redfish_get_node.return_value = node_hw mock_redfish_get_node.return_value = node_hw
result = nodes.Node.get_composed_node_by_uuid("fake_uuid") result = self.node_controller.get_composed_node_by_uuid("fake_uuid")
expected = copy.deepcopy(node_hw) expected = copy.deepcopy(node_hw)
expected.update(node_db) expected.update(node_db)
self.assertEqual(expected, result) self.assertEqual(expected, result)
@mock.patch("valence.db.api.Connection.delete_composed_node") @mock.patch("valence.db.api.Connection.delete_composed_node")
@mock.patch("valence.redfish.redfish.delete_composed_node") def test_delete_composed_node(self, mock_db_delete_composed_node):
@mock.patch("valence.db.api.Connection.get_composed_node_by_uuid")
def test_delete_composed_node(
self, mock_db_get_composed_node, mock_redfish_delete_composed_node,
mock_db_delete_composed_node):
"""Test delete composed node""" """Test delete composed node"""
node_db = test_utils.get_test_composed_node_db_info() node_db = test_utils.get_test_composed_node_db_info()
self.node_controller.node = node_db
mock_db_model = mock.MagicMock() self.node_controller.delete_composed_node(node_db["uuid"])
mock_db_model.index = node_db["index"]
mock_db_get_composed_node.return_value = mock_db_model
nodes.Node.delete_composed_node(node_db["uuid"])
mock_redfish_delete_composed_node.assert_called_once_with(
node_db["index"])
mock_db_delete_composed_node.assert_called_once_with( mock_db_delete_composed_node.assert_called_once_with(
node_db["uuid"]) node_db["uuid"])
@ -220,17 +211,12 @@ class TestAPINodes(unittest.TestCase):
self.assertEqual(expected, result) self.assertEqual(expected, result)
@mock.patch("valence.redfish.redfish.node_action") @mock.patch("valence.podmanagers.podm_base.PodManagerBase.node_action")
@mock.patch("valence.db.api.Connection.get_composed_node_by_uuid") def test_node_action(self, mock_node_action):
def test_node_action(
self, mock_db_get_composed_node, mock_node_action):
"""Test reset composed node status""" """Test reset composed node status"""
action = {"Reset": {"Type": "On"}} action = {"Reset": {"Type": "On"}}
mock_db_model = mock.MagicMock() self.node_controller.node = {'index': '1', 'name': 'test-node'}
mock_db_model.index = "1" self.node_controller.node_action("fake_uuid", action)
mock_db_get_composed_node.return_value = mock_db_model
nodes.Node.node_action("fake_uuid", action)
mock_node_action.assert_called_once_with("1", action) mock_node_action.assert_called_once_with("1", action)
@mock.patch("valence.provision.driver.node_register") @mock.patch("valence.provision.driver.node_register")

View File

@ -15,6 +15,7 @@ def get_test_composed_node(**kwargs):
return { return {
'uuid': kwargs.get('uuid', 'ea8e2a25-2901-438d-8157-de7ffd68d051'), 'uuid': kwargs.get('uuid', 'ea8e2a25-2901-438d-8157-de7ffd68d051'),
'name': kwargs.get('name', 'fake_name'), 'name': kwargs.get('name', 'fake_name'),
'podm_id': kwargs.get('podm_id', '78e2a25-2901-438d-8157-de7ffd68d05'),
'description': kwargs.get('description', 'fake_description'), 'description': kwargs.get('description', 'fake_description'),
'boot_source': kwargs.get('boot_source', 'Hdd'), 'boot_source': kwargs.get('boot_source', 'Hdd'),
'health_status': kwargs.get('health_status', 'OK'), 'health_status': kwargs.get('health_status', 'OK'),

View File

@ -43,7 +43,6 @@ class TestManager(base.BaseTestCase):
@mock.patch("valence.redfish.sushy.sushy_instance.RedfishInstance") @mock.patch("valence.redfish.sushy.sushy_instance.RedfishInstance")
def test_get_podm_connection(self, redfish_mock, get_podm_mock): def test_get_podm_connection(self, redfish_mock, get_podm_mock):
get_podm_mock.return_value = podmanager_fakes.fake_podm_object() get_podm_mock.return_value = podmanager_fakes.fake_podm_object()
inst = manager.get_podm_connection("fake-id") inst = manager.get_connection("fake-id")
self.assertTrue(isinstance(inst, manager.Manager)) self.assertTrue(isinstance(inst, podm_base.PodManagerBase))
self.assertTrue(isinstance(inst.podm, podm_base.PodManagerBase))
self.assertTrue(manager.podm_connections['fake-id']) self.assertTrue(manager.podm_connections['fake-id'])

View File

@ -130,10 +130,11 @@ class TestPodmanagerApi(TestApiValidation):
self.assertEqual('Validation Error', response['title']) self.assertEqual('Validation Error', response['title'])
@mock.patch('valence.podmanagers.manager.get_connection')
class TestNodeApi(TestApiValidation): class TestNodeApi(TestApiValidation):
@mock.patch('valence.controller.nodes.Node.compose_node') @mock.patch('valence.controller.nodes.Node.compose_node')
def test_compose_request_using_properties(self, mock_compose): def test_compose_request_using_properties(self, mock_compose, mock_conn):
req = { req = {
"name": "test_request", "name": "test_request",
"podm_id": "test-podm", "podm_id": "test-podm",
@ -152,21 +153,24 @@ class TestNodeApi(TestApiValidation):
resp = self.app.post('/v1/nodes', resp = self.app.post('/v1/nodes',
content_type='application/json', content_type='application/json',
data=json.dumps(req)) data=json.dumps(req))
mock_conn.assert_called_once_with('test-podm')
self.assertEqual(http_client.OK, resp.status_code) self.assertEqual(http_client.OK, resp.status_code)
@mock.patch('valence.controller.nodes.Node.compose_node') @mock.patch('valence.controller.nodes.Node.compose_node')
def test_compose_request_using_flavor(self, mock_compose): def test_compose_request_using_flavor(self, mock_compose, mock_connection):
req = { req = {
"name": "test_request1", "name": "test_request1",
"flavor_id": "test_flavor" "flavor_id": "test_flavor",
"podm_id": "test-podm-1"
} }
mock_compose.return_value = req mock_compose.return_value = req
resp = self.app.post('/v1/nodes', resp = self.app.post('/v1/nodes',
content_type='application/json', content_type='application/json',
data=json.dumps(req)) data=json.dumps(req))
mock_connection.assert_called_once_with('test-podm-1')
self.assertEqual(http_client.OK, resp.status_code) self.assertEqual(http_client.OK, resp.status_code)
def test_compose_request_invalid_params(self): def test_compose_request_invalid_params(self, mock_conn):
req = { req = {
"name": "test_request1", "name": "test_request1",
"properties": {"invalid_key": "invalid_value"} "properties": {"invalid_key": "invalid_value"}
@ -179,7 +183,7 @@ class TestNodeApi(TestApiValidation):
self.assertEqual('Validation Error', response['title']) self.assertEqual('Validation Error', response['title'])
@mock.patch('valence.controller.nodes.Node.manage_node') @mock.patch('valence.controller.nodes.Node.manage_node')
def test_node_manage_request(self, mock_manage): def test_node_manage_request(self, mock_manage, mock_connection):
req = {"node_index": "fake-index", req = {"node_index": "fake-index",
"podm_id": "test-podm-id"} "podm_id": "test-podm-id"}
mock_manage.return_value = {"uuid": "ea8e2a25-2901-438d-8157-de7ffd", mock_manage.return_value = {"uuid": "ea8e2a25-2901-438d-8157-de7ffd",
@ -190,10 +194,11 @@ class TestNodeApi(TestApiValidation):
resp = self.app.post('/v1/nodes/manage', resp = self.app.post('/v1/nodes/manage',
content_type='application/json', content_type='application/json',
data=json.dumps(req)) data=json.dumps(req))
mock_connection.assert_called_once_with('test-podm-id')
mock_manage.assert_called_once_with(req) mock_manage.assert_called_once_with(req)
self.assertEqual(http_client.OK, resp.status_code) self.assertEqual(http_client.OK, resp.status_code)
def test_node_manage_request_invalid(self): def test_node_manage_request_invalid(self, mock_conn):
req = {"node_id": "fake-index"} req = {"node_id": "fake-index"}
resp = self.app.post('/v1/nodes/manage', resp = self.app.post('/v1/nodes/manage',
content_type='application/json', content_type='application/json',
@ -202,8 +207,9 @@ class TestNodeApi(TestApiValidation):
self.assertEqual(http_client.BAD_REQUEST, response['status']) self.assertEqual(http_client.BAD_REQUEST, response['status'])
self.assertEqual('Validation Error', response['title']) self.assertEqual('Validation Error', response['title'])
@mock.patch('valence.db.api.Connection.get_composed_node_by_uuid')
@mock.patch('valence.controller.nodes.Node.node_action') @mock.patch('valence.controller.nodes.Node.node_action')
def test_node_action_request(self, mock_action): def test_node_action_request(self, mock_action, m_node, mock_connection):
req = { req = {
"Reset": { "Reset": {
"Type": "On" "Type": "On"
@ -217,7 +223,9 @@ class TestNodeApi(TestApiValidation):
self.assertEqual(http_client.NO_CONTENT, resp.status_code) self.assertEqual(http_client.NO_CONTENT, resp.status_code)
@mock.patch('valence.controller.nodes.Node.node_action') @mock.patch('valence.controller.nodes.Node.node_action')
def test_node_action_attach_request(self, mock_action): @mock.patch('valence.db.api.Connection.get_composed_node_by_uuid')
def test_node_action_attach_request(self, mock_node, mock_action,
mock_connection):
req = { req = {
"attach": { "attach": {
"resource_id": "test-device-1" "resource_id": "test-device-1"
@ -231,7 +239,9 @@ class TestNodeApi(TestApiValidation):
self.assertEqual(http_client.NO_CONTENT, resp.status_code) self.assertEqual(http_client.NO_CONTENT, resp.status_code)
@mock.patch('valence.controller.nodes.Node.node_action') @mock.patch('valence.controller.nodes.Node.node_action')
def test_node_action_detach_request(self, mock_action): @mock.patch('valence.db.api.Connection.get_composed_node_by_uuid')
def test_node_action_detach_request(self, mock_node, mock_action,
mock_connection):
req = { req = {
"detach": { "detach": {
"resource_id": "test-device-1" "resource_id": "test-device-1"
@ -244,7 +254,8 @@ class TestNodeApi(TestApiValidation):
mock_action.assert_called_once_with('fake-node', req) mock_action.assert_called_once_with('fake-node', req)
self.assertEqual(http_client.NO_CONTENT, resp.status_code) self.assertEqual(http_client.NO_CONTENT, resp.status_code)
def test_node_action_request_invalid(self): @mock.patch('valence.db.api.Connection.get_composed_node_by_uuid')
def test_node_action_request_invalid(self, mock_node, mock_connection):
req = { req = {
"Boot": { "Boot": {
"Type": "On" "Type": "On"