Change OEM extensions architecture

This patch radically changes OEM extensions architecture in a
backward-incompatible manner. /o\

The rationale is that, prior to this change, it was impossible to
model non-leaf subresources in OEM subtree such as `Links` or
`Actions`. The reason is that OEM objects were lacking BMC connection
context to doing anything beyond just sitting on the parent resource
JSON they were once given.

Technically, this change rebases originally base
`OEMExtensionResourceBase` class on top of universal `ResourceBase`
overriding its JSON parsing logic. That gives all the benefits and
features of `ResourceBase` implementation, including BMC connection
context, message registries etc.

The other conceptual (and breaking!) change is that the OEM extension
should now expose a callable that returns `OEMResourceBase` class, as
opposed to class instance as it used to be. Besides technical reasons
(preserving base class constructor signature), it seems that decoupling
implementation loader from initialization would give us more
flexibility going forward (e.g. sushy could sense what's being
exposed and initialize it differently).

Change-Id: I6c981bc1b2524d0a39a09ed8f0479b06045a1c4e
Story: 2006471
Task: 36402
This commit is contained in:
Ilya Etingof 2019-08-15 15:01:28 +02:00
parent e97952c32f
commit e03caca38f
36 changed files with 318 additions and 253 deletions

View File

@ -0,0 +1,11 @@
---
upgrade:
- |
OEM resource class hierarchy has been redesigned to allow for non-terminal
sub-resources (e.g. Links) to be handled within OEM resource model. As a
consequence, backward compatibility with previously existing OEM extension
framework (anything based on ``OEMExtensionResourceBase`` class) is not
preserved. User OEM code migration would involve switching from
``OEMExtensionResourceBase`` to ``OEMResourceBase`` (note ``__init__``
call signature change) and replacing ``OEMField``-based classes with their
generic sushy ``Field`` counterparts.

View File

@ -25,7 +25,7 @@ packages =
[entry_points]
sushy.resources.system.oems =
contoso = sushy.resources.oem.fake:FakeOEMSystemExtension
contoso = sushy.resources.oem.fake:get_extension
[build_sphinx]

View File

@ -156,9 +156,15 @@ class Sushy(base.ResourceBase):
'with %s: %s', self._base_url, ex)
self._auth = None
def _parse_attributes(self):
super(Sushy, self)._parse_attributes()
self.redfish_version = self.json.get('RedfishVersion')
def _parse_attributes(self, json_doc):
"""Parse the attributes of a resource.
Parsed JSON fields are set to `self` as declared in the class.
:param json_doc: parsed JSON document in form of Python types
"""
super(Sushy, self)._parse_attributes(json_doc)
self.redfish_version = json_doc.get('RedfishVersion')
def get_system_collection(self):
"""Get the SystemCollection object

View File

@ -431,11 +431,16 @@ class ResourceBase(object):
self.refresh()
def _parse_attributes(self):
"""Parse the attributes of a resource."""
def _parse_attributes(self, json_doc):
"""Parse the attributes of a resource.
Parsed JSON fields are set to `self` as declared in the class.
:param json_doc: parsed JSON document in form of Python types
"""
for attr, field in _collect_fields(self):
# Hide the Field object behind the real value
setattr(self, attr, field._load(self.json, self))
setattr(self, attr, field._load(json_doc, self))
def refresh(self, force=True):
"""Refresh the resource
@ -464,7 +469,7 @@ class ResourceBase(object):
LOG.debug('Received representation of %(type)s %(path)s: %(json)s',
{'type': self.__class__.__name__,
'path': self._path, 'json': self._json})
self._parse_attributes()
self._parse_attributes(self._json)
self._do_refresh(force)
# Mark it fresh
@ -516,6 +521,13 @@ class ResourceBase(object):
def path(self):
return self._path
def clone_resource(self, new_resource, path=''):
"""Instantiate given resource using existing BMC connection context"""
return new_resource(
self._conn, path or self.path,
redfish_version=self.redfish_version,
reader=self._reader)
@property
def resource_name(self):
return utils.camelcase_to_underscore_joined(self.__class__.__name__)

View File

