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:
parent
e97952c32f
commit
e03caca38f
|
@ -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.
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue