Automatically discover available system/manager/chassis

The ``get_system``, ``get_manager`` and ``get_chassis`` methods
have been modified not to require the ``identity`` parameter
referring to a particular resource instance. If ``identity`` is
omited, sushy will default to the only available resource for as
long as it's single and therefore deterministic.

The intent is to simplify user API by not requiring the consumer
to discover available resources prior to requesting one.

Change-Id: Ifbf8b05154b619d4831c26870ee97c3dce555fd2
Story: 2007258
Task: 38707
This commit is contained in:
Ilya Etingof 2020-02-07 19:27:28 +01:00
parent 544f000fe6
commit c961d8fa80
4 changed files with 166 additions and 6 deletions

View File

@ -0,0 +1,10 @@
---
features:
- |
The ``get_system``, ``get_manager`` and ``get_chassis`` methods modified
not to require the ``identity`` parameter referring to a particular
resource instance. If ``identity`` is omited, sushy will default to the
only available resource for as long as it's single and therefore
deterministic.
The intent is to simplify user API by not requiring the consumer to
discover available resources prior to requesting one.

View File

@ -60,6 +60,10 @@ class ArchiveParsingError(SushyError):
message = 'Failed parsing archive "%(path)s": %(error)s'
class UnknownDefaultError(SushyError):
message = 'Failed at determining default for "%(entity)s": %(error)s'
class ExtensionError(SushyError):
message = ('Sushy Extension Error: %(error)s')

View File

@ -182,12 +182,25 @@ class Sushy(base.ResourceBase):
redfish_version=self.redfish_version,
registries=self.registries)
def get_system(self, identity):
def get_system(self, identity=None):
"""Given the identity return a System object
:param identity: The identity of the System resource
:param identity: The identity of the System resource. If not given,
sushy will default to the single available System or fail
if there appear to be more or less then one System listed.
:raises: `UnknownDefaultError` if default system can't be determined.
:returns: The System object
"""
if identity is None:
systems_collection = self.get_system_collection()
listed_systems = systems_collection.get_members()
if len(listed_systems) != 1:
raise exceptions.UnknownDefaultError(
entity='ComputerSystem',
error='System count is not exactly one')
identity = listed_systems[0].path
return system.System(self._conn, identity,
redfish_version=self.redfish_version,
registries=self.registries)
@ -207,12 +220,25 @@ class Sushy(base.ResourceBase):
redfish_version=self.redfish_version,
registries=self.registries)
def get_chassis(self, identity):
def get_chassis(self, identity=None):
"""Given the identity return a Chassis object
:param identity: The identity of the Chassis resource
:param identity: The identity of the Chassis resource. If not given,
sushy will default to the single available chassis or fail
if there appear to be more or less then one Chassis listed.
:raises: `UnknownDefaultError` if default system can't be determined.
:returns: The Chassis object
"""
if identity is None:
chassis_collection = self.get_chassis_collection()
listed_chassis = chassis_collection.get_members()
if len(listed_chassis) != 1:
raise exceptions.UnknownDefaultError(
entity='Chassis',
error='Chassis count is not exactly one')
identity = listed_chassis[0].path
return chassis.Chassis(self._conn, identity,
redfish_version=self.redfish_version,
registries=self.registries)
@ -257,12 +283,24 @@ class Sushy(base.ResourceBase):
redfish_version=self.redfish_version,
registries=self.registries)
def get_manager(self, identity):
def get_manager(self, identity=None):
"""Given the identity return a Manager object
:param identity: The identity of the Manager resource
:param identity: The identity of the Manager resource. If not given,
sushy will default to the single available Manager or fail
if there appear to be more or less then one Manager listed.
:returns: The Manager object
"""
if identity is None:
managers_collection = self.get_manager_collection()
listed_managers = managers_collection.get_members()
if len(listed_managers) != 1:
raise exceptions.UnknownDefaultError(
entity='Manager',
error='Manager count is not exactly one')
identity = listed_managers[0].path
return manager.Manager(self._conn, identity,
redfish_version=self.redfish_version,
registries=self.registries)

View File