@ -10,120 +10,64 @@
# License for the specific language governing permissions and limitations
# under the License.
import abc
import logging
import six
from sushy.resources import base
from sushy.resources import common
LOG = logging.getLogger(__name__)
class OEMField(base.Field):
"""Marker class for OEM specific fields."""
class OEMResourceBase(base.ResourceBase):
def __init__(self,
connector,
path='',
redfish_version=None,
registries=None,
reader=None):
"""Class representing an OEM vendor extension
def _collect_oem_fields(resource):
"""Collect OEM fields from resource.
:param resource: OEMExtensionResourceBase instance.
:returns: generator of tuples (key, field)
"""
for attr in dir(resource.__class__):
field = getattr(resource.__class__, attr)
if isinstance(field, OEMField):
yield (attr, field)
def _collect_base_fields(resource):
"""Collect base fields from resource.
:param resource: OEMExtensionResourceBase instance.
:returns: generator of tuples (key, field)
"""
for attr in dir(resource.__class__):
field = getattr(resource.__class__, attr)
if not isinstance(field, OEMField) and isinstance(field, base.Field):
yield (attr, field)
@six.add_metaclass(abc.ABCMeta)
class OEMCompositeField(base.CompositeField, OEMField):
"""CompositeField for OEM fields."""
class OEMListField(base.ListField, OEMField):
"""ListField for OEM fields."""
class OEMDictionaryField(base.DictionaryField, OEMField):
"""DictionaryField for OEM fields."""
class OEMMappedField(base.MappedField, OEMField):
"""MappedField for OEM fields."""
class OEMActionsField(OEMCompositeField):
"""OEM Actions fields"""
@six.add_metaclass(abc.ABCMeta)
class OEMActionField(common.ActionField, OEMField):
"""OEM Actions fields."""
@six.add_metaclass(abc.ABCMeta)
class OEMExtensionResourceBase(object):
def __init__(self, resource, oem_property_name, *args, **kwargs):
"""A class representing the base of any resource OEM extension
Invokes the ``refresh()`` method for the first time from here
(constructor).
:param resource: The parent Sushy resource instance
:param oem_property_name: the unique OEM identifier string
:param connector: A Connector instance
:param path: sub-URI path to the resource.
:param redfish_version: The version of Redfish. Used to construct
the object according to schema of the given version.
:param registries: Dict of Redfish Message Registry objects to be
used in any resource that needs registries to parse messages
"""
if not resource:
raise ValueError('"resource" argument cannot be void')
if not isinstance(resource, base.ResourceBase):
raise TypeError('"resource" argument must be a ResourceBase')
self._parent_resource = None
self._vendor_id = None
self.core_resource = resource
self.oem_property_name = oem_property_name
self.refresh()
super(OEMResourceBase, self).__init__(
connector, path, redfish_version, registries, reader)
def _parse_oem_attributes(self):
"""Parse the OEM extension attributes of a resource."""
oem_json_body = (self.core_resource.json.get('Oem').
get(self.oem_property_name))
def set_parent_resource(self, parent_resource, vendor_id):
self._parent_resource = parent_resource
self._vendor_id = vendor_id
# NOTE(etingof): this is required to pull OEM subtree
self.invalidate(force_refresh=True)
return self
oem_actions = {
'Actions': self.core_resource.json.get(
def _parse_attributes(self, json_doc):
"""Parse the attributes of a resource.
Parsed JSON fields are set to `self` as declared in the class.
:param json_doc: parsed JSON document in form of Python types
"""
oem_json = json_doc.get(
'Oem', {}).get(self._vendor_id, {})
# NOTE(etingof): temporary copy Actions into Oem subtree for parsing
# all fields at once
oem_json = oem_json.copy()
oem_actions_json = {
'Actions': json_doc.get(
'Actions', {}).get('Oem', {})
}
for attr, field in _collect_oem_fields(self):
json_body = (oem_actions
if isinstance(field, OEMActionsField)
else oem_json_body)
oem_json.update(oem_actions_json)
value = field._load(json_body, self)
# Hide the Field object behind the real value
setattr(self, attr, value)
for attr, field in _collect_base_fields(self):
# Hide the Field object behind the real value
setattr(self, attr, field._load(self.core_resource.json, self))
def refresh(self):
"""Refresh the attributes of the resource extension.
Freshly parses the resource OEM attributes via
``_parse_oem_attributes()`` method.
"""
self._parse_oem_attributes()
super(OEMResourceBase, self)._parse_attributes(oem_json)

View File

@ -86,22 +86,27 @@ def _get_extension_manager_of_resource(resource_name):
@utils.synchronized
def _get_resource_vendor_extension_obj(extension, resource, *args, **kwds):
def _get_resource_vendor_extension_obj(extension, resource, vendor):
"""Get the object returned by extension's plugin() method.
:param extension: stevedore Extension
:param resource: The Sushy resource instance
:param *args, **kwds: constructor arguments to plugin() method.
:param vendor: This is the OEM vendor string which is the vendor-specific
extensibility identifier. Examples are: 'Contoso', 'Hpe'. As a matter
of fact the lowercase of this string will be the plugin entry point
name.
:returns: The object returned by ``plugin(*args, **kwds)`` of extension.
"""
if extension.obj is None:
extension.obj = extension.plugin(resource, *args, **kwds)
oem_resource = extension.plugin()
extension.obj = resource.clone_resource(
oem_resource).set_parent_resource(resource, vendor)
return extension.obj
def get_resource_extension_by_vendor(
resource_name, vendor, resource, *args, **kwds):
resource_name, vendor, resource):
"""Helper method to get Resource specific OEM extension object for vendor
:param resource_name: The underscore joined name of the resource e.g.
@ -128,5 +133,5 @@ def get_resource_extension_by_vendor(
if resource_vendor_extn.obj is None:
return _get_resource_vendor_extension_obj(
resource_vendor_extn, resource, *args, **kwds)
resource_vendor_extn, resource, vendor)
return resource_vendor_extn.obj

View File

@ -13,33 +13,30 @@
import logging
from sushy.resources import base
from sushy.resources import common
from sushy.resources.oem import base as oem_base
LOG = logging.getLogger(__name__)
class ProductionLocationField(oem_base.OEMCompositeField):
class ProductionLocationField(base.CompositeField):
facility_name = base.Field('FacilityName')
country = base.Field('Country')
class ContosoActionsField(oem_base.OEMActionsField):
reset = oem_base.OEMActionField('#Contoso.Reset')
class ContosoActionsField(base.CompositeField):
reset = common.ResetActionField('#Contoso.Reset')
class FakeOEMSystemExtension(oem_base.OEMExtensionResourceBase):
class FakeOEMSystemExtension(oem_base.OEMResourceBase):
data_type = oem_base.OEMField('@odata.type')
data_type = base.Field('@odata.type')
production_location = ProductionLocationField('ProductionLocation')
_actions = ContosoActionsField('Actions')
def __init__(self, resource, *args, **kwargs):
"""A class representing ComputerSystem OEM extension for Contoso
:param resource: The parent System resource instance
"""
super(FakeOEMSystemExtension, self).__init__(
resource, 'Contoso', *args, **kwargs)
def get_reset_system_path(self):
return self._actions.reset.target_uri
def get_extension(*args, **kwargs):
return FakeOEMSystemExtension

View File

