Redfish: Add has_rotational attribute to server capabilities

Change-Id: Ic57375b319901d37f32c1cc81b1f47387ec41fcc
This commit is contained in:
Nisha Agarwal 2017-08-03 21:20:00 -07:00
parent aad05fdb11
commit 45191de2e1
12 changed files with 209 additions and 3 deletions

View File

@ -681,6 +681,8 @@ class RedfishOperations(operations.IloOperations):
members_identities) > 0),
('has_ssd',
common_storage.has_ssd(sushy_system)),
('has_rotational',
common_storage.has_rotational(sushy_system)),
) if value})
memory_data = sushy_system.memory.details()

View File

@ -73,6 +73,7 @@ class HPEArrayControllerCollection(base.ResourceCollectionBase):
_logical_drives_maximum_size_mib = None
_physical_drives_maximum_size_mib = None
_has_ssd = None
_has_rotational = None
@property
def _resource_type(self):
@ -114,8 +115,21 @@ class HPEArrayControllerCollection(base.ResourceCollectionBase):
break
return self._has_ssd
@property
def has_rotational(self):
"""Return true if any of the drive under ArrayControllers is ssd"""
if self._has_rotational is None:
self._has_rotational = False
for member in self.get_members():
if member.physical_drives.has_rotational:
self._has_rotational = True
break
return self._has_rotational
def refresh(self):
super(HPEArrayControllerCollection, self).refresh()
self._logical_drives_maximum_size_mib = None
self._physical_drives_maximum_size_mib = None
self._has_ssd = None
self._has_rotational = None

View File

@ -135,3 +135,29 @@ def has_ssd(system_obj):
storage_value = _get_attribute_value_of(
storage_resource, 'has_ssd', default=False)
return storage_value
def has_rotational(system_obj):
"""Gets if the system has any drive as HDD drive
:param system_obj: The HPESystem object.
:returns True if system has HDD drives.
"""
smart_value = False
storage_value = False
smart_resource = _get_attribute_value_of(system_obj, 'smart_storage')
if smart_resource is not None:
smart_value = _get_attribute_value_of(
smart_resource, 'has_rotational', default=False)
if smart_value:
return smart_value
# Its returned before just to avoid hitting BMC if we have
# already got the HDD device above.
storage_resource = _get_attribute_value_of(system_obj, 'storages')
if storage_resource is not None:
storage_value = _get_attribute_value_of(
storage_resource, 'has_rotational', default=False)
return storage_value

View File

@ -41,6 +41,7 @@ class HPEPhysicalDriveCollection(base.ResourceCollectionBase):
_maximum_size_mib = None
_has_ssd = None
_has_rotational = None
@property
def _resource_type(self):
@ -70,7 +71,20 @@ class HPEPhysicalDriveCollection(base.ResourceCollectionBase):
break
return self._has_ssd
@property
def has_rotational(self):
"""Return true if the drive is HDD"""
if self._has_rotational is None:
self._has_rotational = False
for member in self.get_members():
if member.media_type == constants.MEDIA_TYPE_HDD:
self._has_rotational = True
break
return self._has_rotational
def refresh(self):
super(HPEPhysicalDriveCollection, self).refresh()
self._maximum_size_mib = None
self._has_ssd = None
self._has_rotational = None

View File

@ -34,6 +34,7 @@ class HPESmartStorage(base.ResourceBase):
_logical_drives_maximum_size_mib = None
_physical_drives_maximum_size_mib = None
_has_ssd = None
_has_rotational = None
@property
def array_controllers(self):
@ -88,9 +89,22 @@ class HPESmartStorage(base.ResourceBase):
break
return self._has_ssd
@property
def has_rotational(self):
"""Return true if any of the drive under ArrayControllers is HDD"""
if self._has_rotational is None:
self._has_rotational = False
for member in self.array_controllers.get_members():
if member.physical_drives.has_rotational:
self._has_rotational = True
break
return self._has_rotational
def refresh(self):
super(HPESmartStorage, self).refresh()
self._logical_drives_maximum_size_mib = None
self._physical_drives_maximum_size_mib = None
self._array_controllers = None
self._has_ssd = None
self._has_rotational = None

