Redfish: Adds 'read_raid_configuration' API to get current raid config
This commit adds functionality to verify the success of raid create or delete operation and gets the current raid configuration on SmartStorageConfig redfish based iLO. Co-Authored-By: Paresh Sao <paresh.sao@hpe.com> Change-Id: I9f546e8ef87229f442dc3855042cbe3ac3a198f8
This commit is contained in:
parent
8bda342451
commit
72ba876a58
|
@ -48,6 +48,7 @@ SUPPORTED_RIS_METHODS = [
|
|||
'inject_nmi',
|
||||
'insert_virtual_media',
|
||||
'press_pwr_btn',
|
||||
'read_raid_configuration',
|
||||
'reset_bios_to_default',
|
||||
'reset_ilo_credential',
|
||||
'reset_secure_boot_keys',
|
||||
|
@ -96,6 +97,7 @@ SUPPORTED_REDFISH_METHODS = [
|
|||
'set_one_time_boot',
|
||||
'update_persistent_boot',
|
||||
'set_pending_boot_mode',
|
||||
'read_raid_configuration',
|
||||
'reset_ilo_credential',
|
||||
'reset_bios_to_default',
|
||||
'get_secure_boot_mode',
|
||||
|
@ -110,7 +112,7 @@ SUPPORTED_REDFISH_METHODS = [
|
|||
'unset_iscsi_boot_info',
|
||||
'unset_iscsi_info',
|
||||
'get_iscsi_initiator_info',
|
||||
'set_iscsi_initiator_info',
|
||||
'set_iscsi_initiator_info'
|
||||
]
|
||||
|
||||
LOG = log.get_logger(__name__)
|
||||
|
@ -669,6 +671,24 @@ class IloClient(operations.IloOperations):
|
|||
"""
|
||||
return self._call_method('create_raid_configuration', raid_config)
|
||||
|
||||
def read_raid_configuration(self, raid_config=None):
|
||||
"""Read the logical drives from the system.
|
||||
|
||||
:param raid_config: None in case of post-delete read or in case of
|
||||
post-create a dictionary containing target raid
|
||||
configuration data. This data stucture should be as
|
||||
follows:
|
||||
raid_config = {'logical_disks': [{'raid_level': 1,
|
||||
'size_gb': 100, 'physical_disks': ['6I:1:5'],
|
||||
'controller': 'HPE Smart Array P408i-a SR Gen10'},
|
||||
<info-for-logical-disk-2>]}
|
||||
:raises: IloError, on an error from iLO.
|
||||
:raises: IloCommandNotSupportedError, if the command is not supported
|
||||
on the server.
|
||||
:returns: A dictionary containing list of logical disks
|
||||
"""
|
||||
return self._call_method('read_raid_configuration', raid_config)
|
||||
|
||||
def update_firmware(self, firmware_url, component_type):
|
||||
"""Updates the given firmware on the server
|
||||
|
||||
|
|
|
@ -446,6 +446,25 @@ class IloOperations(object):
|
|||
"""
|
||||
raise exception.IloCommandNotSupportedError(ERRMSG)
|
||||
|
||||
def read_raid_configuration(self, raid_config=None):
|
||||
"""Read the logical drives from the system
|
||||
|
||||
Read raid configuration of the hardware.
|
||||
|
||||
:param raid_config: None in case of post-delete read or in case of
|
||||
post-create a dictionary containing target raid
|
||||
configuration data. This data stucture should be as
|
||||
follows:
|
||||
raid_config = {'logical_disks': [{'raid_level': 1,
|
||||
'size_gb': 100, 'physical_disks': ['6I:1:5'],
|
||||
'controller': 'HPE Smart Array P408i-a SR Gen10'},
|
||||
<info-for-logical-disk-2>]}
|
||||
:raises: IloError, on an error from iLO.
|
||||
:raises: IloCommandNotSupportedError, if the command is not supported
|
||||
on the server.
|
||||
"""
|
||||
raise exception.IloCommandNotSupportedError(ERRMSG)
|
||||
|
||||
def delete_raid_configuration(self):
|
||||
"""Deletes the logical drives from the system
|
||||
|
||||
|
|
|
@ -1209,6 +1209,24 @@ class RIBCLOperations(operations.IloOperations):
|
|||
"""
|
||||
self._raise_command_not_supported("get_host_post_state")
|
||||
|
||||
def read_raid_configuration(self, raid_config=None):
|
||||
"""Read the logical drives from the system
|
||||
|
||||
Read raid configuration of the hardware.
|
||||
|
||||
:param raid_config: None in case of post-delete read or in case of
|
||||
post-create a dictionary containing target raid
|
||||
configuration data. This data stucture should be as
|
||||
follows:
|
||||
raid_config = {'logical_disks': [{'raid_level': 1,
|
||||
'size_gb': 100, 'physical_disks': ['6I:1:5'],
|
||||
'controller': 'HPE Smart Array P408i-a SR Gen10'},
|
||||
<info-for-logical-disk-2>]}
|
||||
:raises: IloCommandNotSupportedError, if the command is not supported
|
||||
on the server.
|
||||
"""
|
||||
self._raise_command_not_supported("read_raid_configuration")
|
||||
|
||||
def delete_raid_configuration(self):
|
||||
"""Delete the raid configuration on the hardware.
|
||||
|
||||
|
|
|
@ -1981,6 +1981,24 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
|
|||
{'method': method, 'platform': platform})
|
||||
raise (exception.IloCommandNotSupportedError(msg))
|
||||
|
||||
def read_raid_configuration(self, raid_config=None):
|
||||
"""Read the logical drives from the system
|
||||
|
||||
Read raid configuration of the hardware.
|
||||
|
||||
:param raid_config: None in case of post-delete read or in case of
|
||||
post-create a dictionary containing target raid
|
||||
configuration data. This data stucture should be as
|
||||
follows:
|
||||
raid_config = {'logical_disks': [{'raid_level': 1,
|
||||
'size_gb': 100, 'physical_disks': ['6I:1:5'],
|
||||
'controller': 'HPE Smart Array P408i-a SR Gen10'},
|
||||
<info-for-logical-disk-2>]}
|
||||
:raises: IloCommandNotSupportedError, if the command is not supported
|
||||
on the server.
|
||||
"""
|
||||
self._raise_command_not_supported("read_raid_configuration")
|
||||
|
||||
def delete_raid_configuration(self):
|
||||
"""Delete the raid configuration on the hardware.
|
||||
|
||||
|
|
|
@ -1052,6 +1052,23 @@ class RedfishOperations(operations.IloOperations):
|
|||
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
|
||||
return GET_POST_STATE_MAP.get(sushy_system.post_state)
|
||||
|
||||
def read_raid_configuration(self, raid_config=None):
|
||||
"""Read the logical drives from the system
|
||||
|
||||
:param raid_config: None in case of post-delete read or in case of
|
||||
post-create a dictionary containing target raid
|
||||
configuration data. This data stucture should be as
|
||||
follows:
|
||||
raid_config = {'logical_disks': [{'raid_level': 1,
|
||||
'size_gb': 100, 'physical_disks': ['6I:1:5'],
|
||||
'controller': 'HPE Smart Array P408i-a SR Gen10'},
|
||||
<info-for-logical-disk-2>]}
|
||||
:raises: IloError, on an error from iLO.
|
||||
:returns: A dictionary containing list of logical disks
|
||||
"""
|
||||
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
|
||||
return sushy_system.read_raid(raid_config=raid_config)
|
||||
|
||||
def delete_raid_configuration(self):
|
||||
"""Delete the raid configuration on the hardware."""
|
||||
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
|
||||
|
|
|
@ -33,13 +33,89 @@ class HPESmartStorageConfig(base.ResourceBase):
|
|||
|
||||
controller_id = base.Field("Id")
|
||||
|
||||
smart_storage_config_message = base.Field(['@Redfish.Settings',
|
||||
'Messages'])
|
||||
|
||||
logical_drives = LogicalDriveListField("LogicalDrives", default=[])
|
||||
|
||||
location = base.Field("Location")
|
||||
|
||||
physical_drives = base.Field("PhysicalDrives", adapter=list, default=None)
|
||||
|
||||
settings_uri = base.Field(["@Redfish.Settings",
|
||||
"SettingsObject", "@odata.id"])
|
||||
|
||||
def _generic_format(self, raid_config, controller=None):
|
||||
"""Convert redfish data of current raid config to generic format.
|
||||
|
||||
:param raid_config: Raid configuration dictionary
|
||||
:param controller: Array controller model in post_create read else
|
||||
None
|
||||
:returns: current raid config.
|
||||
"""
|
||||
logical_drives = raid_config["LogicalDrives"]
|
||||
logical_disks = []
|
||||
controller = controller
|
||||
for ld in logical_drives:
|
||||
prop = {'size_gb': ld['CapacityGiB'],
|
||||
'raid_level': ld['Raid'].strip('Raid'),
|
||||
'root_device_hint': {
|
||||
'wwn': '0x' + ld['VolumeUniqueIdentifier']},
|
||||
'controller': controller,
|
||||
'physical_disks': ld['DataDrives'],
|
||||
'volume_name': ld['LogicalDriveName']}
|
||||
logical_disks.append(prop)
|
||||
return logical_disks
|
||||
|
||||
def _check_smart_storage_message(self):
|
||||
"""Check for smart storage message.
|
||||
|
||||
:returns: result, raid_message
|
||||
"""
|
||||
ssc_mesg = self.smart_storage_config_message
|
||||
result = True
|
||||
raid_message = ""
|
||||
for element in ssc_mesg:
|
||||
if "Success" not in element['MessageId']:
|
||||
result = False
|
||||
raid_message = element['MessageId']
|
||||
return result, raid_message
|
||||
|
||||
def read_raid(self, controller=None):
|
||||
"""Get the current RAID configuration from the system.
|
||||
|
||||
:param controller: If controller model its post-create read else
|
||||
post-delete
|
||||
:returns: current raid config.
|
||||
"""
|
||||
if controller:
|
||||
if not self.logical_drives:
|
||||
msg = ('No logical drives found on the controller')
|
||||
LOG.debug(msg)
|
||||
raise exception.IloLogicalDriveNotFoundError(msg)
|
||||
raid_op = 'create_raid'
|
||||
else:
|
||||
raid_op = 'delete_raid'
|
||||
|
||||
result, raid_message = self._check_smart_storage_message()
|
||||
|
||||
if result:
|
||||
configured_raid_settings = self._conn.get(self.settings_uri)
|
||||
raid_data = {
|
||||
'logical_disks': self._generic_format(
|
||||
configured_raid_settings.json(), controller=controller)}
|
||||
return raid_data
|
||||
else:
|
||||
if self.physical_drives is None or not raid_message:
|
||||
# This controller is not configured or controller
|
||||
# not used in raid operation
|
||||
return
|
||||
else:
|
||||
msg = ('Failed to perform the %(opr)s operation '
|
||||
'successfully. Error - %(error)s'
|
||||
% {'opr': raid_op, 'error': str(raid_message)})
|
||||
raise exception.IloError(msg)
|
||||
|
||||
def delete_raid(self):
|
||||
"""Clears the RAID configuration from the system.
|
||||
|
||||
|
|
|
@ -344,10 +344,11 @@ class HPESystem(system.System):
|
|||
"""
|
||||
ac = self.smart_storage.array_controllers.array_controller_by_model(
|
||||
controller_model)
|
||||
for ssc_id in self.smart_storage_config_identities:
|
||||
ssc_obj = self.get_smart_storage_config(ssc_id)
|
||||
if ac.location == ssc_obj.location:
|
||||
return ssc_obj
|
||||
if ac:
|
||||
for ssc_id in self.smart_storage_config_identities:
|
||||
ssc_obj = self.get_smart_storage_config(ssc_id)
|
||||
if ac.location == ssc_obj.location:
|
||||
return ssc_obj
|
||||
|
||||
def check_smart_storage_config_ids(self):
|
||||
"""Check SmartStorageConfig controllers is there in hardware.
|
||||
|
@ -454,3 +455,96 @@ class HPESystem(system.System):
|
|||
'raid configuration for one or more controllers with '
|
||||
'Error: %(error)s' % {'error': str(any_exceptions)})
|
||||
raise exception.IloError(msg)
|
||||
|
||||
def _post_create_read_raid(self, raid_config):
|
||||
"""Read the logical drives from the system after post-create raid
|
||||
|
||||
:param raid_config: A dictionary containing target raid configuration
|
||||
data. This data stucture should be as follows:
|
||||
raid_config = {'logical_disks': [{'raid_level': 1,
|
||||
'size_gb': 100, 'physical_disks': ['6I:1:5'],
|
||||
'controller': 'HPE Smart Array P408i-a SR Gen10'},
|
||||
<info-for-logical-disk-2>]}
|
||||
:raises: IloLogicalDriveNotFoundError, if no controllers are configured
|
||||
:raises: IloError, if any error form iLO
|
||||
:returns: A dictionary containing list of logical disks
|
||||
"""
|
||||
controllers = self._parse_raid_config_data(raid_config)
|
||||
ld_exc_count = 0
|
||||
any_exceptions = []
|
||||
config = {'logical_disks': []}
|
||||
for controller in controllers:
|
||||
try:
|
||||
ssc_obj = (
|
||||
self._get_smart_storage_config_by_controller_model(
|
||||
controller))
|
||||
if ssc_obj:
|
||||
result = ssc_obj.read_raid(controller=controller)
|
||||
config['logical_disks'].extend(result['logical_disks'])
|
||||
except exception.IloLogicalDriveNotFoundError as e:
|
||||
ld_exc_count += 1
|
||||
except sushy.exceptions.SushyError as e:
|
||||
any_exceptions.append((controller, str(e)))
|
||||
|
||||
if ld_exc_count == len(controllers):
|
||||
msg = 'No logical drives are found in any controllers.'
|
||||
raise exception.IloLogicalDriveNotFoundError(msg)
|
||||
if any_exceptions:
|
||||
msg = ('The Redfish controller failed to read the '
|
||||
'raid configuration in one or more controllers with '
|
||||
'Error: %(error)s' % {'error': str(any_exceptions)})
|
||||
raise exception.IloError(msg)
|
||||
return config
|
||||
|
||||
def _post_delete_read_raid(self):
|
||||
"""Read the logical drives from the system after post-delete raid
|
||||
|
||||
:raises: IloError, if any error form iLO
|
||||
:returns: Empty dictionary with format: {'logical_disks': []}
|
||||
"""
|
||||
any_exceptions = []
|
||||
ssc_ids = self.smart_storage_config_identities
|
||||
config = {'logical_disks': []}
|
||||
for ssc_id in ssc_ids:
|
||||
try:
|
||||
ssc_obj = self.get_smart_storage_config(ssc_id)
|
||||
ac_obj = (
|
||||
self.smart_storage.array_controllers.
|
||||
array_controller_by_location(ssc_obj.location))
|
||||
if ac_obj:
|
||||
model = ac_obj.model
|
||||
result = ssc_obj.read_raid()
|
||||
if result:
|
||||
config['logical_disks'].extend(result['logical_disks'])
|
||||
except sushy.exceptions.SushyError as e:
|
||||
any_exceptions.append((model, str(e)))
|
||||
|
||||
if any_exceptions:
|
||||
msg = ('The Redfish controller failed to read the '
|
||||
'raid configuration in one or more controllers with '
|
||||
'Error: %(error)s' % {'error': str(any_exceptions)})
|
||||
raise exception.IloError(msg)
|
||||
return config
|
||||
|
||||
def read_raid(self, raid_config=None):
|
||||
"""Read the logical drives from the system
|
||||
|
||||
:param raid_config: None or a dictionary containing target raid
|
||||
configuration data. This data stucture should be as
|
||||
follows:
|
||||
raid_config = {'logical_disks': [{'raid_level': 1,
|
||||
'size_gb': 100, 'physical_disks': ['6I:1:5'],
|
||||
'controller': 'HPE Smart Array P408i-a SR Gen10'},
|
||||
<info-for-logical-disk-2>]}
|
||||
:returns: A dictionary containing list of logical disks
|
||||
"""
|
||||
self.check_smart_storage_config_ids()
|
||||
if raid_config:
|
||||
# When read called after create raid, user can pass raid config
|
||||
# as a input
|
||||
result = self._post_create_read_raid(raid_config=raid_config)
|
||||
else:
|
||||
# When read called after delete raid, there will be no input
|
||||
# passed by user then
|
||||
result = self._post_delete_read_raid()
|
||||
return result
|
||||
|
|
|
@ -811,6 +811,38 @@ class IloClientTestCase(testtools.TestCase):
|
|||
self.client.create_raid_configuration,
|
||||
raid_config)
|
||||
|
||||
@mock.patch.object(client.IloClient, '_call_method')
|
||||
def test_read_raid_configuration(self, call_mock):
|
||||
ld1 = {"size_gb": 150, "raid_level": '0', "is_root_volume": True}
|
||||
raid_config = {"logical_disks": [ld1]}
|
||||
self.client.read_raid_configuration(raid_config)
|
||||
call_mock.assert_called_once_with('read_raid_configuration',
|
||||
raid_config)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, 'get_product_name')
|
||||
def test_read_raid_configuration_gen9(self, get_product_mock):
|
||||
self.client.model = 'Gen9'
|
||||
ld1 = {"size_gb": 150, "raid_level": '0', "is_root_volume": True}
|
||||
raid_config = {"logical_disks": [ld1]}
|
||||
get_product_mock.return_value = 'ProLiant BL460c Gen9'
|
||||
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||
'`read_raid_configuration` is not supported '
|
||||
'on ProLiant BL460c Gen9',
|
||||
self.client.read_raid_configuration,
|
||||
raid_config)
|
||||
|
||||
@mock.patch.object(ribcl.RIBCLOperations, 'get_product_name')
|
||||
def test_read_raid_configuration_gen8(self, get_product_mock):
|
||||
self.client.model = 'Gen8'
|
||||
ld1 = {"size_gb": 150, "raid_level": '0', "is_root_volume": True}
|
||||
raid_config = {"logical_disks": [ld1]}
|
||||
get_product_mock.return_value = 'ProLiant DL380 G8'
|
||||
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||
'`read_raid_configuration` is not supported '
|
||||
'on ProLiant DL380 G8',
|
||||
self.client.read_raid_configuration,
|
||||
raid_config)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, 'eject_virtual_media')
|
||||
def test_eject_virtual_media_gen9(self, eject_virtual_media_mock):
|
||||
self.client.model = 'Gen9'
|
||||
|
|
|
@ -1055,6 +1055,16 @@ class IloRibclTestCaseBeforeRisSupport(unittest.TestCase):
|
|||
'ProLiant DL380 G7',
|
||||
self.ilo.get_host_post_state)
|
||||
|
||||
@mock.patch.object(ribcl.RIBCLOperations, 'get_product_name')
|
||||
def test_read_raid_configuration(self, product_name_mock):
|
||||
ld1 = {"size_gb": 150, "raid_level": '0', "is_root_volume": True}
|
||||
raid_config = {"logical_disks": [ld1]}
|
||||
product_name_mock.return_value = constants.GET_PRODUCT_NAME
|
||||
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||
'ProLiant DL380 G7',
|
||||
self.ilo.read_raid_configuration,
|
||||
raid_config)
|
||||
|
||||
@mock.patch.object(ribcl.RIBCLOperations, 'get_product_name')
|
||||
def test_delete_raid_configuration(self, product_name_mock):
|
||||
product_name_mock.return_value = constants.GET_PRODUCT_NAME
|
||||
|
|
|
@ -2552,6 +2552,16 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
|
|||
self.assertEqual(ret, expt_ret)
|
||||
get_array_mock.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(ris.RISOperations, 'get_product_name')
|
||||
def test_read_raid_configuration(self, product_name_mock):
|
||||
ld1 = {"size_gb": 150, "raid_level": '0', "is_root_volume": True}
|
||||
raid_config = {"logical_disks": [ld1]}
|
||||
product_name_mock.return_value = 'ProLiant BL460c Gen9'
|
||||
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||
'ProLiant BL460c Gen9',
|
||||
self.client.read_raid_configuration,
|
||||
raid_config)
|
||||
|
||||
@mock.patch.object(ris.RISOperations, 'get_product_name')
|
||||
def test_delete_raid_configuration(self, product_name_mock):
|
||||
product_name_mock.return_value = 'ProLiant BL460c Gen9'
|
||||
|
|
|
@ -38,8 +38,12 @@ class HPESmartStorageConfigTestCase(testtools.TestCase):
|
|||
redfish_version='1.0.2')
|
||||
|
||||
def test_attributes(self):
|
||||
physical_drive = [{'LegacyBootPriority': 'None',
|
||||
'Location': '1I:1:2',
|
||||
'LocationFormat': 'ControllerPort:Box:Bay'}]
|
||||
self.assertEqual('smartstorageconfig', self.ssc_inst.controller_id)
|
||||
self.assertEqual('Slot 0', self.ssc_inst.location)
|
||||
self.assertEqual(physical_drive, self.ssc_inst.physical_drives)
|
||||
self.assertEqual(
|
||||
'600508B1001C045A9BAAC9F4F49498AE',
|
||||
self.ssc_inst.logical_drives[0].volume_unique_identifier)
|
||||
|
@ -102,3 +106,95 @@ class HPESmartStorageConfigTestCase(testtools.TestCase):
|
|||
validate_mock.assert_called_once_with(raid_config)
|
||||
self.ssc_inst._conn.put.assert_called_once_with(settings_uri,
|
||||
data=data)
|
||||
|
||||
def test__generic_format_delete_scenario(self):
|
||||
expected_data = []
|
||||
raid_config = {"LogicalDrives": []}
|
||||
self.assertEqual(expected_data,
|
||||
self.ssc_inst._generic_format(raid_config))
|
||||
|
||||
def test__generic_format_create_scenario(self):
|
||||
expected_data = [{'controller': 'HPE Smart Array P408i-p SR Gen10',
|
||||
'physical_disks': [u'2I:1:2', u'2I:1:1'],
|
||||
'raid_level': u'0',
|
||||
'root_device_hint': {
|
||||
'wwn': u'0x600508B1001C045A9BAAC9F4F49498AE'},
|
||||
'size_gb': 2235,
|
||||
'volume_name': u'01A27294PFJHD0ARCA218H 63E0'}]
|
||||
result = self.ssc_inst._generic_format(
|
||||
self.ssc_inst.json, controller='HPE Smart Array P408i-p SR Gen10')
|
||||
self.assertEqual(expected_data, result)
|
||||
|
||||
def test__check_smart_storage_message(self):
|
||||
result, mesg = self.ssc_inst._check_smart_storage_message()
|
||||
self.assertEqual(True, result)
|
||||
self.assertEqual("", mesg)
|
||||
|
||||
@mock.patch.object(smart_storage_config.HPESmartStorageConfig,
|
||||
'_check_smart_storage_message', autospec=True)
|
||||
@mock.patch.object(smart_storage_config.HPESmartStorageConfig,
|
||||
'_generic_format', autospec=True)
|
||||
def test_read_raid_post_create(self, format_mock, message_mock):
|
||||
message_mock.return_value = True, 'Success'
|
||||
ld1 = {"size_gb": 150, "raid_level": '0', "is_root_volume": True}
|
||||
type(self.ssc_inst).logical_drives = mock.PropertyMock(
|
||||
return_value=[ld1])
|
||||
ld1['controller'] = 'HPE Smart Array P408i-p SR Gen10'
|
||||
format_mock.return_value = [ld1]
|
||||
expected = {'logical_disks': [ld1]}
|
||||
self.assertEqual(
|
||||
expected, self.ssc_inst.read_raid(controller=ld1['controller']))
|
||||
self.assertTrue(message_mock.called)
|
||||
self.assertTrue(format_mock.called)
|
||||
|
||||
@mock.patch.object(smart_storage_config.HPESmartStorageConfig,
|
||||
'_check_smart_storage_message', autospec=True)
|
||||
@mock.patch.object(smart_storage_config.HPESmartStorageConfig,
|
||||
'_generic_format', autospec=True)
|
||||
def test_read_raid_post_delete(self, format_mock, message_mock):
|
||||
message_mock.return_value = True, 'Success'
|
||||
format_mock.return_value = []
|
||||
type(self.ssc_inst).logical_drives = mock.PropertyMock(
|
||||
return_value=[])
|
||||
expected = {'logical_disks': []}
|
||||
self.assertEqual(expected, self.ssc_inst.read_raid())
|
||||
self.assertTrue(message_mock.called)
|
||||
self.assertTrue(format_mock.called)
|
||||
|
||||
@mock.patch.object(smart_storage_config.HPESmartStorageConfig,
|
||||
'_check_smart_storage_message', autospec=True)
|
||||
def test_read_raid_failed(self, message_mock):
|
||||
ld1 = {"size_gb": 150, "raid_level": '0', "is_root_volume": True}
|
||||
type(self.ssc_inst).logical_drives = mock.PropertyMock(
|
||||
return_value=[ld1])
|
||||
ld1['controller'] = 'HPE Smart Array P408i-p SR Gen10'
|
||||
physical_drive = [{'LegacyBootPriority': 'None',
|
||||
'Location': '1I:1:2',
|
||||
'LocationFormat': 'ControllerPort:Box:Bay'}]
|
||||
type(self.ssc_inst).physical_drives = mock.PropertyMock(
|
||||
return_value=physical_drive)
|
||||
message_mock.return_value = False, 'err_mesg'
|
||||
self.assertRaisesRegexp(
|
||||
exception.IloError,
|
||||
'Failed to perform the create_raid operation successfully',
|
||||
self.ssc_inst.read_raid, ld1['controller'])
|
||||
|
||||
def test_read_raid_logical_drive_not_found(self):
|
||||
type(self.ssc_inst).logical_drives = mock.PropertyMock(
|
||||
return_value=[])
|
||||
model = 'HPE Smart Array P408i-p SR Gen10'
|
||||
self.assertRaises(exception.IloLogicalDriveNotFoundError,
|
||||
self.ssc_inst.read_raid, model)
|
||||
|
||||
@mock.patch.object(smart_storage_config.HPESmartStorageConfig,
|
||||
'_check_smart_storage_message', autospec=True)
|
||||
@mock.patch.object(smart_storage_config.HPESmartStorageConfig,
|
||||
'_generic_format', autospec=True)
|
||||
def test_read_raid_controller_not_configured_post_delete(
|
||||
self, format_mock, message_mock):
|
||||
message_mock.return_value = False, ''
|
||||
type(self.ssc_inst).physical_drives = mock.PropertyMock(
|
||||
return_value=None)
|
||||
self.ssc_inst.read_raid()
|
||||
self.assertTrue(message_mock.called)
|
||||
self.assertFalse(format_mock.called)
|
||||
|
|
|
@ -616,6 +616,105 @@ class HPESystemTestCase(testtools.TestCase):
|
|||
"configuration for one or more controllers with",
|
||||
self.sys_inst.create_raid, raid_config)
|
||||
|
||||
@mock.patch.object(array_controller.HPEArrayControllerCollection,
|
||||
'array_controller_by_location')
|
||||
@mock.patch.object(system.HPESystem, 'get_smart_storage_config')
|
||||
def test__post_delete_read_raid(
|
||||
self, get_smart_storage_config_mock,
|
||||
array_controller_by_location_mock):
|
||||
config_id = ['/redfish/v1/systems/1/smartstorageconfig/']
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/smart_storage.json', 'r') as f:
|
||||
ss_json = json.loads(f.read())
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/array_controller_collection.json', 'r') as f:
|
||||
acc_json = json.loads(f.read())
|
||||
self.conn.get.return_value.json.reset_mock()
|
||||
self.conn.get.return_value.json.side_effect = [ss_json, acc_json]
|
||||
type(get_smart_storage_config_mock.return_value).location = 'Slot 0'
|
||||
model = 'HPE Smart Array P408i-a SR Gen10'
|
||||
type(array_controller_by_location_mock.return_value).model = model
|
||||
type(self.sys_inst).smart_storage_config_identities = (
|
||||
mock.PropertyMock(return_value=config_id))
|
||||
result = {'logical_disks': []}
|
||||
(get_smart_storage_config_mock.
|
||||
return_value.read_raid.return_value) = result
|
||||
self.assertEqual(result, self.sys_inst._post_delete_read_raid())
|
||||
get_smart_storage_config_mock.assert_called_once_with(config_id[0])
|
||||
|
||||
@mock.patch.object(system.HPESystem, '_parse_raid_config_data')
|
||||
@mock.patch.object(system.HPESystem,
|
||||
'_get_smart_storage_config_by_controller_model')
|
||||
def test__post_create_read_raid(
|
||||
self, get_ssc_by_controller_model_mock,
|
||||
parse_raid_config_data_mock):
|
||||
ld1 = {'raid_level': '0', 'is_root_volume': True,
|
||||
'size_gb': 150,
|
||||
'controller': 'HPE Smart Array P408i-p SR Gen10'}
|
||||
raid_config = {'logical_disks': [ld1]}
|
||||
parse_data = {'HPE Smart Array P408i-p SR Gen10': [ld1]}
|
||||
parse_raid_config_data_mock.return_value = parse_data
|
||||
result_ld1 = [{'size_gb': 149,
|
||||
'physical_disks': [u'2I:1:1'],
|
||||
'raid_level': u'0',
|
||||
'controller': 'HPE Smart Array P408i-p SR Gen10',
|
||||
'root_device_hint': {'wwn': u'0x600508B'},
|
||||
'volume_name': u'01E6E63APFJHD'}]
|
||||
result = {'logical_disks': result_ld1}
|
||||
(get_ssc_by_controller_model_mock.
|
||||
return_value.read_raid.return_value) = result
|
||||
self.assertEqual(
|
||||
result,
|
||||
self.sys_inst._post_create_read_raid(raid_config=raid_config))
|
||||
get_ssc_by_controller_model_mock.assert_called_once_with(
|
||||
ld1['controller'])
|
||||
|
||||
@mock.patch.object(system.HPESystem, '_parse_raid_config_data')
|
||||
@mock.patch.object(system.HPESystem,
|
||||
'_get_smart_storage_config_by_controller_model')
|
||||
def test__post_create_read_raid_logical_drive_not_found(
|
||||
self, get_ssc_by_controller_model_mock,
|
||||
parse_raid_config_data_mock):
|
||||
ld1 = {'raid_level': '0', 'is_root_volume': True,
|
||||
'size_gb': 150,
|
||||
'controller': 'HPE Smart Array P408i-p SR Gen10'}
|
||||
raid_config = {'logical_disks': [ld1]}
|
||||
parse_data = {'HPE Smart Array P408i-p SR Gen10': [ld1]}
|
||||
parse_raid_config_data_mock.return_value = parse_data
|
||||
get_ssc_by_controller_model_mock.return_value.read_raid.side_effect = (
|
||||
exception.IloLogicalDriveNotFoundError('No logical drive found'))
|
||||
self.assertRaisesRegex(
|
||||
exception.IloError,
|
||||
"No logical drives are found in any controllers.",
|
||||
self.sys_inst._post_create_read_raid, raid_config)
|
||||
|
||||
@mock.patch.object(array_controller.HPEArrayControllerCollection,
|
||||
'array_controller_by_location')
|
||||
@mock.patch.object(system.HPESystem, 'get_smart_storage_config')
|
||||
def test__post_delete_read_raid_failed(
|
||||
self, get_smart_storage_config_mock,
|
||||
array_controller_by_location_mock):
|
||||
config_id = ['/redfish/v1/systems/1/smartstorageconfig/']
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/smart_storage.json', 'r') as f:
|
||||
ss_json = json.loads(f.read())
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/array_controller_collection.json', 'r') as f:
|
||||
acc_json = json.loads(f.read())
|
||||
self.conn.get.return_value.json.reset_mock()
|
||||
self.conn.get.return_value.json.side_effect = [ss_json, acc_json]
|
||||
model = 'HPE Smart Array P408i-a SR Gen10'
|
||||
type(array_controller_by_location_mock.return_value).model = model
|
||||
type(self.sys_inst).smart_storage_config_identities = (
|
||||
mock.PropertyMock(return_value=config_id))
|
||||
get_smart_storage_config_mock.return_value.read_raid.side_effect = (
|
||||
sushy.exceptions.SushyError)
|
||||
self.assertRaisesRegexp(
|
||||
exception.IloError,
|
||||
"The Redfish controller failed to read the "
|
||||
"raid configuration in one or more controllers with Error:",
|
||||
self.sys_inst._post_delete_read_raid)
|
||||
|
||||
@mock.patch.object(system.HPESystem, 'check_smart_storage_config_ids')
|
||||
@mock.patch.object(system.HPESystem, '_parse_raid_config_data')
|
||||
@mock.patch.object(system.HPESystem,
|
||||
|
@ -678,9 +777,60 @@ class HPESystemTestCase(testtools.TestCase):
|
|||
self.conn.get.return_value.json.reset_mock()
|
||||
self.conn.get.return_value.json.side_effect = [ss_json, acc_json]
|
||||
type(array_controller_by_model_mock.return_value).location = 'Slot 0'
|
||||
ssc_obj_mock = mock.Mock(location='Slot 0')
|
||||
get_smart_storage_config_mock.return_value = ssc_obj_mock
|
||||
type(get_smart_storage_config_mock.return_value).location = 'Slot 0'
|
||||
self.assertEqual(
|
||||
ssc_obj_mock.location,
|
||||
'Slot 0',
|
||||
self.sys_inst._get_smart_storage_config_by_controller_model(
|
||||
'HPE Smart Array P408i-a SR Gen10').location)
|
||||
|
||||
@mock.patch.object(system.HPESystem, '_parse_raid_config_data')
|
||||
@mock.patch.object(system.HPESystem,
|
||||
'_get_smart_storage_config_by_controller_model')
|
||||
def test__post_create_read_raid_failed_with_raid_config(
|
||||
self, get_ssc_by_controller_model_mock,
|
||||
parse_raid_config_data_mock):
|
||||
ld1 = {'raid_level': '0', 'is_root_volume': True,
|
||||
'size_gb': 150,
|
||||
'controller': 'HPE Smart Array P408i-p SR Gen10'}
|
||||
raid_config = {'logical_disks': [ld1]}
|
||||
parse_data = {'HPE Smart Array P408i-p SR Gen10': [ld1]}
|
||||
parse_raid_config_data_mock.return_value = parse_data
|
||||
(get_ssc_by_controller_model_mock.
|
||||
return_value.read_raid.side_effect) = sushy.exceptions.SushyError
|
||||
self.assertRaisesRegexp(
|
||||
exception.IloError,
|
||||
"The Redfish controller failed to read the "
|
||||
"raid configuration in one or more controllers with Error:",
|
||||
self.sys_inst._post_create_read_raid, raid_config=raid_config)
|
||||
|
||||
@mock.patch.object(system.HPESystem, '_post_create_read_raid')
|
||||
@mock.patch.object(system.HPESystem, 'check_smart_storage_config_ids')
|
||||
def test_read_raid_post_create(
|
||||
self, check_smart_storage_config_ids_mock,
|
||||
post_create_read_raid_mock):
|
||||
check_smart_storage_config_ids_mock.return_value = None
|
||||
ld1 = {'raid_level': '0', 'is_root_volume': True,
|
||||
'size_gb': 150,
|
||||
'controller': 'HPE Smart Array P408i-p SR Gen10'}
|
||||
raid_config = {'logical_disks': [ld1]}
|
||||
result_ld1 = [{'size_gb': 149,
|
||||
'physical_disks': [u'2I:1:1'],
|
||||
'raid_level': u'0',
|
||||
'controller': 'HPE Smart Array P408i-p SR Gen10',
|
||||
'root_device_hint': {'wwn': u'0x600508B'},
|
||||
'volume_name': u'01E6E63APFJHD'}]
|
||||
result = {'logical_disks': result_ld1}
|
||||
post_create_read_raid_mock.return_value = result
|
||||
self.assertEqual(
|
||||
result, self.sys_inst.read_raid(raid_config=raid_config))
|
||||
|
||||
@mock.patch.object(system.HPESystem, '_post_delete_read_raid')
|
||||
@mock.patch.object(system.HPESystem, 'check_smart_storage_config_ids')
|
||||
def test_read_raid_post_delete(
|
||||
self, check_smart_storage_config_ids_mock,
|
||||
post_delete_read_raid_mock):
|
||||
check_smart_storage_config_ids_mock.return_value = None
|
||||
result = {'logical_disks': []}
|
||||
post_delete_read_raid_mock.return_value = result
|
||||
self.assertEqual(
|
||||
result, self.sys_inst.read_raid())
|
||||
|
|
|
@ -1683,3 +1683,16 @@ class RedfishOperationsTestCase(testtools.TestCase):
|
|||
self.rf_client.create_raid_configuration(raid_config)
|
||||
get_system_mock.return_value.create_raid.assert_called_once_with(
|
||||
raid_config)
|
||||
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
|
||||
def test_read_raid_configuration(self, get_system_mock):
|
||||
result_ld1 = [{'size_gb': 149,
|
||||
'physical_disks': [u'2I:1:1'],
|
||||
'raid_level': u'0',
|
||||
'root_device_hint': {'wwn': u'0x600508B'},
|
||||
'controller': u'Smart Storage Controller in Slot 1',
|
||||
'volume_name': u'01E6E63APFJHD'}]
|
||||
config = {'logical_disks': result_ld1}
|
||||
expected = [('HPE Smart Array P408i-p SR Gen10', config)]
|
||||
get_system_mock.return_value.read_raid.return_value = expected
|
||||
self.assertEqual(expected, self.rf_client.read_raid_configuration())
|
||||
|
|
Loading…
Reference in New Issue