@ -30,14 +30,16 @@ class ChassisTestCase(base.TestCase):
super(ChassisTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/chassis.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.chassis = chassis.Chassis(self.conn, '/redfish/v1/Chassis/Blade1',
redfish_version='1.8.0')
def test__parse_attributes(self):
# | WHEN |
self.chassis._parse_attributes()
self.chassis._parse_attributes(self.json_doc)
# | THEN |
self.assertEqual('1.8.0', self.chassis.redfish_version)
self.assertEqual('Blade1', self.chassis.identity)

View File

@ -26,14 +26,16 @@ class PowerTestCase(base.TestCase):
super(PowerTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/power.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.power = power.Power(
self.conn, '/redfish/v1/Chassis/MultiBladeEnc1/Power',
redfish_version='1.5.0')
def test__parse_attributes(self):
self.power._parse_attributes()
self.power._parse_attributes(self.json_doc)
self.assertEqual('1.5.0', self.power.redfish_version)
self.assertEqual('Power', self.power.identity)
self.assertEqual('Quad Blade Chassis Power', self.power.name)

View File

@ -26,14 +26,16 @@ class ThermalTestCase(base.TestCase):
super(ThermalTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/thermal.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.thermal = thermal.Thermal(
self.conn, '/redfish/v1/Chassis/Blade1/Thermal',
redfish_version='1.5.0')
def test__parse_attributes(self):
self.thermal._parse_attributes()
self.thermal._parse_attributes(self.json_doc)
self.assertEqual('1.5.0', self.thermal.redfish_version)
self.assertEqual('Thermal', self.thermal.identity)
self.assertEqual('Blade Thermal', self.thermal.name)

View File

@ -26,7 +26,9 @@ class CompositionServiceTestCase(base.TestCase):
self.conn = mock.Mock()
with open(
'sushy/tests/unit/json_samples/compositionservice.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.comp_ser = compositionservice.CompositionService(
self.conn,
@ -34,7 +36,7 @@ class CompositionServiceTestCase(base.TestCase):
redfish_version='1.0.2')
def test__parse_attributes(self):
self.comp_ser._parse_attributes()
self.comp_ser._parse_attributes(self.json_doc)
self.assertFalse(self.comp_ser.allow_overprovisioning)
self.assertTrue(self.comp_ser.allow_zone_affinity)
self.assertTrue(self.comp_ser.description, 'CompositionService1')

View File

@ -28,7 +28,9 @@ class ResourceBlockTestCase(base.TestCase):
super(ResourceBlockTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/resourceblock.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.res_block = resourceblock.ResourceBlock(
self.conn,
@ -36,7 +38,7 @@ class ResourceBlockTestCase(base.TestCase):
redfish_version='1.0.2')
def test__parse_attributes(self):
self.res_block._parse_attributes()
self.res_block._parse_attributes(self.json_doc)
self.assertEqual(
res_block_cons.COMPOSITION_STATE_COMPOSED,
self.res_block.composition_status.composition_state)
@ -63,7 +65,7 @@ class ResourceBlockTestCase(base.TestCase):
self.res_block.json.pop('Id')
self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Id',
self.res_block._parse_attributes)
self.res_block._parse_attributes, self.json_doc)
class ResourceBlockCollectionTestCase(base.TestCase):
@ -73,7 +75,9 @@ class ResourceBlockCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'resourceblock_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.res_block_col = resourceblock.ResourceBlockCollection(
self.conn, '/redfish/v1/CompositionService/ResourceBlocks',
@ -81,7 +85,7 @@ class ResourceBlockCollectionTestCase(base.TestCase):
def test__parse_attributes(self):
path = '/redfish/v1/CompositionService/ResourceBlocks/ComputeBlock1'
self.res_block_col._parse_attributes()
self.res_block_col._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.res_block_col.redfish_version)
self.assertEqual(
'Resource Block Collection',

View File

@ -26,7 +26,9 @@ class ResourceZoneTestCase(base.TestCase):
super(ResourceZoneTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/resourcezone.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.res_zone = resourcezone.ResourceZone(
self.conn,
@ -34,7 +36,7 @@ class ResourceZoneTestCase(base.TestCase):
redfish_version='1.0.2')
def test__parse_attributes(self):
self.res_zone._parse_attributes()
self.res_zone._parse_attributes(self.json_doc)
self.assertEqual('ResourceZone1', self.res_zone.description)
self.assertEqual('1', self.res_zone.identity)
self.assertEqual('Resource Zone 1', self.res_zone.name)
@ -51,7 +53,7 @@ class ResourceZoneTestCase(base.TestCase):
self.res_zone.json.pop('Id')
self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Id',
self.res_zone._parse_attributes)
self.res_zone._parse_attributes, self.json_doc)
class ResourceZoneCollectionTestCase(base.TestCase):
@ -61,7 +63,9 @@ class ResourceZoneCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'resourcezone_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.res_zone_col = resourcezone.ResourceZoneCollection(
self.conn, '/redfish/v1/CompositionService/ResourceZones',
@ -69,7 +73,7 @@ class ResourceZoneCollectionTestCase(base.TestCase):
def test__parse_attributes(self):
path = '/redfish/v1/CompositionService/ResourceZones/1'
self.res_zone_col._parse_attributes()
self.res_zone_col._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.res_zone_col.redfish_version)
self.assertEqual('Resource Zone Collection', self.res_zone_col.name)
self.assertEqual((path,), self.res_zone_col.members_identities)

View File

