From ee97a8a8ed9618f43394a6986b1700d5ed5f2ffc Mon Sep 17 00:00:00 2001 From: Nisha Agarwal Date: Wed, 13 Jul 2016 08:44:41 +0000 Subject: [PATCH] Discover Storage details Discover following attributes: has_ssd has_rotational drive_rotational__rpm logical_raid_level_ Change-Id: Ib987651d78057719033366417dd3addf46d14578 --- proliantutils/ilo/ris.py | 177 ++++++++++- proliantutils/tests/ilo/ris_sample_outputs.py | 287 ++++++++++++++++++ proliantutils/tests/ilo/test_ris.py | 179 ++++++++++- 3 files changed, 638 insertions(+), 5 deletions(-) diff --git a/proliantutils/ilo/ris.py b/proliantutils/ilo/ris.py index 508a6b6f..9d372fd5 100755 --- a/proliantutils/ilo/ris.py +++ b/proliantutils/ilo/ris.py @@ -274,6 +274,175 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations): gpu_list.append(item) return gpu_list + def _get_storage_resource(self): + """Gets the SmartStorage resource if exists. + + :raises: IloCommandNotSupportedError if the resource SmartStorage + doesn't exist. + :returns the tuple of SmartStorage URI, Headers and settings. + """ + system = self._get_host_details() + if ('links' in system['Oem']['Hp'] and + 'SmartStorage' in system['Oem']['Hp']['links']): + # Get the SmartStorage URI and Settings + storage_uri = system['Oem']['Hp']['links']['SmartStorage']['href'] + status, headers, storage_settings = self._rest_get(storage_uri) + + if status >= 300: + msg = self._get_extended_error(storage_settings) + raise exception.IloError(msg) + + return headers, storage_uri, storage_settings + else: + msg = ('"links/SmartStorage" section in ComputerSystem/Oem/Hp' + ' does not exist') + raise exception.IloCommandNotSupportedError(msg) + + def _get_array_controller_resource(self): + """Gets the ArrayController resource if exists. + + :raises: IloCommandNotSupportedError if the resource ArrayController + doesn't exist. + :returns the tuple of SmartStorage URI, Headers and settings. + """ + headers, storage_uri, storage_settings = self._get_storage_resource() + if ('links' in storage_settings and + 'ArrayControllers' in storage_settings['links']): + # Get the ArrayCOntrollers URI and Settings + array_uri = storage_settings['links']['ArrayControllers']['href'] + status, headers, array_settings = self._rest_get(array_uri) + + if status >= 300: + msg = self._get_extended_error(array_settings) + raise exception.IloError(msg) + + return headers, array_uri, array_settings + else: + msg = ('"links/ArrayControllers" section in SmartStorage' + ' does not exist') + raise exception.IloCommandNotSupportedError(msg) + + def _create_list_of_array_controllers(self): + """Creates the list of Array Controller URIs. + + :raises: IloCommandNotSupportedError if the ArrayControllers + doesnt have member "Member". + :returns list of ArrayControllers. + """ + headers, array_uri, array_settings = ( + self._get_array_controller_resource()) + array_uri_links = [] + if ('links' in array_settings and + 'Member' in array_settings['links']): + array_uri_links = array_settings['links']['Member'] + else: + msg = ('"links/Member" section in ArrayControllers' + ' does not exist') + raise exception.IloCommandNotSupportedError(msg) + return array_uri_links + + def _get_drive_type_and_speed(self): + """Gets the disk drive type. + + :returns: A dictionary with the following keys: + - has_rotational: True/False. It is True if atleast one + rotational disk is attached. + - has_ssd: True/False. It is True if at least one SSD disk is + attached. + - drive_rotational__rpm: These are set to true as + per the speed of the rotational disks. + :raises: IloCommandNotSupportedError if the PhysicalDrives resource + doesn't exist. + :raises: IloError, on an error from iLO. + """ + disk_details = self._get_physical_drive_resource() + drive_hdd = False + drive_ssd = False + drive_details = {} + speed_const_list = [4800, 5400, 7200, 10000, 15000] + if disk_details: + for item in disk_details: + value = item['MediaType'] + if value == "HDD": + drive_hdd = True + speed = item['RotationalSpeedRpm'] + if speed in speed_const_list: + var = 'rotational_drive_' + str(speed) + '_rpm' + drive_details.update({var: 'true'}) + # Note: RIS returns value as 'SDD' for SSD drives. + else: + drive_ssd = True + if drive_hdd: + drive_details.update({'has_rotational': 'true'}) + if drive_ssd: + drive_details.update({'has_ssd': 'true'}) + return drive_details if len(drive_details.keys()) > 0 else None + + def _get_drive_resource(self, drive_name): + """Gets the DiskDrive resource if exists. + + :param drive_name: can be either "PhysicalDrives" or + "LogicalDrives". + :returns the list of drives. + :raises: IloCommandNotSupportedError if the given drive resource + doesn't exist. + :raises: IloError, on an error from iLO. + """ + disk_details_list = [] + array_uri_links = self._create_list_of_array_controllers() + for array_link in array_uri_links: + _, _, member_settings = ( + self._rest_get(array_link['href'])) + + if ('links' in member_settings and + drive_name in member_settings['links']): + disk_uri = member_settings['links'][drive_name]['href'] + headers, disk_member_uri, disk_mem = ( + self._rest_get(disk_uri)) + if ('links' in disk_mem and + 'Member' in disk_mem['links']): + for disk_link in disk_mem['links']['Member']: + diskdrive_uri = disk_link['href'] + _, _, disk_details = ( + self._rest_get(diskdrive_uri)) + disk_details_list.append(disk_details) + else: + msg = ('"links/Member" section in %s' + ' does not exist', drive_name) + raise exception.IloCommandNotSupportedError(msg) + else: + msg = ('"links/%s" section in ' + ' ArrayController/links/Member does not exist', + drive_name) + raise exception.IloCommandNotSupportedError(msg) + if disk_details_list: + return disk_details_list + + def _get_logical_drive_resource(self): + """Returns the LogicalDrives data.""" + return self._get_drive_resource('LogicalDrives') + + def _get_physical_drive_resource(self): + """Returns the PhysicalDrives data.""" + return self._get_drive_resource('PhysicalDrives') + + def _get_logical_raid_levels(self): + """Gets the different raid levels configured on a server. + + :returns a dictionary of logical_raid_levels set to true. + Example if raid level 1+0 and 6 are configured, it returns + {'logical_raid_level_10': 'true', + 'logical_raid_level_6': 'true'} + """ + logical_drive_details = self._get_logical_drive_resource() + raid_level = {} + if logical_drive_details: + for item in logical_drive_details: + if 'Raid' in item: + raid_level_var = "logical_raid_level_" + item['Raid'] + raid_level.update({raid_level_var: 'true'}) + return raid_level if len(raid_level.keys()) > 0 else None + def _get_bios_settings_resource(self, data): """Get the BIOS settings resource.""" try: @@ -1002,6 +1171,12 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations): capabilities['rom_firmware_version'] = rom_firmware_version capabilities.update(self._get_ilo_firmware_version()) capabilities.update(self._get_number_of_gpu_devices_connected()) + drive_details = self._get_drive_type_and_speed() + if drive_details is not None: + capabilities.update(drive_details) + raid_details = self._get_logical_raid_levels() + if raid_details is not None: + capabilities.update(raid_details) boot_modes = common.get_supported_boot_modes( self.get_supported_boot_mode()) capabilities.update({ @@ -1016,7 +1191,7 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations): try: self._check_iscsi_rest_patch_allowed() capabilities['iscsi_boot'] = 'true' - except exception.IloCommandNotSupportedError: + except exception.IloError: # If an error is raised dont populate the capability # iscsi_boot pass diff --git a/proliantutils/tests/ilo/ris_sample_outputs.py b/proliantutils/tests/ilo/ris_sample_outputs.py index 1462cc88..e0006215 100755 --- a/proliantutils/tests/ilo/ris_sample_outputs.py +++ b/proliantutils/tests/ilo/ris_sample_outputs.py @@ -287,6 +287,24 @@ GET_HEADERS = { 'x_hp-chrp-service-version': '1.0.3' } +REST_GET_SMART_STORAGE = """ +{ + "Model": "ProLiant BL460c Gen9", + "Name": "Computer System", + "Oem": { + "Hp": { + "links": + { + "SmartStorage": + { + "href": "/rest/v1/Systems/1/SmartStorage" + } + } + } + } +} +""" + REST_GET_SECURE_BOOT = { "Name": "SecureBoot", "ResetAllKeys": True, @@ -3892,3 +3910,272 @@ Pci(0x8,0x0)/Pci(0x0,0x0)", ] } """ + +STORAGE_SETTINGS = """ +{ + "@odata.context": "/redfish/v1/$metadata#Systems/Members/1\ +/SmartStorage$entity", + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/", + "@odata.type": "#HpSmartStorage.HpSmartStorage", + "Description": "HP Smart Storage", + "Id": "1", + "Links": { + "ArrayControllers": { + "@odata.id": "/redfish/v1/Systems/1\ +/SmartStorage/ArrayControllers/" + }, + "HostBusAdapters": { + "@odata.id": "/redfish/v1/Systems/1/SmartStorage\ +/HostBusAdapters/" + } + }, + "Name": "HpSmartStorage", + "Status": { + "Health": "OK" + }, + "Type": "HpSmartStorage.1.0.0", + "links": { + "ArrayControllers": { + "href": "/rest/v1/Systems/1/SmartStorage\ +/ArrayControllers" + }, + "HostBusAdapters": { + "href": "/rest/v1/Systems/1/SmartStorage\ +/HostBusAdapters" + }, + "self": { + "href": "/rest/v1/Systems/1/SmartStorage" + } + } +} +""" + +ARRAY_SETTINGS = """ +{ + "@odata.context": "/redfish/v1/$metadata#Systems/Members/1\ +/SmartStorage/ArrayControllers", + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers/", + "@odata.type": "#HpSmartStorageArrayControllerCollection.\ +1.0.0.HpSmartStorageArrayControllerCollection", + "Description": "HP Smart Storage Array Controllers View", + "MemberType": "HpSmartStorageArrayController.1", + "Members": [{ + "@odata.id": "/redfish/v1/Systems/1/SmartStorage\ +/ArrayControllers/0/" + }], + "Members@odata.count": 1, + "Name": "HpSmartStorageArrayControllers", + "Total": 1, + "Type": "Collection.0.9.5", + "links": { + "Member": [{ + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers/0" + }], + "self": { + "href": "/rest/v1/Systems/1/SmartStorage/\ +ArrayControllers" + } + } +} +""" + +ARRAY_MEM_SETTINGS = """ +{ + "@odata.context": "/redfish/v1/$metadata#Systems/Members/1\ +/SmartStorage/ArrayControllers/Members/$entity", + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers/0/", + "@odata.type": "#HpSmartStorageArrayController.\ +HpSmartStorageArrayController", + "AdapterType": "SmartArray", + "BackupPowerSourceStatus": "Present", + "CacheMemorySizeMiB": 1024, + "CurrentOperatingMode": "RAID", + "Description": "HP Smart Storage Array Controller View", + "FirmwareVersion": { + "Current": { + "VersionString": "2.49" + } + }, + "HardwareRevision": "B", + "Id": "0", + "Links": { + "LogicalDrives": { + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/\ +ArrayControllers/0/LogicalDrives/" + }, + "PhysicalDrives": { + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/\ +ArrayControllers/0/DiskDrives/" + }, + "StorageEnclosures": { + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/\ +ArrayControllers/0/StorageEnclosures/" + } + }, + "Location": "Slot 0", + "LocationFormat": "PCISlot", + "Model": "HP Smart Array P244br Controller", + "Name": "HpSmartStorageArrayController", + "SerialNumber": "PDZVU0FLM7I03I", + "Status": { + "Health": "OK", + "State": "Enabled" + }, + "Type": "HpSmartStorageArrayController.1.0.0", + "links": { + "LogicalDrives": { + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers\ +/0/LogicalDrives" + }, + "PhysicalDrives": { + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers/\ +0/DiskDrives" + }, + "StorageEnclosures": { + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers/\ +0/StorageEnclosures" + }, + "self": { + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers/0" + } + } +} +""" + +DISK_COLLECTION = """ +{ + "@odata.context": "/redfish/v1/$metadata#Systems/Members/1\ +/SmartStorage/ArrayControllers/Members/2/DiskDrives", + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers\ +/2/DiskDrives/", + "@odata.type": "\ +#HpSmartStorageDiskDriveCollection.HpSmartStorageDiskDriveCollection", + "Description": "HP Smart Storage Disk Drives View", + "MemberType": "HpSmartStorageDiskDrive.1", + "Members": [{ + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/\ +ArrayControllers/0/DiskDrives/0/" + }], + "Members@odata.count": 1, + "Name": "HpSmartStorageDiskDrives", + "Total": 1, + "Type": "Collection.1.0.0", + "links": { + "Member": [{ + "href": "/rest/v1/Systems/1/SmartStorage/\ +ArrayControllers/0/DiskDrives/0" + }], + "self": { + "href": "/rest/v1/Systems/1/SmartStorage/\ +ArrayControllers/0/DiskDrives" + } + } +} +""" +DISK_DETAILS_LIST = """ +[{ + "@odata.context": "/redfish/v1/$metadata#Systems/Members/1\ +/SmartStorage/ArrayControllers/Members/0/DiskDrives/Members/$entity", + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers\ +/0/DiskDrives/0/", + "@odata.type": "#HpSmartStorageDiskDrive.HpSmartStorageDiskDrive", + "CapacityMiB": 572325, + "CurrentTemperatureCelsius": 25, + "Description": "HP Smart Storage Disk Drive View", + "EncryptedDrive": "False", + "FirmwareVersion": { + "Current": { + "VersionString": "HPDC" + } + }, + "Id": "0", + "InterfaceType": "SAS", + "Location": "1I:1:1", + "LocationFormat": "ControllerPort:Box:Bay", + "MaximumTemperatureCelsius": 34, + "MediaType": "HDD", + "Model": "EG0600FBVFP", + "Name": "HpSmartStorageDiskDrive", + "RotationalSpeedRpm": 10000, + "SerialNumber": "KWK1JS2X", + "Status": { + "Health": "OK", + "State": "Enabled" + }, + "Type": "HpSmartStorageDiskDrive.1.0.0", + "links": { + "self": { + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers\ +/0/DiskDrives/0" + } + } +}] +""" + +LOGICAL_COLLECTION = """ +{ + "@odata.context": "/redfish/v1/$metadata#Systems/Members/1/SmartStorage/\ +ArrayControllers/Members/0/LogicalDrives", + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers/\ +0/LogicalDrives/", + "@odata.type": "\ +#HpSmartStorageLogicalDriveCollection.HpSmartStorageLogicalDriveCollection", + "Description": "HP Smart Storage Logical Drives View", + "MemberType": "HpSmartStorageLogicalDrive.1", + "Members": [{ + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers\ +/0/LogicalDrives/0/" + }], + "Members@odata.count": 1, + "Name": "HpSmartStorageLogicalDrives", + "Total": 1, + "Type": "Collection.1.0.0", + "links": { + "Member": [{ + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers/\ +0/LogicalDrives/1" + }], + "self": { + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers/0\ +/LogicalDrives" + } + } +} +""" + +LOGICAL_DETAILS = """ +[{ + "@odata.context": "/redfish/v1/$metadata#Systems/Members/1/SmartStorage/\ +ArrayControllers/Members/0/LogicalDrives/Members/$entity", + "@odata.id": "/redfish/v1/Systems/1/SmartStorage/ArrayControllers/0/\ +LogicalDrives/1/", + "@odata.type": "\ +#HpSmartStorageLogicalDrive.1.1.0.HpSmartStorageLogicalDrive", + "CapacityMiB": 286070, + "Description": "HP Smart Storage Logical Drive View", + "Id": "1", + "LogicalDriveEncryption": false, + "LogicalDriveName": "01908CF2PDNMF0ARH6X0FN6FE9", + "LogicalDriveNumber": 1, + "LogicalDriveType": "Data", + "Name": "HpSmartStorageLogicalDrive", + "Raid": "0", + "Status": { + "Health": "OK", + "State": "Enabled" + }, + "StripeSizeBytes": 262144, + "Type": "HpSmartStorageLogicalDrive.1.1.0", + "VolumeUniqueIdentifier": "600508B1001CC8A5FF549462C7B8412A", + "links": { + "DataDrives": { + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers/0/\ +LogicalDrives/1/DataDrives" + }, + "self": { + "href": "/rest/v1/Systems/1/SmartStorage/ArrayControllers/0/\ +LogicalDrives/1" + } + } +}] +""" diff --git a/proliantutils/tests/ilo/test_ris.py b/proliantutils/tests/ilo/test_ris.py index 3e64d7eb..5fc69aba 100755 --- a/proliantutils/tests/ilo/test_ris.py +++ b/proliantutils/tests/ilo/test_ris.py @@ -437,6 +437,8 @@ class IloRisTestCase(testtools.TestCase): validate_mock.assert_called_once_with(ris_outputs.GET_HEADERS, settings_uri) + @mock.patch.object(ris.RISOperations, '_get_logical_raid_levels') + @mock.patch.object(ris.RISOperations, '_get_drive_type_and_speed') @mock.patch.object(ris.RISOperations, '_check_iscsi_rest_patch_allowed') @mock.patch.object(ris.RISOperations, '_get_bios_setting') @mock.patch.object(ris.RISOperations, '_get_nvdimm_n_status') @@ -452,7 +454,8 @@ class IloRisTestCase(testtools.TestCase): def test_get_server_capabilities(self, get_details_mock, ilo_firm_mock, secure_mock, boot_mode_mock, gpu_mock, tpm_mock, cpu_vt_mock, nvdimm_n_mock, - bios_sriov_mock, iscsi_boot_mock): + bios_sriov_mock, iscsi_boot_mock, + drive_mock, raid_mock): host_details = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP) get_details_mock.return_value = host_details ilo_firm_mock.return_value = {'ilo_firmware_version': 'iLO 4 v2.20'} @@ -465,6 +468,9 @@ class IloRisTestCase(testtools.TestCase): tpm_mock.return_value = True bios_sriov_mock.return_value = 'Disabled' iscsi_boot_mock.return_value = '/rest/v1/systems/1/bios/iScsi' + drive_mock.return_value = {'has_rotational': True, + 'rotational_drive_4800_rpm': True} + raid_mock.return_value = {'logical_raid_volume_0': 'true'} expected_caps = {'secure_boot': 'true', 'ilo_firmware_version': 'iLO 4 v2.20', 'rom_firmware_version': u'I36 v1.40 (01/28/2015)', @@ -475,10 +481,15 @@ class IloRisTestCase(testtools.TestCase): 'nvdimm_n': 'true', 'boot_mode_bios': 'false', 'boot_mode_uefi': 'true', - 'iscsi_boot': 'true'} + 'iscsi_boot': 'true', + 'has_rotational': True, + 'rotational_drive_4800_rpm': True, + 'logical_raid_volume_0': 'true'} capabilities = self.client.get_server_capabilities() self.assertEqual(expected_caps, capabilities) + @mock.patch.object(ris.RISOperations, '_get_logical_raid_levels') + @mock.patch.object(ris.RISOperations, '_get_drive_type_and_speed') @mock.patch.object(ris.RISOperations, '_check_iscsi_rest_patch_allowed') @mock.patch.object(ris.RISOperations, '_get_bios_setting') @mock.patch.object(ris.RISOperations, '_get_nvdimm_n_status') @@ -494,7 +505,7 @@ class IloRisTestCase(testtools.TestCase): def test_get_server_capabilities_tp_absent( self, get_details_mock, ilo_firm_mock, secure_mock, boot_mode_mock, gpu_mock, tpm_mock, cpu_vt_mock, nvdimm_n_mock, bios_sriov_mock, - iscsi_mock): + iscsi_mock, drive_mock, raid_mock): host_details = json.loads(ris_outputs.RESPONSE_BODY_FOR_REST_OP) get_details_mock.return_value = host_details ilo_firm_mock.return_value = {'ilo_firmware_version': 'iLO 4 v2.20'} @@ -507,6 +518,9 @@ class IloRisTestCase(testtools.TestCase): cpu_vt_mock.return_value = True bios_sriov_mock.return_value = 'Enabled' iscsi_mock.side_effect = exception.IloCommandNotSupportedError('error') + drive_mock.return_value = {'has_rotational': True, + 'rotational_drive_4800_rpm': True} + raid_mock.return_value = {'logical_raid_volume_0': 'true'} expected_caps = {'secure_boot': 'true', 'ilo_firmware_version': 'iLO 4 v2.20', 'rom_firmware_version': u'I36 v1.40 (01/28/2015)', @@ -516,7 +530,10 @@ class IloRisTestCase(testtools.TestCase): 'nvdimm_n': 'true', 'sriov_enabled': 'true', 'boot_mode_bios': 'true', - 'boot_mode_uefi': 'true'} + 'boot_mode_uefi': 'true', + 'has_rotational': True, + 'rotational_drive_4800_rpm': True, + 'logical_raid_volume_0': 'true'} capabilities = self.client.get_server_capabilities() self.assertEqual(expected_caps, capabilities) @@ -1775,6 +1792,160 @@ class TestRISOperationsPrivateMethods(testtools.TestCase): self.client._get_pci_devices) get_details_mock.assert_called_once_with() + @mock.patch.object(ris.RISOperations, '_rest_get') + @mock.patch.object(ris.RISOperations, '_get_host_details') + def test__get_storage_resource(self, get_host_details_mock, get_mock): + system_data = json.loads(ris_outputs.REST_GET_SMART_STORAGE) + get_host_details_mock.return_value = system_data + storage_uri = '/rest/v1/Systems/1/SmartStorage' + storage_settings = json.loads(ris_outputs.STORAGE_SETTINGS) + + get_mock.return_value = (200, ris_outputs.GET_HEADERS, + storage_settings) + self.client._get_storage_resource() + get_mock.assert_called_once_with(storage_uri) + + @mock.patch.object(ris.RISOperations, '_rest_get') + @mock.patch.object(ris.RISOperations, '_get_host_details') + def test__get_storage_resource_fail(self, get_host_details_mock, + get_mock): + system_data = json.loads(ris_outputs.REST_GET_SMART_STORAGE) + get_host_details_mock.return_value = system_data + storage_uri = '/rest/v1/Systems/1/SmartStorage' + storage_settings = json.loads(ris_outputs.STORAGE_SETTINGS) + + get_mock.return_value = (301, ris_outputs.GET_HEADERS, + storage_settings) + self.assertRaises(exception.IloError, + self.client._get_storage_resource) + get_mock.assert_called_once_with(storage_uri) + + @mock.patch.object(ris.RISOperations, '_get_host_details') + def test__get_storage_resource_not_supported(self, + get_host_details_mock): + system_data = json.loads(ris_outputs.REST_GET_SMART_STORAGE) + del system_data['Oem']['Hp']['links']['SmartStorage'] + get_host_details_mock.return_value = system_data + self.assertRaises(exception.IloCommandNotSupportedError, + self.client._get_storage_resource) + get_host_details_mock.assert_called_once_with() + + @mock.patch.object(ris.RISOperations, '_rest_get') + @mock.patch.object(ris.RISOperations, '_get_storage_resource') + def test__get_array_controller_resource(self, storage_mock, get_mock): + storage_data = json.loads(ris_outputs.STORAGE_SETTINGS) + storage_uri = '/rest/v1/Systems/1/SmartStorage' + storage_mock.return_value = (ris_outputs.GET_HEADERS, + storage_uri, + storage_data) + array_uri = '/rest/v1/Systems/1/SmartStorage/ArrayControllers' + array_settings = json.loads(ris_outputs.ARRAY_SETTINGS) + + get_mock.return_value = (200, ris_outputs.GET_HEADERS, + array_settings) + self.client._get_array_controller_resource() + get_mock.assert_called_once_with(array_uri) + + @mock.patch.object(ris.RISOperations, '_rest_get') + @mock.patch.object(ris.RISOperations, '_get_storage_resource') + def test__get_array_controller_resource_fail(self, storage_mock, + get_mock): + storage_data = json.loads(ris_outputs.STORAGE_SETTINGS) + storage_uri = '/rest/v1/Systems/1/SmartStorage' + storage_mock.return_value = (ris_outputs.GET_HEADERS, + storage_uri, + storage_data) + array_uri = '/rest/v1/Systems/1/SmartStorage/ArrayControllers' + array_settings = json.loads(ris_outputs.ARRAY_SETTINGS) + + get_mock.return_value = (301, ris_outputs.GET_HEADERS, + array_settings) + self.assertRaises(exception.IloError, + self.client._get_array_controller_resource) + get_mock.assert_called_once_with(array_uri) + + @mock.patch.object(ris.RISOperations, '_get_storage_resource') + def test__get_array_controller_resource_not_supported(self, + storage_mock): + storage_data = json.loads(ris_outputs.STORAGE_SETTINGS) + storage_uri = '/rest/v1/Systems/1/SmartStorage' + del storage_data['links']['ArrayControllers'] + storage_mock.return_value = (ris_outputs.GET_HEADERS, + storage_uri, + storage_data) + self.assertRaises(exception.IloCommandNotSupportedError, + self.client._get_array_controller_resource) + storage_mock.assert_called_once_with() + + @mock.patch.object(ris.RISOperations, '_get_array_controller_resource') + def test__create_list_of_array_controllers(self, array_mock): + array_data = json.loads(ris_outputs.ARRAY_SETTINGS) + array_uri = '/rest/v1/Systems/1/SmartStorage/ArrayControllers' + array_mock.return_value = (ris_outputs.GET_HEADERS, + array_uri, + array_data) + expected_uri_links = ( + [{u'href': u'/rest/v1/Systems/1/SmartStorage/ArrayControllers/0'}]) + uri_links = self.client._create_list_of_array_controllers() + self.assertEqual(expected_uri_links, uri_links) + array_mock.assert_called_once_with() + + @mock.patch.object(ris.RISOperations, '_get_array_controller_resource') + def test__create_list_of_array_controllers_fail(self, array_mock): + array_data = json.loads(ris_outputs.ARRAY_SETTINGS) + array_uri = '/rest/v1/Systems/1/SmartStorage/ArrayControllers' + del array_data['links']['Member'] + array_mock.return_value = (ris_outputs.GET_HEADERS, + array_uri, + array_data) + self.assertRaises(exception.IloCommandNotSupportedError, + self.client._create_list_of_array_controllers) + array_mock.assert_called_once_with() + + @mock.patch.object(ris.RISOperations, '_get_physical_drive_resource') + def test__get_drive_type_and_speed(self, disk_details_mock): + disk_details_mock.return_value = ( + json.loads(ris_outputs.DISK_DETAILS_LIST)) + expected_out = {'has_rotational': 'true', + 'rotational_drive_10000_rpm': 'true'} + out = self.client._get_drive_type_and_speed() + self.assertEqual(expected_out, out) + disk_details_mock.assert_called_once_with() + + @mock.patch.object(ris.RISOperations, '_create_list_of_array_controllers') + @mock.patch.object(ris.RISOperations, '_rest_get') + def test__get_drive_resource_physical(self, get_mock, array_mock): + array_mock.return_value = ( + [{u'href': u'/rest/v1/Systems/1/SmartStorage/ArrayControllers/0'}]) + get_mock.side_effect = [(ris_outputs.GET_HEADERS, 'xyz', + json.loads(ris_outputs.ARRAY_MEM_SETTINGS)), + (ris_outputs.GET_HEADERS, 'xyz', + json.loads(ris_outputs.DISK_COLLECTION)), + (ris_outputs.GET_HEADERS, 'xyz', + json.loads(ris_outputs.DISK_DETAILS_LIST))] + out = self.client._get_physical_drive_resource() + expected_out = [] + expected_out.append(json.loads(ris_outputs.DISK_DETAILS_LIST)) + self.assertEqual(expected_out, out) + array_mock.assert_called_once_with() + + @mock.patch.object(ris.RISOperations, '_create_list_of_array_controllers') + @mock.patch.object(ris.RISOperations, '_rest_get') + def test__get_drive_resource_logical(self, get_mock, array_mock): + array_mock.return_value = ( + [{u'href': u'/rest/v1/Systems/1/SmartStorage/ArrayControllers/0'}]) + get_mock.side_effect = [(ris_outputs.GET_HEADERS, 'xyz', + json.loads(ris_outputs.ARRAY_MEM_SETTINGS)), + (ris_outputs.GET_HEADERS, 'xyz', + json.loads(ris_outputs.LOGICAL_COLLECTION)), + (ris_outputs.GET_HEADERS, 'xyz', + json.loads(ris_outputs.LOGICAL_DETAILS))] + out = self.client._get_logical_drive_resource() + expected_out = [] + expected_out.append(json.loads(ris_outputs.LOGICAL_DETAILS)) + self.assertEqual(expected_out, out) + array_mock.assert_called_once_with() + @mock.patch.object(ris.RISOperations, '_get_pci_devices') def test__get_gpu_pci_devices(self, pci_mock): pci_mock.return_value = json.loads(ris_outputs.PCI_DEVICE_DETAILS)