Add support for BIOS Attribute Registry
Add support for caching Attribute Registries. In particular, cache the BIOS Attribute Registry and provide a function to return it if it matches the AttributeRegistry field in System BIOS. Change-Id: I1b83cfd9d9a44ac00e423c589bcc2c53c14ad478
This commit is contained in:
parent
c0da841700
commit
2d88bc9d86
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Add support for caching Redfish Attribute Registries. In particular,
|
||||
cache the BIOS Attribute Registry and provide a function to return it
|
||||
if it matches the AttributeRegistry field in System BIOS.
|
|
@ -466,14 +466,16 @@ class Sushy(base.ResourceBase):
|
|||
@property
|
||||
@utils.cache_it
|
||||
def registries(self):
|
||||
"""Gets and combines all message registries together
|
||||
"""Gets and combines all registries together
|
||||
|
||||
Fetches all registries if any provided by Redfish service
|
||||
and combines together with packaged standard registries.
|
||||
Both message and attribute registries are supported from
|
||||
the Redfish service.
|
||||
|
||||
:returns: dict of combined message registries keyed by both the
|
||||
:returns: dict of combined registries keyed by both the
|
||||
registry name (Registry_name.Major_version.Minor_version) and the
|
||||
message registry file identity, with the value being the actual
|
||||
registry file identity, with the value being the actual
|
||||
registry itself.
|
||||
"""
|
||||
standard = self._get_standard_message_registry_collection()
|
||||
|
@ -487,12 +489,19 @@ class Sushy(base.ResourceBase):
|
|||
if registry_col:
|
||||
provided = registry_col.get_members()
|
||||
for r in provided:
|
||||
message_registry = r.get_message_registry(
|
||||
|
||||
# Check for Message and Attribute registries
|
||||
registry = r.get_message_registry(
|
||||
self._language,
|
||||
self._public_connector)
|
||||
registries[r.registry] = message_registry
|
||||
if r.identity not in registries:
|
||||
registries[r.identity] = message_registry
|
||||
if not registry:
|
||||
registry = r.get_attribute_registry(
|
||||
self._language,
|
||||
self._public_connector)
|
||||
if registry:
|
||||
registries[r.registry] = registry
|
||||
if r.identity not in registries:
|
||||
registries[r.identity] = registry
|
||||
|
||||
return registries
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# The Redfish standard schema that defines the AttributeRegistry is at:
|
||||
# https://redfish.dmtf.org/schemas/v1/AttributeRegistry.v1_3_5.json
|
||||
|
||||
import logging
|
||||
|
||||
from sushy.resources import base
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AttributeListField(base.ListField):
|
||||
|
||||
name = base.Field('AttributeName', required=True)
|
||||
"""The unique name for the attribute"""
|
||||
|
||||
default_value = base.Field('DefaultValue')
|
||||
"""The default value for the attribute"""
|
||||
|
||||
attribute_type = base.Field('Type')
|
||||
"""The attribute type"""
|
||||
|
||||
unique = base.Field('IsSystemUniqueProperty', adapter=bool)
|
||||
"""Indicates whether this attribute is unique for this system"""
|
||||
|
||||
display_name = base.Field('DisplayName')
|
||||
"""User-readable display string for attribute in the defined language"""
|
||||
|
||||
immutable = base.Field('Immutable', adapter=bool)
|
||||
"""An indication of whether this attribute is immutable"""
|
||||
|
||||
read_only = base.Field('ReadOnly', adapter=bool)
|
||||
"""An indication of whether this attribute is read-only"""
|
||||
|
||||
reset_required = base.Field('ResetRequired', adapter=bool)
|
||||
"""An indication of whether this attribute is read-only"""
|
||||
|
||||
lower_bound = base.Field('LowerBound')
|
||||
"""The lower limit for an integer attribute"""
|
||||
|
||||
max_length = base.Field('MaxLength')
|
||||
"""The maximum character length of the string attribute"""
|
||||
|
||||
min_length = base.Field('MinLength')
|
||||
"""The minimum character length of the string attribute"""
|
||||
|
||||
upper_bound = base.Field('UpperBound')
|
||||
"""The upper limit for an integer attribute"""
|
||||
|
||||
allowable_values = base.Field('Value')
|
||||
"""An array of the possible values for enumerated attribute values"""
|
||||
|
||||
|
||||
class AttributeRegistryEntryField(base.CompositeField):
|
||||
|
||||
attributes = AttributeListField('Attributes')
|
||||
"""List of attributes in this registry"""
|
||||
|
||||
# Vendors may have aditional items such as Dependencies, Menus, etc.
|
||||
# Only get the attributes.
|
||||
|
||||
|
||||
class AttributeRegistry(base.ResourceBase):
|
||||
|
||||
identity = base.Field('Id', required=True)
|
||||
"""The Attribute registry identity string"""
|
||||
|
||||
name = base.Field('Name', required=True)
|
||||
"""The name of the attribute registry"""
|
||||
|
||||
description = base.Field('Description')
|
||||
"""Human-readable description of the registry"""
|
||||
|
||||
language = base.Field('Language', required=True)
|
||||
"""RFC 5646 compliant language code for the registry"""
|
||||
|
||||
owning_entity = base.Field('OwningEntity', required=True)
|
||||
"""Organization or company that publishes this registry"""
|
||||
|
||||
registry_version = base.Field('RegistryVersion', required=True)
|
||||
"""The version of this registry"""
|
||||
|
||||
supported_systems = base.Field('SupportedSystems')
|
||||
"""The system that this registry supports"""
|
||||
|
||||
registry_entries = AttributeRegistryEntryField('RegistryEntries')
|
||||
"""Field containing Attributes, Dependencies, Menus etc."""
|
|
@ -87,9 +87,11 @@ class MessageRegistry(base.ResourceBase):
|
|||
|
||||
|
||||
def parse_message(message_registries, message_field):
|
||||
"""Using message registries parse the message and substitute any parms
|
||||
"""Parse the messages in registries and substitute any parms
|
||||
|
||||
:param message_registries: dict of Message Registries
|
||||
Check only registries that support messages.
|
||||
|
||||
:param registries: dict of Message Registries
|
||||
:param message_field: settings.MessageListField to parse
|
||||
|
||||
:returns: parsed settings.MessageListField with missing attributes filled
|
||||
|
@ -99,8 +101,9 @@ def parse_message(message_registries, message_field):
|
|||
if '.' in message_field.message_id:
|
||||
registry, msg_key = message_field.message_id.rsplit('.', 1)
|
||||
|
||||
if (registry in message_registries and msg_key
|
||||
in message_registries[registry].messages):
|
||||
if (registry in message_registries
|
||||
and hasattr(message_registries[registry], "messages")
|
||||
and msg_key in message_registries[registry].messages):
|
||||
reg_msg = message_registries[registry].messages[msg_key]
|
||||
else:
|
||||
# Some firmware only reports the MessageKey and no RegistryName.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
import logging
|
||||
|
||||
from sushy.resources import base
|
||||
from sushy.resources.registry import attribute_registry
|
||||
from sushy.resources.registry import message_registry
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -76,15 +77,43 @@ class MessageRegistryFile(base.ResourceBase):
|
|||
"""List of locations of Registry files for each supported language"""
|
||||
|
||||
def get_message_registry(self, language, public_connector):
|
||||
"""Load message registry file depending on its source
|
||||
|
||||
Will try to find `MessageRegistry` based on `odata.type` property and
|
||||
provided language. If desired language is not found, will pick a
|
||||
registry that has 'default' language.
|
||||
"""Get a Message Registry from the location
|
||||
|
||||
:param language: RFC 5646 language code for registry files
|
||||
:param public_connector: connector to use when downloading registry
|
||||
from the Internet
|
||||
:returns: a MessageRegistry or None if not found
|
||||
"""
|
||||
return self._get_registry(language, public_connector,
|
||||
'MessageRegistry',
|
||||
message_registry.MessageRegistry)
|
||||
|
||||
def get_attribute_registry(self, language, public_connector):
|
||||
"""Get an Attribute Registry from the location
|
||||
|
||||
:param language: RFC 5646 language code for registry files
|
||||
:param public_connector: connector to use when downloading registry
|
||||
from the Internet
|
||||
:returns: an AttributeRegistry or None if not found
|
||||
"""
|
||||
return self._get_registry(language, public_connector,
|
||||
'AttributeRegistry',
|
||||
attribute_registry.AttributeRegistry)
|
||||
|
||||
def _get_registry(self, language, public_connector, requested_type,
|
||||
registry_class):
|
||||
"""Load registry file depending on the registry type
|
||||
|
||||
Will try to find requested_type based on `odata.type` property,
|
||||
location, and provided language. If desired language is not found,
|
||||
will pick a registry that has 'default' language.
|
||||
|
||||
:param language: RFC 5646 language code for registry files
|
||||
:param public_connector: connector to use when downloading registry
|
||||
from the Internet
|
||||
:param requested_type: string identifying registry
|
||||
:param registry_class: registry class
|
||||
:returns: registry or None if not found
|
||||
"""
|
||||
|
||||
# NOTE (etingof): as per RFC5646, languages are case-insensitive
|
||||
|
@ -127,34 +156,35 @@ class MessageRegistryFile(base.ResourceBase):
|
|||
continue
|
||||
|
||||
try:
|
||||
registry = RegistryType(*args, **kwargs)
|
||||
registry_type = RegistryType(*args, **kwargs)
|
||||
|
||||
except Exception as exc:
|
||||
LOG.warning(
|
||||
'Cannot load message registry type from location '
|
||||
'Cannot load registry type from location '
|
||||
'%(location)s: %(error)s', {
|
||||
'location': kwargs['path'],
|
||||
'error': exc})
|
||||
continue
|
||||
|
||||
if registry._odata_type.endswith('MessageRegistry'):
|
||||
if registry_type._odata_type.endswith(requested_type):
|
||||
try:
|
||||
return message_registry.MessageRegistry(*args, **kwargs)
|
||||
return registry_class(*args, **kwargs)
|
||||
|
||||
except Exception as exc:
|
||||
LOG.warning(
|
||||
'Cannot load message registry from location '
|
||||
'Cannot load registry %(type)s from location '
|
||||
'%(location)s: %(error)s', {
|
||||
'type': requested_type,
|
||||
'location': kwargs['path'],
|
||||
'error': exc})
|
||||
continue
|
||||
|
||||
LOG.debug('Ignoring unsupported flavor of registry %(registry)s',
|
||||
{'registry': registry._odata_type})
|
||||
{'registry': registry_type._odata_type})
|
||||
return
|
||||
|
||||
LOG.warning('No message registry found for %(language)s or '
|
||||
'default', {'language': language})
|
||||
LOG.warning('No registry found for %(language)s or default',
|
||||
{'language': language})
|
||||
|
||||
|
||||
class MessageRegistryFileCollection(base.ResourceCollectionBase):
|
||||
|
|
|
@ -247,3 +247,31 @@ class Bios(base.ResourceBase):
|
|||
:returns: List of supported update apply time names
|
||||
"""
|
||||
return self._settings._supported_apply_times
|
||||
|
||||
def get_attribute_registry(self, language='en'):
|
||||
"""Get the Attribute Registry associated with this BIOS instance
|
||||
|
||||
:param language: RFC 5646 language code for Message Registries.
|
||||
Indicates language of registry to be used. Defaults to 'en'.
|
||||
:returns: the BIOS Attribute Registry
|
||||
"""
|
||||
registries = self._registries
|
||||
for key, registry in registries.items():
|
||||
# Check that BIOS attribute_registry matches the identity
|
||||
# of a registry, and this is the requested language
|
||||
if registry and self._attribute_registry == registry.identity:
|
||||
if language != registry.language:
|
||||
LOG.debug('Found BIOS attribute registry but '
|
||||
'language %(lang)s does not match '
|
||||
'%(reg_lang)s',
|
||||
{'lang': language,
|
||||
'reg_lang': registry.language})
|
||||
continue
|
||||
|
||||
return registry
|
||||
|
||||
LOG.info('BIOS attribute registry %(registry)s '
|
||||
'not available for language %(lang)s',
|
||||
{'registry': self._attribute_registry,
|
||||
'lang': language})
|
||||
return None
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#AttributeRegistry.AttributeRegistry",
|
||||
"@odata.id": "/redfish/v1/Test/Bios/BiosRegistry",
|
||||
"@odata.type": "#AttributeRegistry.v1_1_1.AttributeRegistry",
|
||||
"Description": "This is a test of BIOS Attribute Registry",
|
||||
"Id": "BiosAttributeRegistryP89.v1_0_0",
|
||||
"Language": "en",
|
||||
"Name": "BIOS Attribute Registry",
|
||||
"OwningEntity": "VendorA",
|
||||
"RegistryVersion": "1.0.0",
|
||||
"SupportedSystems": [
|
||||
{
|
||||
"FirmwareVersion": "2.0",
|
||||
"ProductName": "Ultra 4",
|
||||
"SystemId": "URGR8"
|
||||
}
|
||||
],
|
||||
"RegistryEntries": {
|
||||
"Attributes": [
|
||||
{
|
||||
"AttributeName": "SystemModelName",
|
||||
"CurrentValue": null,
|
||||
"DisplayName": "System Model Name",
|
||||
"DisplayOrder": 200,
|
||||
"HelpText": "Indicates the product name of the system.",
|
||||
"Hidden": false,
|
||||
"Immutable": true,
|
||||
"MaxLength": 40,
|
||||
"MenuPath": "./SysInformationRef",
|
||||
"MinLength": 0,
|
||||
"ReadOnly": true,
|
||||
"Type": "String",
|
||||
"ValueExpression": null,
|
||||
"WriteOnly": false
|
||||
},
|
||||
{
|
||||
"AttributeName": "ProcVirtualization",
|
||||
"CurrentValue": null,
|
||||
"DisplayName": "Virtualization Technology",
|
||||
"DisplayOrder": 404,
|
||||
"HelpText": "When set to Enabled, the BIOS will enable processor Virtualization features",
|
||||
"Hidden": false,
|
||||
"Immutable": false,
|
||||
"MenuPath": "./ProcSettingsRef",
|
||||
"ReadOnly": false,
|
||||
"ResetRequired": true,
|
||||
"Type": "Enumeration",
|
||||
"Value": [
|
||||
{
|
||||
"ValueDisplayName": "Enabled",
|
||||
"ValueName": "Enabled"
|
||||
},
|
||||
{
|
||||
"ValueDisplayName": "Disabled",
|
||||
"ValueName": "Disabled"
|
||||
}
|
||||
],
|
||||
"WarningText": null,
|
||||
"WriteOnly": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"@odata.context": "/redfish/v1/$metadata#MessageRegistryFile.MessageRegistryFile",
|
||||
"@odata.id": "/redfish/v1/Registries/BiosAttributeRegistry.v1_0",
|
||||
"@odata.type": "#MessageRegistryFile.v1_0_4.MessageRegistryFile",
|
||||
"Id": "BiosAttributeRegistry.v1_0",
|
||||
"Description": "Registry Definition File for BiosAttributeRegistry.v1_0",
|
||||
"Languages": [
|
||||
"en",
|
||||
"ja",
|
||||
"zh"
|
||||
],
|
||||
"Location": [
|
||||
{
|
||||
"Language": "en",
|
||||
"Uri": "/redfish/v1/registrystore/registries/en/biosattributeregistry.v1_0"
|
||||
},
|
||||
{
|
||||
"Language": "ja",
|
||||
"Uri": "/redfish/v1/registrystore/registries/ja/biosattributeregistry.v1_0"
|
||||
},
|
||||
{
|
||||
"Language": "zh",
|
||||
"Uri": "/redfish/v1/registrystore/registries/zh/biosattributeregistry.v1_0"
|
||||
}
|
||||
],
|
||||
"Name": "BiosAttributeRegistry.v1_0 Message Registry File",
|
||||
"Registry": "BiosAttributeRegistry.v1_0"
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import json
|
||||
from unittest import mock
|
||||
|
||||
from sushy.resources.registry import attribute_registry
|
||||
from sushy.tests.unit import base
|
||||
|
||||
|
||||
class AttributeRegistryTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(AttributeRegistryTestCase, self).setUp()
|
||||
self.conn = mock.Mock()
|
||||
with open('sushy/tests/unit/json_samples/'
|
||||
'bios_attribute_registry.json') as f:
|
||||
self.json_doc = json.load(f)
|
||||
|
||||
self.conn.get.return_value.json.return_value = self.json_doc
|
||||
|
||||
self.registry = attribute_registry.AttributeRegistry(
|
||||
self.conn, '/redfish/v1/Test/Bios/BiosRegistry',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test__parse_attributes(self):
|
||||
self.registry._parse_attributes(self.json_doc)
|
||||
self.assertEqual('BiosAttributeRegistryP89.v1_0_0',
|
||||
self.registry.identity)
|
||||
self.assertEqual('BIOS Attribute Registry', self.registry.name)
|
||||
self.assertEqual('en', self.registry.language)
|
||||
self.assertEqual('This is a test of BIOS Attribute Registry',
|
||||
self.registry.description)
|
||||
self.assertEqual('1.0.0', self.registry.registry_version)
|
||||
self.assertEqual('VendorA', self.registry.owning_entity)
|
||||
self.assertEqual([{'FirmwareVersion': '2.0', 'ProductName': 'Ultra 4',
|
||||
'SystemId': 'URGR8'}],
|
||||
self.registry.supported_systems)
|
||||
attributes = self.registry.registry_entries.attributes[0]
|
||||
self.assertEqual('SystemModelName', attributes.name)
|
||||
self.assertEqual('System Model Name', attributes.display_name)
|
||||
self.assertEqual(True, attributes.immutable)
|
||||
self.assertEqual(True, attributes.read_only)
|
||||
self.assertEqual('String', attributes.attribute_type)
|
||||
|
||||
attributes = self.registry.registry_entries.attributes[1]
|
||||
self.assertEqual('ProcVirtualization', attributes.name)
|
||||
self.assertEqual('Virtualization Technology', attributes.display_name)
|
||||
self.assertEqual(False, attributes.immutable)
|
||||
self.assertEqual(False, attributes.read_only)
|
||||
self.assertEqual(True, attributes.reset_required)
|
||||
self.assertEqual('Enumeration', attributes.attribute_type)
|
||||
self.assertEqual([{'ValueDisplayName': 'Enabled',
|
||||
'ValueName': 'Enabled'},
|
||||
{'ValueDisplayName': 'Disabled',
|
||||
'ValueName': 'Disabled'}],
|
||||
attributes.allowable_values)
|
|
@ -19,6 +19,7 @@ from unittest import mock
|
|||
|
||||
from sushy.resources import base as sushy_base
|
||||
from sushy.resources import constants as res_cons
|
||||
from sushy.resources.registry import attribute_registry
|
||||
from sushy.resources.registry import message_registry
|
||||
from sushy.tests.unit import base
|
||||
|
||||
|
@ -117,7 +118,7 @@ class MessageRegistryTestCase(base.TestCase):
|
|||
self.registry._parse_attributes(self.json_doc)
|
||||
self.assertEqual('warning', self.registry.messages['Success'].severity)
|
||||
|
||||
def test__parse_attribtues_unknown_param_type(self):
|
||||
def test__parse_attributes_unknown_param_type(self):
|
||||
self.registry.json['Messages']['Failed']['ParamTypes'] = \
|
||||
['unknown_type']
|
||||
self.assertRaisesRegex(KeyError,
|
||||
|
@ -291,3 +292,28 @@ class MessageRegistryTestCase(base.TestCase):
|
|||
self.assertEqual(res_cons.SEVERITY_WARNING, parsed_msg.severity)
|
||||
self.assertEqual('Property\'s arg1 value cannot be greater than '
|
||||
'unknown.', parsed_msg.message)
|
||||
|
||||
def test_parse_message_multiple_registries(self):
|
||||
conn = mock.Mock()
|
||||
with open('sushy/tests/unit/json_samples/message_registry.json') as f:
|
||||
conn.get.return_value.json.return_value = json.load(f)
|
||||
msg_registry = message_registry.MessageRegistry(
|
||||
conn, '/redfish/v1/Registries/Test',
|
||||
redfish_version='1.0.2')
|
||||
attr_registry = attribute_registry.AttributeRegistry(
|
||||
self.conn, '/redfish/v1/Test/Bios/BiosRegistry',
|
||||
redfish_version='1.0.2')
|
||||
registries = {'Test.1.0.2': attr_registry,
|
||||
'Test.1.0.0': msg_registry}
|
||||
message_field = sushy_base.MessageListField('Foo')
|
||||
message_field.message_id = 'Test.1.0.0.TooBig'
|
||||
message_field.message_args = ['arg1', 10]
|
||||
message_field.severity = None
|
||||
message_field.resolution = None
|
||||
|
||||
parsed_msg = message_registry.parse_message(registries, message_field)
|
||||
|
||||
self.assertEqual('Try again', parsed_msg.resolution)
|
||||
self.assertEqual(res_cons.SEVERITY_WARNING, parsed_msg.severity)
|
||||
self.assertEqual('Property\'s arg1 value cannot be greater than 10.',
|
||||
parsed_msg.message)
|
||||
|
|
|
@ -155,7 +155,7 @@ class MessageRegistryFileTestCase(base.TestCase):
|
|||
mock_msg_reg.assert_not_called()
|
||||
self.assertIsNone(registry)
|
||||
mock_log.warning.assert_called_with(
|
||||
'No message registry found for %(language)s or default',
|
||||
'No registry found for %(language)s or default',
|
||||
{'language': 'en'})
|
||||
|
||||
@mock.patch('sushy.resources.registry.message_registry.MessageRegistry',
|
||||
|
@ -189,12 +189,13 @@ class MessageRegistryFileTestCase(base.TestCase):
|
|||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
'Cannot load message registry from location %(location)s: '
|
||||
'Cannot load registry %(type)s from location %(location)s: '
|
||||
'%(error)s',
|
||||
{'location': {'extref': 'http://127.0.0.1/reg'},
|
||||
{'type': 'MessageRegistry',
|
||||
'location': {'extref': 'http://127.0.0.1/reg'},
|
||||
'error': mock.ANY}),
|
||||
mock.call(
|
||||
'No message registry found for %(language)s or default',
|
||||
'No registry found for %(language)s or default',
|
||||
{'language': 'en'})
|
||||
]
|
||||
|
||||
|
@ -224,12 +225,12 @@ class MessageRegistryFileTestCase(base.TestCase):
|
|||
self.assertTrue(mock_reg_type.called)
|
||||
self.assertIsNone(registry)
|
||||
mock_log.warning.assert_any_call(
|
||||
'Cannot load message registry type from location '
|
||||
'Cannot load registry type from location '
|
||||
'%(location)s: %(error)s',
|
||||
{'location': '/redfish/v1/Registries/Test/Test.1.0.json',
|
||||
'error': mock.ANY})
|
||||
mock_log.warning.assert_called_with(
|
||||
'No message registry found for %(language)s or default',
|
||||
'No registry found for %(language)s or default',
|
||||
{'language': 'en'})
|
||||
|
||||
@mock.patch('sushy.resources.registry.message_registry_file.RegistryType',
|
||||
|
@ -258,7 +259,7 @@ class MessageRegistryFileTestCase(base.TestCase):
|
|||
mock_msg_reg.assert_not_called()
|
||||
self.assertIsNone(registry)
|
||||
mock_log.warning.assert_called_with(
|
||||
'No message registry found for %(language)s or default',
|
||||
'No registry found for %(language)s or default',
|
||||
{'language': 'en'})
|
||||
|
||||
@mock.patch('sushy.resources.base.logging.warning',
|
||||
|
@ -272,6 +273,44 @@ class MessageRegistryFileTestCase(base.TestCase):
|
|||
'attribute "[\'Registry\']"')
|
||||
|
||||
|
||||
class BiosRegistryTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BiosRegistryTestCase, self).setUp()
|
||||
self.conn = mock.Mock()
|
||||
with open('sushy/tests/unit/json_samples/'
|
||||
'bios_attribute_registry_file.json') as 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/BiosAttributeRegistry.v1_0',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
@mock.patch('sushy.resources.registry.attribute_registry.'
|
||||
'AttributeRegistry',
|
||||
autospec=True)
|
||||
@mock.patch('sushy.resources.base.JsonDataReader', autospec=True)
|
||||
def test_get_bios_registry_uri(self, mock_reader, mock_msg_reg):
|
||||
mock_reader_rv = mock.Mock()
|
||||
mock_reader.return_value = mock_reader_rv
|
||||
mock_reader_rv.get_data.return_value = FieldData(200, {}, {
|
||||
"@odata.type": "#AttributeRegistry.v1_0_0.AttributeRegistry",
|
||||
"Id": "BiosAttributeRegistry.v1_0",
|
||||
})
|
||||
mock_msg_reg_rv = mock.Mock()
|
||||
mock_msg_reg.return_value = mock_msg_reg_rv
|
||||
|
||||
registry = self.reg_file.get_attribute_registry('en', None)
|
||||
mock_msg_reg.assert_called_once_with(
|
||||
self.conn,
|
||||
path='/redfish/v1/registrystore/registries/en/'
|
||||
'biosattributeregistry.v1_0',
|
||||
reader=None, redfish_version=self.reg_file.redfish_version)
|
||||
self.assertEqual(mock_msg_reg_rv, registry)
|
||||
|
||||
|
||||
class MessageRegistryFileCollectionTestCase(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
|
|
@ -21,6 +21,7 @@ from dateutil import parser
|
|||
|
||||
from sushy import exceptions
|
||||
from sushy.resources import constants as res_cons
|
||||
from sushy.resources.registry import attribute_registry
|
||||
from sushy.resources.registry import message_registry
|
||||
from sushy.resources import settings
|
||||
from sushy.resources.system import bios
|
||||
|
@ -42,16 +43,28 @@ class BiosTestCase(base.TestCase):
|
|||
self.bios_settings_json,
|
||||
self.bios_settings_json]
|
||||
|
||||
registries = {}
|
||||
conn = mock.Mock()
|
||||
with open('sushy/tests/unit/json_samples/message_registry.json') as f:
|
||||
conn.get.return_value.json.return_value = json.load(f)
|
||||
registry = message_registry.MessageRegistry(
|
||||
msg_reg = message_registry.MessageRegistry(
|
||||
conn, '/redfish/v1/Registries/Test',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
registries['Test.1.0'] = msg_reg
|
||||
|
||||
with open('sushy/tests/unit/json_samples/'
|
||||
'bios_attribute_registry.json') as f:
|
||||
conn.get.return_value.json.return_value = json.load(f)
|
||||
bios_reg = attribute_registry.AttributeRegistry(
|
||||
conn, '/redfish/v1/Registries/BiosRegistryTest',
|
||||
redfish_version='1.0.2')
|
||||
|
||||
registries['BiosRegistry.1.0'] = bios_reg
|
||||
|
||||
self.sys_bios = bios.Bios(
|
||||
self.conn, '/redfish/v1/Systems/437XR1138R2/BIOS',
|
||||
registries={'Test.1.0': registry},
|
||||
registries=registries,
|
||||
redfish_version='1.0.2')
|
||||
|
||||
def test__parse_attributes(self):
|
||||
|
@ -333,3 +346,49 @@ class BiosTestCase(base.TestCase):
|
|||
data={'OldPassword': 'oldpassword',
|
||||
'NewPassword': 'newpassword',
|
||||
'PasswordName': 'adminpassword'})
|
||||
|
||||
def test_get_attribute_registry(self):
|
||||
|
||||
registry = self.sys_bios.get_attribute_registry()
|
||||
self.assertEqual(registry.name, 'BIOS Attribute Registry')
|
||||
self.assertEqual(registry.description, 'This is a test of BIOS '
|
||||
'Attribute Registry')
|
||||
self.assertEqual(registry.registry_entries.attributes[0].name,
|
||||
'SystemModelName')
|
||||
self.assertEqual(registry.registry_entries.attributes[0].display_name,
|
||||
'System Model Name')
|
||||
self.assertEqual(registry.registry_entries.attributes[0].immutable,
|
||||
True)
|
||||
self.assertEqual(registry.registry_entries.attributes[0].read_only,
|
||||
True)
|
||||
self.assertEqual(registry.registry_entries.attributes[0].
|
||||
attribute_type, 'String')
|
||||
self.assertEqual(registry.registry_entries.attributes[1].name,
|
||||
'ProcVirtualization')
|
||||
self.assertEqual(registry.registry_entries.attributes[1].display_name,
|
||||
'Virtualization Technology')
|
||||
self.assertEqual(registry.registry_entries.attributes[1].immutable,
|
||||
False)
|
||||
self.assertEqual(registry.registry_entries.attributes[1].read_only,
|
||||
False)
|
||||
self.assertEqual(registry.registry_entries.attributes[1].
|
||||
reset_required, True)
|
||||
self.assertEqual(registry.registry_entries.attributes[1].
|
||||
attribute_type, 'Enumeration')
|
||||
self.assertEqual(registry.registry_entries.attributes[1].
|
||||
allowable_values,
|
||||
[{'ValueDisplayName': 'Enabled',
|
||||
'ValueName': 'Enabled'},
|
||||
{'ValueDisplayName': 'Disabled',
|
||||
'ValueName': 'Disabled'}])
|
||||
|
||||
def test_get_attribute_registry_no_lang(self):
|
||||
|
||||
registry = self.sys_bios.get_attribute_registry(language='zh')
|
||||
self.assertIsNone(registry)
|
||||
|
||||
def test_get_attribute_registry_not_found(self):
|
||||
|
||||
self.sys_bios._attribute_registry = "Unknown"
|
||||
registry = self.sys_bios.get_attribute_registry()
|
||||
self.assertIsNone(registry)
|
||||
|
|
Loading…
Reference in New Issue