@ -26,13 +26,16 @@ class EndpointTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'endpoint.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.fab_endpoint = endpoint.Endpoint(
self.conn, '/redfish/v1/Fabrics/SAS/Endpoints/Drive1',
redfish_version='1.0.2')
def test__parse_atrtributes(self):
self.fab_endpoint._parse_attributes()
self.fab_endpoint._parse_attributes(self.json_doc)
self.assertEqual('Drive1', self.fab_endpoint.identity)
self.assertEqual('SAS Drive', self.fab_endpoint.name)
self.assertEqual(sushy.PROTOCOL_TYPE_SAS,

View File

@ -28,14 +28,16 @@ class FabricTestCase(base.TestCase):
super(FabricTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/fabric.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.fabric = fabric.Fabric(self.conn, '/redfish/v1/Fabrics/SAS',
redfish_version='1.0.3')
def test__parse_attributes(self):
# | WHEN |
self.fabric._parse_attributes()
self.fabric._parse_attributes(self.json_doc)
# | THEN |
self.assertEqual('1.0.3', self.fabric.redfish_version)
self.assertEqual('SAS', self.fabric.identity)

View File

@ -29,14 +29,16 @@ class ManagerTestCase(base.TestCase):
super(ManagerTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/manager.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.manager = manager.Manager(self.conn, '/redfish/v1/Managers/BMC',
redfish_version='1.0.2')
def test__parse_attributes(self):
# | WHEN |
self.manager._parse_attributes()
self.manager._parse_attributes(self.json_doc)
# | THEN |
self.assertEqual('1.0.2', self.manager.redfish_version)
self.assertEqual('1.00', self.manager.firmware_version)

View File

@ -30,13 +30,16 @@ class VirtualMediaTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'virtual_media.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.sys_virtual_media = virtual_media.VirtualMedia(
self.conn, '/redfish/v1/Managers/BMC/VirtualMedia/Floppy1',
redfish_version='1.0.2')
def test__parse_atrtributes(self):
self.sys_virtual_media._parse_attributes()
self.sys_virtual_media._parse_attributes(self.json_doc)
self.assertEqual('Virtual Removable Media',
self.sys_virtual_media.name)
self.assertEqual('Floppy1', self.sys_virtual_media.identity)

View File

@ -20,18 +20,12 @@ from sushy.resources.oem import common as oem_common
from sushy.tests.unit import base
class ContosoResourceOEMExtension(oem_base.OEMExtensionResourceBase):
def __init__(self, resource, *args, **kwargs):
super(ContosoResourceOEMExtension, self).__init__(
resource, 'Contoso', *args, **kwargs)
class ContosoResourceOEMExtension(oem_base.OEMResourceBase):
pass
class FauxResourceOEMExtension(oem_base.OEMExtensionResourceBase):
def __init__(self, resource, *args, **kwargs):
super(FauxResourceOEMExtension, self).__init__(
resource, 'Faux', *args, **kwargs)
class FauxResourceOEMExtension(oem_base.OEMResourceBase):
pass
class ResourceOEMCommonMethodsTestCase(base.TestCase):
@ -50,17 +44,18 @@ class ResourceOEMCommonMethodsTestCase(base.TestCase):
contoso_ep.module_name = __name__
contoso_ep.attrs = ['ContosoResourceOEMExtension']
self.contoso_extn = stevedore.extension.Extension(
'contoso', contoso_ep, ContosoResourceOEMExtension, None)
'contoso', contoso_ep, lambda: ContosoResourceOEMExtension, None)
self.contoso_extn_dup = stevedore.extension.Extension(
'contoso_dup', contoso_ep, ContosoResourceOEMExtension, None)
'contoso_dup', contoso_ep,
lambda: ContosoResourceOEMExtension, None)
faux_ep = mock.Mock()
faux_ep.module_name = __name__
faux_ep.attrs = ['FauxResourceOEMExtension']
self.faux_extn = stevedore.extension.Extension(
'faux', faux_ep, FauxResourceOEMExtension, None)
'faux', faux_ep, lambda: FauxResourceOEMExtension, None)
self.faux_extn_dup = stevedore.extension.Extension(
'faux_dup', faux_ep, FauxResourceOEMExtension, None)
'faux_dup', faux_ep, lambda: FauxResourceOEMExtension, None)
self.fake_ext_mgr = (
stevedore.extension.ExtensionManager.make_test_instance(
@ -124,41 +119,54 @@ class ResourceOEMCommonMethodsTestCase(base.TestCase):
extension_mock = mock.MagicMock()
extension_mock.obj = None
mock_oem_resource = extension_mock.plugin.return_value
result = oem_common._get_resource_vendor_extension_obj(
extension_mock, resource_instance_mock)
self.assertEqual(extension_mock.plugin.return_value, result)
extension_mock.plugin.assert_called_once_with(resource_instance_mock)
extension_mock, resource_instance_mock, 'fish-n-chips')
mock_clone_resource = resource_instance_mock.clone_resource
mock_clone_resource.assert_called_once_with(mock_oem_resource)
mock_ext = mock_clone_resource.return_value
mock_ext.set_parent_resource.assert_called_once_with(
resource_instance_mock, 'fish-n-chips')
mock_ext = mock_ext.set_parent_resource.return_value
self.assertEqual(result, mock_ext)
extension_mock.reset_mock()
# extension_mock.obj is not None anymore
result = oem_common._get_resource_vendor_extension_obj(
extension_mock, resource_instance_mock)
self.assertEqual(extension_mock.plugin.return_value, result)
oem_common._get_resource_vendor_extension_obj(
extension_mock, resource_instance_mock, 'fish-n-chips')
self.assertFalse(extension_mock.plugin.called)
@mock.patch.object(stevedore, 'ExtensionManager', autospec=True)
def test_get_resource_extension_by_vendor(self, ExtensionManager_mock):
resource_instance_mock = mock.Mock(spec=res_base.ResourceBase)
oem_resource_mock = mock.Mock()
oem_resource_mock.set_parent_resource = lambda *x: oem_resource_mock
resource_instance_mock = mock.Mock()
resource_instance_mock.clone_resource = lambda *x: oem_resource_mock
ExtensionManager_mock.side_effect = [self.fake_ext_mgr,
self.fake_ext_mgr2]
result = oem_common.get_resource_extension_by_vendor(
'system', 'Faux', resource_instance_mock)
self.assertIsInstance(result, FauxResourceOEMExtension)
self.assertEqual(result, oem_resource_mock)
ExtensionManager_mock.assert_called_once_with(
'sushy.resources.system.oems', propagate_map_exceptions=True,
on_load_failure_callback=oem_common._raise)
ExtensionManager_mock.reset_mock()
oem_resource_mock.obj = None
result = oem_common.get_resource_extension_by_vendor(
'system', 'Contoso', resource_instance_mock)
self.assertIsInstance(result, ContosoResourceOEMExtension)
self.assertEqual(result, oem_resource_mock)
self.assertFalse(ExtensionManager_mock.called)
ExtensionManager_mock.reset_mock()
result = oem_common.get_resource_extension_by_vendor(
'manager', 'Faux_dup', resource_instance_mock)
self.assertIsInstance(result, FauxResourceOEMExtension)
self.assertEqual(result, oem_resource_mock)
ExtensionManager_mock.assert_called_once_with(
'sushy.resources.manager.oems', propagate_map_exceptions=True,
on_load_failure_callback=oem_common._raise)
@ -166,7 +174,7 @@ class ResourceOEMCommonMethodsTestCase(base.TestCase):
result = oem_common.get_resource_extension_by_vendor(
'manager', 'Contoso_dup', resource_instance_mock)
self.assertIsInstance(result, ContosoResourceOEMExtension)
self.assertEqual(result, oem_resource_mock)
self.assertFalse(ExtensionManager_mock.called)
ExtensionManager_mock.reset_mock()

View File

@ -30,7 +30,11 @@ class FakeOEMSystemExtensionTestCase(base.TestCase):
self.sys_instance = system.System(
self.conn, '/redfish/v1/Systems/437XR1138R2',
redfish_version='1.0.2')
self.fake_sys_oem_extn = fake.FakeOEMSystemExtension(self.sys_instance)
self.fake_sys_oem_extn = fake.FakeOEMSystemExtension(
self.conn, '',
redfish_version='1.0.2')
self.fake_sys_oem_extn = self.fake_sys_oem_extn.set_parent_resource(
self.sys_instance, 'Contoso')
def test__parse_oem_attributes(self):
self.assertEqual('http://Contoso.com/Schema#Contoso.ComputerSystem',

View File

@ -29,14 +29,16 @@ class MessageRegistryTestCase(base.TestCase):
super(MessageRegistryTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/message_registry.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.registry = message_registry.MessageRegistry(
self.conn, '/redfish/v1/Registries/Test',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.registry._parse_attributes()
self.registry._parse_attributes(self.json_doc)
self.assertEqual('Test.1.1.1', self.registry.identity)
self.assertEqual('Test Message Registry', self.registry.name)
self.assertEqual('en', self.registry.language)
@ -65,7 +67,7 @@ class MessageRegistryTestCase(base.TestCase):
['unknown_type']
self.assertRaisesRegex(KeyError,
'unknown_type',
self.registry._parse_attributes)
self.registry._parse_attributes, self.json_doc)
def test_parse_message(self):
conn = mock.Mock()

View File

@ -27,14 +27,16 @@ class MessageRegistryFileTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'message_registry_file.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.reg_file = message_registry_file.MessageRegistryFile(
self.conn, '/redfish/v1/Registries/Test',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.reg_file._parse_attributes()
self.reg_file._parse_attributes(self.json_doc)
self.assertEqual('Test', self.reg_file.identity)
self.assertEqual('Test Message Registry File', self.reg_file.name)
self.assertEqual('Message Registry file for testing',
@ -197,14 +199,17 @@ class MessageRegistryFileCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'message_registry_file_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.reg_file_col =\
message_registry_file.MessageRegistryFileCollection(
self.conn, '/redfish/v1/Registries',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.reg_file_col._parse_attributes()
self.reg_file_col._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.reg_file_col.redfish_version)
self.assertEqual('Message Registry Test Collection',
self.reg_file_col.name)

View File

@ -28,10 +28,10 @@ class SessionTestCase(base.TestCase):
self.conn = mock.Mock()
self.auth = mock.Mock()
with open('sushy/tests/unit/json_samples/session.json') as f:
sample_json = json.load(f)
self.conn.get.return_value.json.return_value = sample_json
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.auth._session_key = 'fake_x_auth_token'
self.auth._session_uri = sample_json['@odata.id']
self.auth._session_uri = self.json_doc['@odata.id']
self.conn._auth = self.auth
self.sess_inst = session.Session(
@ -39,7 +39,7 @@ class SessionTestCase(base.TestCase):
redfish_version='1.0.2')
def test__parse_attributes(self):
self.sess_inst._parse_attributes()
self.sess_inst._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.sess_inst.redfish_version)
self.assertEqual('1234567890ABCDEF', self.sess_inst.identity)
self.assertEqual('User Session', self.sess_inst.name)
@ -50,7 +50,7 @@ class SessionTestCase(base.TestCase):
self.sess_inst.json.pop('Id')
self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Id',
self.sess_inst._parse_attributes)
self.sess_inst._parse_attributes, self.json_doc)
def test_session_close(self):
session_key = self.sess_inst._conn._auth._session_key
@ -68,7 +68,9 @@ class SessionCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'session_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.sess_col = session.SessionCollection(
self.conn, '/redfish/v1/SessionService/Sessions',
@ -76,7 +78,7 @@ class SessionCollectionTestCase(base.TestCase):
def test__parse_attributes(self):
path = '/redfish/v1/SessionService/Sessions/104f9d68f58abb85'
self.sess_col._parse_attributes()
self.sess_col._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.sess_col.redfish_version)
self.assertEqual('Session Collection', self.sess_col.name)
self.assertEqual((path,), self.sess_col.members_identities)