View File

@ -42,6 +42,7 @@ class Storage(base.ResourceBase):
_volumes = None
_drives_maximum_size_bytes = None
_has_ssd = None
_has_rotational = None
@property
def volumes(self):
@ -90,11 +91,24 @@ class Storage(base.ResourceBase):
break
return self._has_ssd
@property
def has_rotational(self):
"""Return true if any of the drive is HDD"""
if self._has_rotational is None:
self._has_rotational = False
for member in self._drives_list():
if member.media_type == constants.MEDIA_TYPE_HDD:
self._has_rotational = True
break
return self._has_rotational
def refresh(self):
super(Storage, self).refresh()
self._drives_maximum_size_bytes = None
self._volumes = None
self._has_ssd = None
self._has_rotational = None
class StorageCollection(base.ResourceCollectionBase):
@ -103,6 +117,7 @@ class StorageCollection(base.ResourceCollectionBase):
_volumes_maximum_size_bytes = None
_drives_maximum_size_bytes = None
_has_ssd = None
_has_rotational = None
@property
def _resource_type(self):
@ -144,8 +159,21 @@ class StorageCollection(base.ResourceCollectionBase):
break
return self._has_ssd
@property
def has_rotational(self):
"""Return true if Storage has any drive as HDD"""
if self._has_rotational is None:
self._has_rotational = False
for member in self.get_members():
if member.has_rotational:
self._has_rotational = True
break
return self._has_rotational
def refresh(self):
super(StorageCollection, self).refresh()
self._volumes_maximum_size_bytes = None
self._drives_maximum_size_bytes = None
self._has_ssd = None
self._has_rotational = None

View File

@ -181,3 +181,24 @@ class HPEArrayControllerCollectionTestCase(testtools.TestCase):
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor_col.has_ssd)
def test_has_rotational(self):
self.assertIsNone(self.sys_stor_col._has_rotational)
self.conn.get.return_value.json.reset_mock()
val = []
path = ('proliantutils/tests/redfish/json_samples/'
'array_controller.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'disk_drive_collection.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'disk_drive.json')
with open(path, 'r') as f:
dr_json = json.loads(f.read())
val.append(dr_json['drive1'])
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor_col.has_rotational)

View File

@ -109,3 +109,18 @@ class CommonMethodsTestCase(testtools.TestCase):
self._mock_property(storage_value))
actual = common.has_ssd(system_obj)
self.assertEqual(expected, actual)
@ddt.data((True, False, True),
(True, True, True),
(False, True, True),
(False, False, False))
@ddt.unpack
def test_has_rotational(self, smart_value, storage_value,
expected):
system_obj = self.system_obj
type(system_obj.smart_storage).has_rotational = (
self._mock_property(smart_value))
type(system_obj.storages).has_rotational = (
self._mock_property(storage_value))
actual = common.has_rotational(system_obj)
self.assertEqual(expected, actual)

View File

@ -117,3 +117,14 @@ class HPEPhysicalDriveCollectionTestCase(testtools.TestCase):
self.conn.get.return_value.json.side_effect = val
actual = self.sys_stor_col.has_ssd
self.assertTrue(actual)
def test_has_rotational(self):
self.assertIsNone(self.sys_stor_col._has_rotational)
self.conn.get.return_value.json.reset_mock()
path = ('proliantutils/tests/redfish/json_samples/'
'disk_drive.json')
with open(path, 'r') as f:
dr_json = json.loads(f.read())
val = [dr_json['drive1'], dr_json['drive2']]
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor_col.has_rotational)

View File

