Add NodeCollection class in rsd 2.3

Previously it still uses rsd 2.1 NodeCollection class in rsd 2.3,
which leads to return rsd 2.1 Node instance by mistake. So add new
NodeCollection class to fix it.

Change-Id: I1a8a77546646f935ca3263a481ef6fbb3f141f74
This commit is contained in:
Lin Yang 2018-08-16 11:33:18 -07:00
parent e5cbe55e1f
commit 06e6145e4a
5 changed files with 124 additions and 2 deletions

View File

@ -35,6 +35,16 @@ class RSDLibV2_3(v2_2.RSDLibV2_2):
'@odata.id'], required=True)
"""StorageServiceCollection path"""
def get_node_collection(self):
"""Get the NodeCollection object
:raises: MissingAttributeError, if the collection attribute is
not found
:returns: a NodeCollection object
"""
return node.NodeCollection(self._conn, self._nodes_path,
redfish_version=self.redfish_version)
def get_node(self, identity):
"""Given the identity return a Node object

View File

@ -145,3 +145,21 @@ class Node(v2_1_node.Node):
self._actions.attach_endpoint.action_info = None
if self._actions.detach_endpoint:
self._actions.detach_endpoint.action_info = None
class NodeCollection(v2_1_node.NodeCollection):
@property
def _resource_type(self):
return Node
def __init__(self, connector, path, redfish_version=None):
"""A class representing a NodeCollection
:param connector: A Connector instance
:param path: The canonical path to the Node collection
resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(NodeCollection, self).__init__(connector, path, redfish_version)

View File

@ -0,0 +1,15 @@
{
"@odata.context" : "/redfish/v1/$metadata#ComposedNodeCollection.ComposedNodeCollection",
"@odata.id" : "/redfish/v1/Nodes",
"@odata.type" : "#ComposedNodeCollection.ComposedNodeCollection",
"Name" : "Composed Node Collection",
"Members@odata.count" : 5,
"Members" : [{
"@odata.id" : "/redfish/v1/Nodes/1"
}],
"Actions" : {
"#ComposedNodeCollection.Allocate" : {
"target" : "/redfish/v1/Nodes/Actions/Allocate"
}
}
}

View File

@ -14,12 +14,14 @@
# under the License.
import json
import jsonschema
import mock
import testtools
from sushy import exceptions
from rsd_lib.resources.v2_3.node import node
from rsd_lib.tests.unit.fakes import request_fakes
class NodeTestCase(testtools.TestCase):
@ -200,3 +202,81 @@ class NodeTestCase(testtools.TestCase):
self.assertIsNone(self.node_inst._actions.attach_endpoint.action_info)
self.assertIsNone(self.node_inst._actions.detach_endpoint.action_info)
class NodeCollectionTestCase(testtools.TestCase):
def setUp(self):
super(NodeCollectionTestCase, self).setUp()
self.conn = mock.Mock()
with open('rsd_lib/tests/unit/json_samples/v2_3/node_collection.json',
'r') as f:
self.conn.get.return_value = request_fakes.fake_request_get(
json.loads(f.read()))
self.conn.post.return_value = request_fakes.fake_request_post(
None, headers={"Location": "https://localhost:8443/"
"redfish/v1/Nodes/1"})
self.node_col = node.NodeCollection(
self.conn, '/redfish/v1/Nodes', redfish_version='1.0.2')
def test__parse_attributes(self):
self.node_col._parse_attributes()
self.assertEqual('1.0.2', self.node_col.redfish_version)
self.assertEqual('Composed Node Collection', self.node_col.name)
self.assertEqual(('/redfish/v1/Nodes/1',),
self.node_col.members_identities)
@mock.patch.object(node, 'Node', autospec=True)
def test_get_member(self, mock_node):
self.node_col.get_member('/redfish/v1/Nodes/1')
mock_node.assert_called_once_with(
self.node_col._conn, '/redfish/v1/Nodes/1',
redfish_version=self.node_col.redfish_version)
@mock.patch.object(node, 'Node', autospec=True)
def test_get_members(self, mock_node):
members = self.node_col.get_members()
mock_node.assert_called_once_with(
self.node_col._conn, '/redfish/v1/Nodes/1',
redfish_version=self.node_col.redfish_version)
self.assertIsInstance(members, list)
self.assertEqual(1, len(members))
def test__get_compose_action_element(self):
value = self.node_col._get_compose_action_element()
self.assertEqual('/redfish/v1/Nodes/Actions/Allocate',
value.target_uri)
def test_compose_node_no_reqs(self):
result = self.node_col.compose_node()
self.node_col._conn.post.assert_called_once_with(
'/redfish/v1/Nodes/Actions/Allocate', data={})
self.assertEqual(result, '/redfish/v1/Nodes/1')
def test_compose_node_reqs(self):
reqs = {
'Name': 'test',
'Description': 'this is a test node',
'Processors': [{
'TotalCores': 4
}],
'Memory': [{
'CapacityMiB': 8000
}],
'TotalSystemCoreCount': 8,
'TotalSystemMemoryMiB': 16000
}
result = self.node_col.compose_node(
name='test', description='this is a test node',
processor_req=[{'TotalCores': 4}],
memory_req=[{'CapacityMiB': 8000}],
total_system_core_req=8,
total_system_memory_req=16000)
self.node_col._conn.post.assert_called_once_with(
'/redfish/v1/Nodes/Actions/Allocate', data=reqs)
self.assertEqual(result, '/redfish/v1/Nodes/1')
def test_compose_node_invalid_reqs(self):
self.assertRaises(jsonschema.exceptions.ValidationError,
self.node_col.compose_node,
processor_req='invalid')

View File

@ -21,7 +21,6 @@ from rsd_lib.resources.v2_1.chassis import chassis as v2_1_chassis
from rsd_lib.resources.v2_1.ethernet_switch import ethernet_switch \
as v2_1_ethernet_switch
from rsd_lib.resources.v2_1.manager import manager as v2_1_manager
from rsd_lib.resources.v2_1.node import node as v2_1_node
from rsd_lib.resources.v2_2.system import system as v2_2_system
from rsd_lib.resources import v2_3
from rsd_lib.resources.v2_3.fabric import fabric as v2_3_fabric
@ -65,7 +64,7 @@ class RSDLibV2_3TestCase(testtools.TestCase):
self.rsd._conn, 'fake-system-id',
redfish_version=self.rsd.redfish_version)
@mock.patch.object(v2_1_node, 'NodeCollection', autospec=True)
@mock.patch.object(v2_3_node, 'NodeCollection', autospec=True)
def test_get_node_collection(self, mock_node_collection):
self.rsd.get_node_collection()
mock_node_collection.assert_called_once_with(