View File

@ -29,7 +29,9 @@ class SessionServiceTestCase(base.TestCase):
super(SessionServiceTestCase, self).setUp()
self.conn = mock.MagicMock()
with open('sushy/tests/unit/json_samples/session_service.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.sess_serv_inst = sessionservice.SessionService(
self.conn, '/redfish/v1/SessionService',
@ -46,7 +48,7 @@ class SessionServiceTestCase(base.TestCase):
self.assertTrue(mock_LOG.warning.called)
def test__parse_attributes(self):
self.sess_serv_inst._parse_attributes()
self.sess_serv_inst._parse_attributes(self.json_doc)
exp_path = '/redfish/v1/SessionService'
self.assertEqual('1.0.2', self.sess_serv_inst.redfish_version)
self.assertEqual('SessionService', self.sess_serv_inst.identity)
@ -58,7 +60,7 @@ class SessionServiceTestCase(base.TestCase):
self.sess_serv_inst.json.pop('SessionTimeout')
self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute SessionTimeout',
self.sess_serv_inst._parse_attributes())
self.sess_serv_inst._parse_attributes(self.json_doc))
def test__get_sessions_collection_path(self):
self.sess_serv_inst.json.pop('Sessions')

View File

@ -26,7 +26,9 @@ class DriveTestCase(base.TestCase):
super(DriveTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/drive.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.stor_drive = drive.Drive(
self.conn,
@ -34,7 +36,7 @@ class DriveTestCase(base.TestCase):
redfish_version='1.0.2')
def test__parse_attributes(self):
self.stor_drive._parse_attributes()
self.stor_drive._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.stor_drive.redfish_version)
self.assertEqual('32ADF365C6C1B7BD', self.stor_drive.identity)
self.assertEqual('Drive Sample', self.stor_drive.name)