@ -116,6 +116,41 @@ class MainTestCase(base.TestCase):
redfish_version=self.root.redfish_version,
registries=mock_registries)
@mock.patch.object(system, 'SystemCollection', autospec=True)
@mock.patch.object(system, 'System', autospec=True)
@mock.patch('sushy.Sushy.registries', autospec=True)
def test_get_system_default_ok(
self, mock_registries, mock_system, mock_system_collection):
self.root._standard_message_registries_path = None
mock_system.path = 'fake-system-id'
mock_members = mock_system_collection.return_value.get_members
mock_members.return_value = [mock_system]
self.root.get_system()
mock_system_collection.assert_called_once_with(
self.root._conn, '/redfish/v1/Systems',
redfish_version=self.root.redfish_version,
registries=mock_registries
)
mock_system.assert_called_once_with(
self.root._conn, 'fake-system-id',
redfish_version=self.root.redfish_version,
registries=mock_registries)
@mock.patch.object(system, 'SystemCollection', autospec=True)
@mock.patch.object(system, 'System', autospec=True)
@mock.patch('sushy.Sushy.registries', autospec=True)
def test_get_system_default_failure(
self, mock_registries, mock_system, mock_system_collection):
self.root._standard_message_registries_path = None
mock_members = mock_system_collection.return_value.get_members
mock_members.return_value = []
self.assertRaises(exceptions.UnknownDefaultError, self.root.get_system)
mock_system_collection.assert_called_once_with(
self.root._conn, '/redfish/v1/Systems',
redfish_version=self.root.redfish_version,
registries=mock_registries
)
@mock.patch.object(chassis, 'Chassis', autospec=True)
def test_get_chassis(self, mock_chassis):
self.root.get_chassis('fake-chassis-id')
@ -123,6 +158,43 @@ class MainTestCase(base.TestCase):
self.root._conn, 'fake-chassis-id',
self.root.redfish_version, self.root.registries)
@mock.patch.object(chassis, 'ChassisCollection', autospec=True)
@mock.patch.object(chassis, 'Chassis', autospec=True)
@mock.patch('sushy.Sushy.registries', autospec=True)
def test_get_chassis_default_ok(
self, mock_registries, mock_chassis, mock_chassis_collection):
self.root._standard_message_registries_path = None
mock_chassis.path = 'fake-chassis-id'
mock_members = mock_chassis_collection.return_value.get_members
mock_members.return_value = [mock_chassis]
self.root.get_chassis()
mock_chassis_collection.assert_called_once_with(
self.root._conn, '/redfish/v1/Chassis',
redfish_version=self.root.redfish_version,
registries=mock_registries
)
mock_chassis.assert_called_once_with(
self.root._conn, 'fake-chassis-id',
redfish_version=self.root.redfish_version,
registries=mock_registries
)
@mock.patch.object(chassis, 'ChassisCollection', autospec=True)
@mock.patch.object(chassis, 'Chassis', autospec=True)
@mock.patch('sushy.Sushy.registries', autospec=True)
def test_get_chassis_default_failure(
self, mock_registries, mock_chassis, mock_chassis_collection):
self.root._standard_message_registries_path = None
mock_members = mock_chassis_collection.return_value.get_members
mock_members.return_value = []
self.assertRaises(
exceptions.UnknownDefaultError, self.root.get_chassis)
mock_chassis_collection.assert_called_once_with(
self.root._conn, '/redfish/v1/Chassis',
redfish_version=self.root.redfish_version,
registries=mock_registries
)
@mock.patch.object(chassis, 'ChassisCollection', autospec=True)
def test_get_chassis_collection(self, chassis_collection_mock):
self.root.get_chassis_collection()
@ -158,6 +230,42 @@ class MainTestCase(base.TestCase):
self.root._conn, 'fake-manager-id',
self.root.redfish_version, self.root.registries)
@mock.patch.object(manager, 'ManagerCollection', autospec=True)
@mock.patch.object(manager, 'Manager', autospec=True)
@mock.patch('sushy.Sushy.registries', autospec=True)
def test_get_manager_default_ok(
self, mock_registries, mock_manager, mock_manager_collection):
self.root._standard_message_registries_path = None
mock_manager.path = 'fake-manager-id'
mock_members = mock_manager_collection.return_value.get_members
mock_members.return_value = [mock_manager]
self.root.get_manager()
mock_manager_collection.assert_called_once_with(
self.root._conn, '/redfish/v1/Managers',
redfish_version=self.root.redfish_version,
registries=mock_registries
)
mock_manager.assert_called_once_with(
self.root._conn, 'fake-manager-id',
redfish_version=self.root.redfish_version,
registries=mock_registries)
@mock.patch.object(manager, 'ManagerCollection', autospec=True)
@mock.patch.object(manager, 'Manager', autospec=True)
@mock.patch('sushy.Sushy.registries', autospec=True)
def test_get_manager_default_failure(
self, mock_registries, mock_manager, mock_system_collection):
self.root._standard_message_registries_path = None
mock_members = mock_system_collection.return_value.get_members
mock_members.return_value = []
self.assertRaises(
exceptions.UnknownDefaultError, self.root.get_manager)
mock_system_collection.assert_called_once_with(
self.root._conn, '/redfish/v1/Managers',
redfish_version=self.root.redfish_version,
registries=mock_registries
)
@mock.patch.object(sessionservice, 'SessionService', autospec=True)
def test_get_sessionservice(self, mock_sess_serv):
self.root.get_session_service()