diff --git a/sushy/resources/constants.py b/sushy/resources/constants.py index 19276bc9..ea8a279b 100644 --- a/sushy/resources/constants.py +++ b/sushy/resources/constants.py @@ -11,7 +11,8 @@ # under the License. # Values comes from the Redfish System json-schema 1.0.0: -# http://redfish.dmtf.org/schemas/v1/Resource.json +# http://redfish.dmtf.org/schemas/v1/Resource.json or +# https://redfish.dmtf.org/schemas/v1/MessageRegistry.v1_1_1.json # Health related constants. HEALTH_OK = 'ok' @@ -30,3 +31,12 @@ STATE_UNAVAILABLEOFFLINE = 'unavailable offline' STATE_DEFERRING = 'deferring' STATE_QUIESCED = 'quiesced' STATE_UPDATING = 'updating' + +# Message Registry message parameter type related constants. +PARAMTYPE_STRING = 'string' +PARAMTYPE_NUMBER = 'number' + +# Severity related constants +SEVERITY_OK = 'ok' +SEVERITY_WARNING = 'warning' +SEVERITY_CRITICAL = 'critical' diff --git a/sushy/resources/mappings.py b/sushy/resources/mappings.py index 26588f24..c0819829 100644 --- a/sushy/resources/mappings.py +++ b/sushy/resources/mappings.py @@ -34,3 +34,14 @@ HEALTH_VALUE_MAP = { HEALTH_VALUE_MAP_REV = ( utils.revert_dictionary(HEALTH_VALUE_MAP)) + +PARAMTYPE_MAP = { + 'string': res_cons.PARAMTYPE_STRING, + 'number': res_cons.PARAMTYPE_NUMBER +} + +SEVERITY_VALUE_MAP = { + 'OK': res_cons.SEVERITY_OK, + 'Warning': res_cons.SEVERITY_WARNING, + 'Critical': res_cons.SEVERITY_CRITICAL +} diff --git a/sushy/resources/registry/__init__.py b/sushy/resources/registry/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sushy/resources/registry/messageregistry.py b/sushy/resources/registry/messageregistry.py new file mode 100644 index 00000000..a5d80b5e --- /dev/null +++ b/sushy/resources/registry/messageregistry.py @@ -0,0 +1,80 @@ +# 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. + +# This is referred from Redfish standard schema. +# https://redfish.dmtf.org/schemas/v1/MessageRegistry.v1_1_1.json + + +from sushy.resources import base +from sushy.resources import mappings as res_maps + + +class MessageDictionaryField(base.DictionaryField): + + description = base.Field('Description', required=True) + """Indicates how and when the message is returned by the Redfish service""" + + message = base.Field('Message', required=True) + """Template text of the message + + Template can include placeholders for message arguments in form + % where denotes a position passed from MessageArgs. + """ + + number_of_args = base.Field('NumberOfArgs', required=True) + """Number of arguments to be expected to be passed in as MessageArgs + for this message + """ + + param_types = base.Field('ParamTypes', + adapter=lambda x: + [res_maps.PARAMTYPE_MAP[v] for v in x]) + """Mapped MessageArg types, in order, for the message""" + + resolution = base.Field('Resolution', required=True) + """Suggestions on how to resolve the situation that caused the error""" + + severity = base.MappedField('Severity', + res_maps.SEVERITY_VALUE_MAP, + required=True) + """Mapped severity of the message""" + + +class MessageRegistry(base.ResourceBase): + + identity = base.Field('Id', required=True) + """The Message registry identity string""" + + name = base.Field('Name', required=True) + """The name of the message registry""" + + description = base.Field('Description') + """Human-readable description of the message 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_prefix = base.Field('RegistryPrefix', required=True) + """Prefix used in messageIDs which uniquely identifies all of + the messages in this registry as belonging to this registry + """ + + registry_version = base.Field('RegistryVersion', required=True) + """Message registry version which is used in the middle portion + of a messageID + """ + + messages = MessageDictionaryField('Messages') + """List of messages in this registry""" diff --git a/sushy/tests/unit/json_samples/message_registry.json b/sushy/tests/unit/json_samples/message_registry.json new file mode 100644 index 00000000..8b612a22 --- /dev/null +++ b/sushy/tests/unit/json_samples/message_registry.json @@ -0,0 +1,40 @@ +{ + "@odata.type": "#MessageRegistry.v1_0_0.MessageRegistry", + "Id": "Test.1.0.0", + "Name": "Test Message Registry", + "Language": "en", + "Description": "This registry defines messages for sushy testing", + "RegistryPrefix": "Test", + "RegistryVersion": "1.0.0", + "OwningEntity": "sushy", + "Messages": { + "Success": { + "Description": "Everything OK", + "Message": "Everything done successfully.", + "Severity": "OK", + "NumberOfArgs": 0, + "Resolution": "None" + }, + "Failed": { + "Description": "Nothing is OK", + "Message": "The property %1 broke everything.", + "Severity": "Critical", + "NumberOfArgs": 1, + "ParamTypes": [ + "string" + ], + "Resolution": "Panic" + }, + "TooBig": { + "Description": "Value too big", + "Message": "Property's %1 value cannot be greater than %2.", + "Severity": "Warning", + "NumberOfArgs": 2, + "ParamTypes": [ + "string", + "number" + ], + "Resolution": "Try again" + } + } +} diff --git a/sushy/tests/unit/resources/registry/__init__.py b/sushy/tests/unit/resources/registry/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sushy/tests/unit/resources/registry/test_messageregistry.py b/sushy/tests/unit/resources/registry/test_messageregistry.py new file mode 100644 index 00000000..59e2fc09 --- /dev/null +++ b/sushy/tests/unit/resources/registry/test_messageregistry.py @@ -0,0 +1,67 @@ +# 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 + +import mock + +from sushy.resources import constants as res_cons +from sushy.resources.registry import messageregistry +from sushy.tests.unit import base + + +class MessageRegistryTestCase(base.TestCase): + + def setUp(self): + 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.registry = messageregistry.MessageRegistry( + self.conn, '/redfish/v1/Registries/Test', + redfish_version='1.0.2') + + def test__parse_attributes(self): + self.registry._parse_attributes() + self.assertEqual('Test.1.0.0', self.registry.identity) + self.assertEqual('Test Message Registry', self.registry.name) + self.assertEqual('en', self.registry.language) + self.assertEqual('This registry defines messages for sushy testing', + self.registry.description) + self.assertEqual('Test', self.registry.registry_prefix) + self.assertEqual('1.0.0', self.registry.registry_version) + self.assertEqual('sushy', self.registry.owning_entity) + self.assertEqual(3, len(self.registry.messages)) + self.assertEqual('Everything OK', + self.registry.messages['Success'].description) + self.assertEqual('Everything done successfully.', + self.registry.messages['Success'].message) + self.assertEqual(res_cons.SEVERITY_OK, + self.registry.messages['Success'].severity) + self.assertEqual(0, self.registry.messages['Success'].number_of_args) + self.assertEqual(2, len(self.registry.messages['TooBig'].param_types)) + self.assertEqual(res_cons.PARAMTYPE_STRING, + self.registry.messages['TooBig'].param_types[0]) + self.assertEqual(res_cons.PARAMTYPE_NUMBER, + self.registry.messages['TooBig'].param_types[1]) + self.assertEqual('Panic', self.registry.messages['Failed'].resolution) + + def test__parse_attribtues_unknown_param_type(self): + self.registry.json['Messages']['Failed']['ParamTypes'] = \ + ['unknown_type'] + self.assertRaisesRegex(KeyError, + 'unknown_type', + self.registry._parse_attributes)