View File

@ -41,14 +41,16 @@ class StorageTestCase(base.TestCase):
super(StorageTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/storage.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.storage = storage.Storage(
self.conn, '/redfish/v1/Systems/437XR1138R2/Storage/1',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.storage._parse_attributes()
self.storage._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.storage.redfish_version)
self.assertEqual('1', self.storage.identity)
self.assertEqual('Local Storage Controller', self.storage.name)
@ -233,13 +235,16 @@ class StorageCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'storage_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.stor_col = storage.StorageCollection(
self.conn, '/redfish/v1/Systems/437XR1138R2/Storage',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.stor_col._parse_attributes()
self.stor_col._parse_attributes(self.json_doc)
self.assertEqual((
'/redfish/v1/Systems/437XR1138R2/Storage/1',),
self.stor_col.members_identities)

View File

@ -27,14 +27,16 @@ class VolumeTestCase(base.TestCase):
super(VolumeTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/volume.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.stor_volume = volume.Volume(
self.conn, '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.stor_volume._parse_attributes()
self.stor_volume._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.stor_volume.redfish_version)
self.assertEqual('1', self.stor_volume.identity)
self.assertEqual('Virtual Disk 1', self.stor_volume.name)
@ -84,14 +86,17 @@ class VolumeCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'volume_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.stor_vol_col = volume.VolumeCollection(
self.conn, '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes',
redfish_version='1.0.2')
self.stor_vol_col.refresh = mock.Mock()
def test__parse_attributes(self):
self.stor_vol_col._parse_attributes()
self.stor_vol_col._parse_attributes(self.json_doc)
self.assertEqual((
'/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1',
'/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/2',

View File

@ -31,14 +31,14 @@ class BiosTestCase(base.TestCase):
super(BiosTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/bios.json') as f:
bios_json = json.load(f)
self.bios_json = json.load(f)
with open('sushy/tests/unit/json_samples/bios_settings.json') as f:
bios_settings_json = json.load(f)
self.bios_settings_json = json.load(f)
self.conn.get.return_value.json.side_effect = [
bios_json,
bios_settings_json,
bios_settings_json]
self.bios_json,
self.bios_settings_json,
self.bios_settings_json]
conn = mock.Mock()
with open('sushy/tests/unit/json_samples/message_registry.json') as f:
@ -53,7 +53,7 @@ class BiosTestCase(base.TestCase):
redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_bios._parse_attributes()
self.sys_bios._parse_attributes(self.bios_json)
self.assertEqual('1.0.2', self.sys_bios.redfish_version)
self.assertEqual('BIOS', self.sys_bios.identity)
self.assertEqual('BIOS Configuration Current Settings',
@ -151,7 +151,7 @@ class BiosTestCase(base.TestCase):
self.assertRaisesRegex(
exceptions.MissingAttributeError,
'attribute Actions/#Bios.ResetBios/target',
self.sys_bios._parse_attributes)
self.sys_bios._parse_attributes, self.bios_json)
def test_reset_bios(self):
self.sys_bios.reset_bios()
@ -202,7 +202,7 @@ class BiosTestCase(base.TestCase):
self.assertRaisesRegex(
exceptions.MissingAttributeError,
'attribute Actions/#Bios.ChangePassword/target',
self.sys_bios._parse_attributes)
self.sys_bios._parse_attributes, self.bios_json)
def test_change_password(self):
self.sys_bios.change_password('newpassword',

View File

@ -26,7 +26,9 @@ class EthernetInterfaceTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'ethernet_interfaces.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
eth_path = ("/redfish/v1/Systems/437XR1138R2/EthernetInterfaces/"
"12446A3B0411")
@ -34,7 +36,7 @@ class EthernetInterfaceTestCase(base.TestCase):
self.conn, eth_path, redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_eth._parse_attributes()
self.sys_eth._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.sys_eth.redfish_version)
self.assertEqual('1', self.sys_eth.identity)
self.assertEqual('Ethernet Interface', self.sys_eth.name)
@ -54,13 +56,16 @@ class EthernetInterfaceCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'ethernet_interfaces_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.sys_eth_col = ethernet_interface.EthernetInterfaceCollection(
self.conn, '/redfish/v1/Systems/437XR1138R2/EthernetInterfaces',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_eth_col._parse_attributes()
self.sys_eth_col._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.sys_eth_col.redfish_version)
self.assertEqual('Ethernet Interface Collection',
self.sys_eth_col.name)

View File

@ -28,14 +28,16 @@ class ProcessorTestCase(base.TestCase):
super(ProcessorTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/processor.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.sys_processor = processor.Processor(
self.conn, '/redfish/v1/Systems/437XR1138R2/Processors/CPU1',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_processor._parse_attributes()
self.sys_processor._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.sys_processor.redfish_version)
self.assertEqual('CPU1', self.sys_processor.identity)
self.assertEqual('CPU 1', self.sys_processor.socket)
@ -82,13 +84,16 @@ class ProcessorCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'processor_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.sys_processor_col = processor.ProcessorCollection(
self.conn, '/redfish/v1/Systems/437XR1138R2/Processors',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_processor_col._parse_attributes()
self.sys_processor_col._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.sys_processor_col.redfish_version)
self.assertEqual('Processors Collection', self.sys_processor_col.name)
self.assertEqual(('/redfish/v1/Systems/437XR1138R2/Processors/CPU1',

View File

@ -26,14 +26,16 @@ class SimpleStorageTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'simple_storage.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.simpl_stor = simple_storage.SimpleStorage(
self.conn, '/redfish/v1/Systems/437XR1138R2/SimpleStorage/1',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.simpl_stor._parse_attributes()
self.simpl_stor._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.simpl_stor.redfish_version)
self.assertEqual('1', self.simpl_stor.identity)
self.assertEqual('Simple Storage Controller', self.simpl_stor.name)
@ -56,13 +58,17 @@ class SimpleStorageCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'simple_storage_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.simpl_stor_col = simple_storage.SimpleStorageCollection(
self.conn, '/redfish/v1/Systems/437XR1138R2/SimpleStorage',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.simpl_stor_col._parse_attributes()
self.simpl_stor_col._parse_attributes(self.json_doc)
self.assertEqual((
'/redfish/v1/Systems/437XR1138R2/SimpleStorage/1',),
self.simpl_stor_col.members_identities)

View File

@ -39,14 +39,16 @@ class SystemTestCase(base.TestCase):
super(SystemTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/system.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.sys_inst = system.System(
self.conn, '/redfish/v1/Systems/437XR1138R2',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_inst._parse_attributes()
self.sys_inst._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.sys_inst.redfish_version)
self.assertEqual('Chicago-45Z-2381', self.sys_inst.asset_tag)
self.assertEqual('P79 v1.33 (02/28/2015)', self.sys_inst.bios_version)
@ -85,13 +87,13 @@ class SystemTestCase(base.TestCase):
self.sys_inst.json.pop('Actions')
self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Actions',
self.sys_inst._parse_attributes)
self.sys_inst._parse_attributes, self.json_doc)
def test__parse_attributes_missing_boot(self):
self.sys_inst.json.pop('Boot')
self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Boot',
self.sys_inst._parse_attributes)
self.sys_inst._parse_attributes, self.json_doc)
def test__parse_attributes_missing_reset_target(self):
self.sys_inst.json['Actions']['#ComputerSystem.Reset'].pop(
@ -99,11 +101,11 @@ class SystemTestCase(base.TestCase):
self.assertRaisesRegex(
exceptions.MissingAttributeError,
'attribute Actions/#ComputerSystem.Reset/target',
self.sys_inst._parse_attributes)
self.sys_inst._parse_attributes, self.json_doc)
def test__parse_attributes_null_memory_capacity(self):
self.sys_inst.json['MemorySummary']['TotalSystemMemoryGiB'] = None
self.sys_inst._parse_attributes()
self.sys_inst._parse_attributes(self.json_doc)
self.assertIsNone(self.sys_inst.memory_summary.size_gib)
def test__parse_attributes_bad_maintenance_window_time(self):
@ -112,7 +114,7 @@ class SystemTestCase(base.TestCase):
self.assertRaisesRegex(
exceptions.MalformedAttributeError,
'@Redfish.MaintenanceWindow/MaintenanceWindowStartTime',
self.sys_inst._parse_attributes)
self.sys_inst._parse_attributes, self.json_doc)
def test_get__reset_action_element(self):
value = self.sys_inst._get_reset_action_element()
@ -284,7 +286,7 @@ class SystemTestCase(base.TestCase):
# | GIVEN |
self.sys_inst._json['MemorySummary']['Status'].pop('HealthRollup')
# | WHEN |
self.sys_inst._parse_attributes()
self.sys_inst._parse_attributes(self.json_doc)
# | THEN |
self.assertEqual(96, self.sys_inst.memory_summary.size_gib)
self.assertIsNone(self.sys_inst.memory_summary.health)
@ -292,7 +294,7 @@ class SystemTestCase(base.TestCase):
# | GIVEN |
self.sys_inst._json['MemorySummary'].pop('Status')
# | WHEN |
self.sys_inst._parse_attributes()
self.sys_inst._parse_attributes(self.json_doc)
# | THEN |
self.assertEqual(96, self.sys_inst.memory_summary.size_gib)
self.assertIsNone(self.sys_inst.memory_summary.health)
@ -300,7 +302,7 @@ class SystemTestCase(base.TestCase):
# | GIVEN |
self.sys_inst._json['MemorySummary'].pop('TotalSystemMemoryGiB')
# | WHEN |
self.sys_inst._parse_attributes()
self.sys_inst._parse_attributes(self.json_doc)
# | THEN |
self.assertIsNone(self.sys_inst.memory_summary.size_gib)
self.assertIsNone(self.sys_inst.memory_summary.health)
@ -308,7 +310,7 @@ class SystemTestCase(base.TestCase):
# | GIVEN |
self.sys_inst._json.pop('MemorySummary')
# | WHEN |
self.sys_inst._parse_attributes()
self.sys_inst._parse_attributes(self.json_doc)
# | THEN |
self.assertIsNone(self.sys_inst.memory_summary)
@ -555,8 +557,8 @@ class SystemTestCase(base.TestCase):
# | THEN |
self.assertIsInstance(contoso_system_extn_inst,
fake.FakeOEMSystemExtension)
self.assertIs(self.sys_inst, contoso_system_extn_inst.core_resource)
self.assertEqual('Contoso', contoso_system_extn_inst.oem_property_name)
self.assertIs(self.sys_inst, contoso_system_extn_inst._parent_resource)
self.assertEqual('Contoso', contoso_system_extn_inst._vendor_id)
class SystemCollectionTestCase(base.TestCase):
@ -566,12 +568,15 @@ class SystemCollectionTestCase(base.TestCase):
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'system_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.sys_col = system.SystemCollection(
self.conn, '/redfish/v1/Systems', redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_col._parse_attributes()
self.sys_col._parse_attributes(self.json_doc)
self.assertEqual('1.0.2', self.sys_col.redfish_version)
self.assertEqual('Computer System Collection', self.sys_col.name)
self.assertEqual(('/redfish/v1/Systems/437XR1138R2',),

View File

@ -47,7 +47,7 @@ BASE_RESOURCE_JSON = {
class BaseResource(resource_base.ResourceBase):
def _parse_attributes(self):
def _parse_attributes(self, json_doc):
pass
@ -182,7 +182,7 @@ class TestResource(resource_base.ResourceBase):
redfish_version, registries)
self.identity = identity
def _parse_attributes(self):
def _parse_attributes(self, json_doc):
pass

View File

@ -27,7 +27,9 @@ class SoftwareInventoryTestCase(base.TestCase):
conn = mock.Mock()
with open(
'sushy/tests/unit/json_samples/softwareinventory.json') as f:
conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
conn.get.return_value.json.return_value = self.json_doc
self.soft_inv = softwareinventory.SoftwareInventory(
conn,
@ -35,7 +37,7 @@ class SoftwareInventoryTestCase(base.TestCase):
redfish_version='1.3.0')
def test__parse_attributes(self):
self.soft_inv._parse_attributes()
self.soft_inv._parse_attributes(self.json_doc)
self.assertEqual('BMC', self.soft_inv.identity)
self.assertEqual(
'1.30.367a12-rev1',
@ -57,7 +59,7 @@ class SoftwareInventoryTestCase(base.TestCase):
self.soft_inv.json.pop('Id')
self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Id',
self.soft_inv._parse_attributes)
self.soft_inv._parse_attributes, self.json_doc)
class SoftwareInventoryCollectionTestCase(base.TestCase):
@ -67,14 +69,16 @@ class SoftwareInventoryCollectionTestCase(base.TestCase):
conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'softwareinventory_collection.json') as f:
conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
conn.get.return_value.json.return_value = self.json_doc
self.soft_inv_col = softwareinventory.SoftwareInventoryCollection(
conn, '/redfish/v1/UpdateService/SoftwareInventory',
redfish_version='1.3.0')
def test__parse_attributes(self):
self.soft_inv_col._parse_attributes()
self.soft_inv_col._parse_attributes(self.json_doc)
self.assertEqual('1.3.0', self.soft_inv_col.redfish_version)
self.assertEqual(
'Software Inventory Collection',

View File

@ -28,14 +28,16 @@ class UpdateServiceTestCase(base.TestCase):
super(UpdateServiceTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/updateservice.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.upd_serv = updateservice.UpdateService(
self.conn, '/redfish/v1/UpdateService/UpdateService',
redfish_version='1.3.0')
def test__parse_attributes(self):
self.upd_serv._parse_attributes()
self.upd_serv._parse_attributes(self.json_doc)
self.assertEqual('UpdateService', self.upd_serv.identity)
self.assertEqual('/FWUpdate', self.upd_serv.http_push_uri)
self.assertIn('/FWUpdate', self.upd_serv.http_push_uri_targets)
@ -52,7 +54,7 @@ class UpdateServiceTestCase(base.TestCase):
self.upd_serv.json.pop('Actions')
self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Actions',
self.upd_serv._parse_attributes)
self.upd_serv._parse_attributes, self.json_doc)
def test_simple_update(self):
self.upd_serv.simple_update(

View File

@ -45,14 +45,16 @@ class MainTestCase(base.TestCase):
mock_session_service.return_value = self.sess_serv
mock_connector.return_value = self.conn
with open('sushy/tests/unit/json_samples/root.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.json_doc = json.load(f)
self.conn.get.return_value.json.return_value = self.json_doc
self.root = main.Sushy('http://foo.bar:1234',
verify=True, auth=mock_auth)
mock_connector.assert_called_once_with(
'http://foo.bar:1234', verify=True)
def test__parse_attributes(self):
self.root._parse_attributes()
self.root._parse_attributes(self.json_doc)
self.assertEqual('RootService', self.root.identity)
self.assertEqual('Root Service', self.root.name)
self.assertEqual('1.0.2', self.root.redfish_version)

View File

@ -129,13 +129,13 @@ class UtilsTestCase(base.TestCase):
class NestedResource(resource_base.ResourceBase):
def _parse_attributes(self):
def _parse_attributes(self, json_doc):
pass
class BaseResource(resource_base.ResourceBase):
def _parse_attributes(self):
def _parse_attributes(self, json_doc):
pass
def _do_some_crunch_work_to_get_a(self):