@ -132,3 +132,28 @@ class HPESmartStorageTestCase(testtools.TestCase):
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor.has_ssd)
def test_has_rotaional(self):
self.assertIsNone(self.sys_stor._has_rotational)
self.conn.get.return_value.json.reset_mock()
val = []
path = ('proliantutils/tests/redfish/json_samples/'
'array_controller_collection.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'array_controller.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'disk_drive_collection.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'disk_drive.json')
with open(path, 'r') as f:
dr_json = json.loads(f.read())
val.append(dr_json['drive1'])
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor.has_rotational)

View File

@ -100,6 +100,19 @@ class StorageTestCase(testtools.TestCase):
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor.has_ssd)
def test_has_rotational(self):
self.assertIsNone(self.sys_stor._has_rotational)
self.conn.get.return_value.json.reset_mock()
val = []
path = ('proliantutils/tests/redfish/json_samples/'
'drive.json')
with open(path, 'r') as f:
dr_json = json.loads(f.read())
val.append(dr_json['drive1'])
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor.has_rotational)
class StorageCollectionTestCase(testtools.TestCase):
@ -198,3 +211,20 @@ class StorageCollectionTestCase(testtools.TestCase):
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor_col.has_ssd)
def test_has_rotational(self):
self.assertIsNone(self.sys_stor_col._has_rotational)
self.conn.get.return_value.json.reset_mock()
val = []
path = ('proliantutils/tests/redfish/json_samples/'
'storage.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'drive.json')
with open(path, 'r') as f:
dr_json = json.loads(f.read())
val.append(dr_json['drive1'])
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
self.assertTrue(self.sys_stor_col.has_rotational)

View File

@ -684,11 +684,12 @@ class RedfishOperationsTestCase(testtools.TestCase):
'The Redfish controller failed to get the supported boot modes.',
self.rf_client.get_supported_boot_mode)
@mock.patch.object(common_storage, 'has_rotational')
@mock.patch.object(common_storage, 'has_ssd')
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
def test_get_server_capabilities(self, get_manager_mock, get_system_mock,
ssd_mock):
ssd_mock, rotational_mock):
type(get_system_mock.return_value.pci_devices).gpu_devices = (
[mock.MagicMock(spec=pci_device.PCIDevice)])
type(get_system_mock.return_value.bios_settings).sriov = (
@ -726,6 +727,7 @@ class RedfishOperationsTestCase(testtools.TestCase):
memory_mock.details = mock.MagicMock(return_value=mem)
get_system_mock.return_value.memory = memory_mock
ssd_mock.return_value = True
rotational_mock.return_value = True
actual = self.rf_client.get_server_capabilities()
expected = {'pci_gpu_devices': 1, 'sriov_enabled': 'true',
'secure_boot': 'true', 'cpu_vt': 'true',
@ -740,14 +742,17 @@ class RedfishOperationsTestCase(testtools.TestCase):
'persistent_memory': 'true',
'nvdimm_n': 'true',
'logical_nvdimm_n': 'false',
'has_ssd': 'true'}
'has_ssd': 'true',
'has_rotational': 'true'}
self.assertEqual(expected, actual)
@mock.patch.object(common_storage, 'has_rotational')
@mock.patch.object(common_storage, 'has_ssd')
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
def test_get_server_capabilities_optional_capabilities_absent(
self, get_manager_mock, get_system_mock, ssd_mock):
self, get_manager_mock, get_system_mock, ssd_mock,
rotational_mock):
type(get_system_mock.return_value.pci_devices).gpu_devices = (
[mock.MagicMock(spec=pci_device.PCIDevice)])
type(get_system_mock.return_value.bios_settings).sriov = (
@ -786,6 +791,7 @@ class RedfishOperationsTestCase(testtools.TestCase):
get_system_mock.return_value.memory = memory_mock
memory_mock.details = mock.MagicMock(return_value=mem)
ssd_mock.return_value = False
rotational_mock.return_value = False
actual = self.rf_client.get_server_capabilities()
expected = {'pci_gpu_devices': 1,
'rom_firmware_version': 'U31 v1.00 (03/11/2017)',