Merge "Add System<->Manager linkage"
This commit is contained in:
commit
815da08998
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Establishes ComputerSystem->Managers and Manager->ComputerSystems
|
||||
references at sushy data abstraction level what make it possible to
|
||||
look up Manager(s) responsible for a ComputerSystem and vice versa.
|
|
@ -195,6 +195,25 @@ class Manager(base.ResourceBase):
|
|||
self._conn, utils.get_sub_resource_path_by(self, 'VirtualMedia'),
|
||||
redfish_version=self.redfish_version)
|
||||
|
||||
@property
|
||||
@utils.cache_it
|
||||
def systems(self):
|
||||
"""A list of systems managed by this manager.
|
||||
|
||||
Returns a list of `System` objects representing systems being
|
||||
managed by this manager.
|
||||
|
||||
:raises: MissingAttributeError if '@odata.id' field is missing.
|
||||
:returns: A list of `System` instances
|
||||
"""
|
||||
paths = utils.get_sub_resource_path_by(
|
||||
self, ["Links", "ManagerForServers"], is_collection=True)
|
||||
|
||||
from sushy.resources.system import system
|
||||
return [system.System(self._conn, path,
|
||||
redfish_version=self.redfish_version)
|
||||
for path in paths]
|
||||
|
||||
|
||||
class ManagerCollection(base.ResourceCollectionBase):
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import logging
|
|||
from sushy import exceptions
|
||||
from sushy.resources import base
|
||||
from sushy.resources import common
|
||||
from sushy.resources.manager import manager
|
||||
from sushy.resources import mappings as res_maps
|
||||
from sushy.resources.system import bios
|
||||
from sushy.resources.system import constants as sys_cons
|
||||
|
@ -336,6 +337,24 @@ class System(base.ResourceBase):
|
|||
self._conn, utils.get_sub_resource_path_by(self, "Storage"),
|
||||
redfish_version=self.redfish_version)
|
||||
|
||||
@property
|
||||
@utils.cache_it
|
||||
def managers(self):
|
||||
"""A list of managers for this system.
|
||||
|
||||
Returns a list of `Manager` objects representing the managers
|
||||
that manage this system.
|
||||
|
||||
:raises: MissingAttributeError if '@odata.id' field is missing.
|
||||
:returns: A list of `Manager` instances
|
||||
"""
|
||||
paths = utils.get_sub_resource_path_by(
|
||||
self, ["Links", "ManagedBy"], is_collection=True)
|
||||
|
||||
return [manager.Manager(self._conn, path,
|
||||
redfish_version=self.redfish_version)
|
||||
for path in paths]
|
||||
|
||||
|
||||
class SystemCollection(base.ResourceCollectionBase):
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import sushy
|
|||
from sushy import exceptions
|
||||
from sushy.resources.manager import manager
|
||||
from sushy.resources.manager import virtual_media
|
||||
from sushy.resources.system import system
|
||||
from sushy.tests.unit import base
|
||||
|
||||
|
||||
|
@ -266,6 +267,18 @@ class ManagerTestCase(base.TestCase):
|
|||
virtual_media.VirtualMediaCollection)
|
||||
self.assertFalse(vrt_media._is_stale)
|
||||
|
||||
def test_systems(self):
|
||||
# | GIVEN |
|
||||
with open('sushy/tests/unit/json_samples/'
|
||||
'system.json') as f:
|
||||
self.conn.get.return_value.json.return_value = json.load(f)
|
||||
|
||||
# | WHEN & THEN |
|
||||
actual_systems = self.manager.systems
|
||||
self.assertIsInstance(actual_systems[0], system.System)
|
||||
self.assertEqual(
|
||||
'/redfish/v1/Systems/437XR1138R2', actual_systems[0].path)
|
||||
|
||||
|
||||
class ManagerCollectionTestCase(base.TestCase):
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import mock
|
|||
import sushy
|
||||
from sushy import exceptions
|
||||
from sushy.resources import constants as res_cons
|
||||
from sushy.resources.manager import manager
|
||||
from sushy.resources.system import bios
|
||||
from sushy.resources.system import mappings as sys_map
|
||||
from sushy.resources.system import processor
|
||||
|
@ -478,6 +479,18 @@ class SystemTestCase(base.TestCase):
|
|||
# | WHEN & THEN |
|
||||
self.assertIsInstance(self.sys_inst.storage, storage.StorageCollection)
|
||||
|
||||
def test_managers(self):
|
||||
# | GIVEN |
|
||||
with open('sushy/tests/unit/json_samples/'
|
||||
'manager.json') as f:
|
||||
self.conn.get.return_value.json.return_value = json.load(f)
|
||||
|
||||
# | WHEN & THEN |
|
||||
actual_managers = self.sys_inst.managers
|
||||
self.assertIsInstance(actual_managers[0], manager.Manager)
|
||||
self.assertEqual(
|
||||
'/redfish/v1/Managers/BMC', actual_managers[0].path)
|
||||
|
||||
|
||||
class SystemCollectionTestCase(base.TestCase):
|
||||
|
||||
|
|
|
@ -69,6 +69,14 @@ class UtilsTestCase(base.TestCase):
|
|||
subresource_path)
|
||||
self.assertEqual(expected_result, value)
|
||||
|
||||
def test_get_sub_resource_path_by_collection(self):
|
||||
subresource_path = ["Links", "ManagedBy"]
|
||||
expected_result = ['/redfish/v1/Managers/BMC']
|
||||
value = utils.get_sub_resource_path_by(self.sys_inst,
|
||||
subresource_path,
|
||||
is_collection=True)
|
||||
self.assertEqual(expected_result, value)
|
||||
|
||||
def test_get_sub_resource_path_by_fails(self):
|
||||
subresource_path = ['Links', 'Chassis']
|
||||
expected_result = 'attribute Links/Chassis/@odata.id is missing'
|
||||
|
|
|
@ -66,13 +66,17 @@ def int_or_none(x):
|
|||
return int(x)
|
||||
|
||||
|
||||
def get_sub_resource_path_by(resource, subresource_name):
|
||||
def get_sub_resource_path_by(resource, subresource_name, is_collection=False):
|
||||
"""Helper function to find the subresource path
|
||||
|
||||
:param resource: ResourceBase instance on which the name
|
||||
gets queried upon.
|
||||
:param subresource_name: name of the resource field to
|
||||
fetch the '@odata.id' from.
|
||||
:param is_collection: if `True`, expect a list of resources to
|
||||
fetch the '@odata.id' from.
|
||||
:returns: Resource path (if `is_collection` is `False`) or
|
||||
a list of resource paths (if `is_collection` is `True`).
|
||||
"""
|
||||
if not subresource_name:
|
||||
raise ValueError('"subresource_name" cannot be empty')
|
||||
|
@ -88,12 +92,24 @@ def get_sub_resource_path_by(resource, subresource_name):
|
|||
raise exceptions.MissingAttributeError(
|
||||
attribute='/'.join(subresource_name), resource=resource.path)
|
||||
|
||||
if '@odata.id' not in body:
|
||||
raise exceptions.MissingAttributeError(
|
||||
attribute='/'.join(subresource_name) + '/@odata.id',
|
||||
resource=resource.path)
|
||||
elements = []
|
||||
|
||||
return body['@odata.id']
|
||||
try:
|
||||
if is_collection:
|
||||
for element in body:
|
||||
elements.append(element['@odata.id'])
|
||||
return elements
|
||||
|
||||
else:
|
||||
return body['@odata.id']
|
||||
|
||||
except (TypeError, KeyError):
|
||||
attribute = '/'.join(subresource_name)
|
||||
if is_collection:
|
||||
attribute += '[%s]' % len(elements)
|
||||
attribute += '/@odata.id'
|
||||
raise exceptions.MissingAttributeError(
|
||||
attribute=attribute, resource=resource.path)
|
||||
|
||||
|
||||
def max_safe(iterable, default=0):
|
||||
|
|
Loading…
Reference in New Issue