From 8bbd8883b0de7d96801527282a0d33490301931b Mon Sep 17 00:00:00 2001 From: Shivanand Tendulker Date: Fri, 2 Aug 2019 08:20:30 -0400 Subject: [PATCH] Add iLO RAID deploy steps Change-Id: Ic754235102d139b0fe12b090cb1fc1ce68904bb8 Story: 2003817 Task: 26571 Task: 30004 Task: 36061 --- ironic/drivers/modules/ilo/raid.py | 120 ++++-- .../unit/drivers/modules/ilo/test_raid.py | 342 +++++++++++++++--- ...s-ilo-raid-interface-732314cea19fe8ac.yaml | 6 + 3 files changed, 379 insertions(+), 89 deletions(-) create mode 100644 releasenotes/notes/add-deploy-steps-ilo-raid-interface-732314cea19fe8ac.yaml diff --git a/ironic/drivers/modules/ilo/raid.py b/ironic/drivers/modules/ilo/raid.py index 697b4a3736..1b528fc0ea 100644 --- a/ironic/drivers/modules/ilo/raid.py +++ b/ironic/drivers/modules/ilo/raid.py @@ -41,11 +41,34 @@ ilo_error = importutils.try_import('proliantutils.exception') class Ilo5RAID(base.RAIDInterface): """Implementation of OOB RAIDInterface for iLO5.""" + _RAID_APPLY_CONFIGURATION_ARGSINFO = { + "raid_config": { + "description": "The RAID configuration to apply.", + "required": True, + }, + "create_root_volume": { + "description": ( + "Setting this to 'False' indicates not to create root " + "volume that is specified in 'raid_config'. Default " + "value is 'True'." + ), + "required": False, + }, + "create_nonroot_volumes": { + "description": ( + "Setting this to 'False' indicates not to create " + "non-root volumes (all except the root volume) in " + "'raid_config'. Default value is 'True'." + ), + "required": False, + } + } + def get_properties(self): """Return the properties of the interface.""" return ilo_common.REQUIRED_PROPERTIES - def _set_clean_failed(self, task, msg, exc): + def _set_step_failed(self, task, msg, exc): LOG.error("RAID configuration job failed for node %(node)s. " "Message: '%(message)s'.", {'node': task.node.uuid, 'message': msg}) @@ -83,8 +106,16 @@ class Ilo5RAID(base.RAIDInterface): else: self._set_driver_internal_true_value( task, 'ilo_raid_delete_in_progress') - self._set_driver_internal_true_value(task, 'cleaning_reboot') - self._set_driver_internal_false_value(task, 'skip_current_clean_step') + deploy_utils.set_async_step_flags(task.node, reboot=True, + skip_current_step=False) + + @base.deploy_step(priority=0, + argsinfo=_RAID_APPLY_CONFIGURATION_ARGSINFO) + def apply_configuration(self, task, raid_config, create_root_volume=True, + create_nonroot_volumes=False): + return super(Ilo5RAID, self).apply_configuration( + task, raid_config, create_root_volume=create_root_volume, + create_nonroot_volumes=create_nonroot_volumes) @METRICS.timer('Ilo5RAID.create_configuration') @base.clean_step(priority=0, abortable=False, argsinfo={ @@ -119,7 +150,8 @@ class Ilo5RAID(base.RAIDInterface): :raises: MissingParameterValue, if node.target_raid_config is missing or was found to be empty after skipping root volume and/or non-root volumes. - :raises: NodeCleaningFailure, on failure to execute step. + :raises: NodeCleaningFailure, on failure to execute clean step. + :raises: InstanceDeployFailure, on failure to execute deploy step. """ node = task.node target_raid_config = raid.filter_target_raid_config( @@ -139,44 +171,52 @@ class Ilo5RAID(base.RAIDInterface): if not driver_internal_info.get('ilo_raid_create_in_progress'): ilo_object.create_raid_configuration(target_raid_config) self._prepare_for_read_raid(task, 'create_raid') - return states.CLEANWAIT + return deploy_utils.get_async_step_return_state(node) else: # Raid configuration is done, updating raid_config raid_conf = ( ilo_object.read_raid_configuration( raid_config=target_raid_config)) + fields = ['ilo_raid_create_in_progress'] + if node.clean_step: + fields.append('skip_current_clean_step') + else: + fields.append('skip_current_deploy_step') + self._pop_driver_internal_values(task, *fields) if len(raid_conf['logical_disks']): raid.update_raid_info(node, raid_conf) LOG.debug("Node %(uuid)s raid create clean step is done.", {'uuid': node.uuid}) - self._pop_driver_internal_values( - task, 'ilo_raid_create_in_progress', - 'skip_current_clean_step') else: # Raid configuration failed - msg = "Unable to create raid" - self._pop_driver_internal_values( - task, 'ilo_raid_create_in_progress', - 'skip_current_clean_step') - raise exception.NodeCleaningFailure( - "Clean step create_configuration failed " - "on node %(node)s with error: %(err)s" % - {'node': node.uuid, 'err': msg}) + msg = (_("Step create_configuration failed " + "on node %(node)s with error: " + "Unable to create raid") + % {'node': node.uuid}) + if node.clean_step: + raise exception.NodeCleaningFailure(msg) + else: + raise exception.InstanceDeployFailure(reason=msg) except ilo_error.IloError as ilo_exception: operation = (_("Failed to create raid configuration on node %s") % node.uuid) - self._pop_driver_internal_values(task, - 'ilo_raid_create_in_progress', - 'skip_current_clean_step') - self._set_clean_failed(task, operation, ilo_exception) + fields = ['ilo_raid_create_in_progress'] + if node.clean_step: + fields.append('skip_current_clean_step') + else: + fields.append('skip_current_deploy_step') + self._pop_driver_internal_values(task, *fields) + self._set_step_failed(task, operation, ilo_exception) @METRICS.timer('Ilo5RAID.delete_configuration') @base.clean_step(priority=0, abortable=False) + @base.deploy_step(priority=0) def delete_configuration(self, task): """Delete the RAID configuration. :param task: a TaskManager instance containing the node to act on. - :raises: NodeCleaningFailure, on failure to execute step. + :raises: NodeCleaningFailure, on failure to execute clean step. + :raises: InstanceDeployFailure, on failure to execute deploy step. """ node = task.node LOG.debug("OOB RAID delete_configuration invoked for node %s.", @@ -189,28 +229,32 @@ class Ilo5RAID(base.RAIDInterface): if not driver_internal_info.get('ilo_raid_delete_in_progress'): ilo_object.delete_raid_configuration() self._prepare_for_read_raid(task, 'delete_raid') - return states.CLEANWAIT + return deploy_utils.get_async_step_return_state(node) else: # Raid configuration is done, updating raid_config raid_conf = ilo_object.read_raid_configuration() + fields = ['ilo_raid_delete_in_progress'] + if node.clean_step: + fields.append('skip_current_clean_step') + else: + fields.append('skip_current_deploy_step') + self._pop_driver_internal_values(task, *fields) if not len(raid_conf['logical_disks']): node.raid_config = {} LOG.debug("Node %(uuid)s raid delete clean step is done.", {'uuid': node.uuid}) - self._pop_driver_internal_values( - task, 'ilo_raid_delete_in_progress', - 'skip_current_clean_step') else: # Raid configuration failed - msg = ("Unable to delete this logical disks: %s" % - raid_conf['logical_disks']) - self._pop_driver_internal_values( - task, 'ilo_raid_delete_in_progress', - 'skip_current_clean_step') - raise exception.NodeCleaningFailure( - "Clean step delete_configuration failed " - "on node %(node)s with error: %(err)s" % - {'node': node.uuid, 'err': msg}) + err_msg = (_("Step delete_configuration failed " + "on node %(node)s with error: " + "Unable to delete these logical disks: " + "%(disks)s") + % {'node': node.uuid, + 'disks': raid_conf['logical_disks']}) + if node.clean_step: + raise exception.NodeCleaningFailure(err_msg) + else: + raise exception.InstanceDeployFailure(reason=err_msg) except ilo_error.IloLogicalDriveNotFoundError: LOG.info("No logical drive found to delete on node %(node)s", {'node': node.uuid}) @@ -220,4 +264,10 @@ class Ilo5RAID(base.RAIDInterface): self._pop_driver_internal_values(task, 'ilo_raid_delete_in_progress', 'skip_current_clean_step') - self._set_clean_failed(task, operation, ilo_exception) + fields = ['ilo_raid_delete_in_progress'] + if node.clean_step: + fields.append('skip_current_clean_step') + else: + fields.append('skip_current_deploy_step') + self._pop_driver_internal_values(task, *fields) + self._set_step_failed(task, operation, ilo_exception) diff --git a/ironic/tests/unit/drivers/modules/ilo/test_raid.py b/ironic/tests/unit/drivers/modules/ilo/test_raid.py index 3e91be4b60..7e89c2160f 100644 --- a/ironic/tests/unit/drivers/modules/ilo/test_raid.py +++ b/ironic/tests/unit/drivers/modules/ilo/test_raid.py @@ -44,13 +44,10 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): {'size_gb': 200, 'raid_level': 0, 'is_root_volume': True}, {'size_gb': 200, 'raid_level': 5} ]} - self.clean_step = {'step': 'create_configuration', - 'interface': 'raid'} n = { 'driver': 'ilo5', 'driver_info': INFO_DICT, 'target_raid_config': self.target_raid_config, - 'clean_step': self.clean_step, } self.config(enabled_hardware_types=['ilo5'], enabled_boot_interfaces=['ilo-virtual-media'], @@ -64,7 +61,7 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): @mock.patch.object(deploy_utils, 'build_agent_options', autospec=True) @mock.patch.object(manager_utils, 'node_power_action', autospec=True) - def test__prepare_for_read_raid_create_raid( + def _test__prepare_for_read_raid_create_raid( self, mock_reboot, mock_build_opt): with task_manager.acquire(self.context, self.node.uuid) as task: mock_build_opt.return_value = [] @@ -72,17 +69,37 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): self.assertTrue( task.node.driver_internal_info.get( 'ilo_raid_create_in_progress')) - self.assertTrue( - task.node.driver_internal_info.get( - 'cleaning_reboot')) - self.assertFalse( - task.node.driver_internal_info.get( - 'skip_current_clean_step')) + if task.node.clean_step: + self.assertTrue( + task.node.driver_internal_info.get( + 'cleaning_reboot')) + self.assertFalse( + task.node.driver_internal_info.get( + 'skip_current_clean_step')) + if task.node.deploy_step: + self.assertTrue( + task.node.driver_internal_info.get( + 'deployment_reboot')) + self.assertFalse( + task.node.driver_internal_info.get( + 'skip_current_deploy_step')) mock_reboot.assert_called_once_with(task, states.REBOOT) + def test__prepare_for_read_raid_create_raid_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test__prepare_for_read_raid_create_raid() + + def test__prepare_for_read_raid_create_raid_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test__prepare_for_read_raid_create_raid() + @mock.patch.object(deploy_utils, 'build_agent_options', autospec=True) @mock.patch.object(manager_utils, 'node_power_action', autospec=True) - def test__prepare_for_read_raid_delete_raid( + def _test__prepare_for_read_raid_delete_raid( self, mock_reboot, mock_build_opt): with task_manager.acquire(self.context, self.node.uuid) as task: mock_build_opt.return_value = [] @@ -90,18 +107,38 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): self.assertTrue( task.node.driver_internal_info.get( 'ilo_raid_delete_in_progress')) - self.assertTrue( - task.node.driver_internal_info.get( - 'cleaning_reboot')) - self.assertEqual( - task.node.driver_internal_info.get( - 'skip_current_clean_step'), False) + if task.node.clean_step: + self.assertTrue( + task.node.driver_internal_info.get( + 'cleaning_reboot')) + self.assertEqual( + task.node.driver_internal_info.get( + 'skip_current_clean_step'), False) + else: + self.assertTrue( + task.node.driver_internal_info.get( + 'deployment_reboot')) + self.assertEqual( + task.node.driver_internal_info.get( + 'skip_current_deploy_step'), False) mock_reboot.assert_called_once_with(task, states.REBOOT) + def test__prepare_for_read_raid_delete_raid_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test__prepare_for_read_raid_delete_raid() + + def test__prepare_for_read_raid_delete_raid_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test__prepare_for_read_raid_delete_raid() + @mock.patch.object(ilo_raid.Ilo5RAID, '_prepare_for_read_raid') @mock.patch.object(raid, 'filter_target_raid_config') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_create_configuration( + def _test_create_configuration( self, ilo_mock, filter_target_raid_config_mock, prepare_raid_mock): ilo_mock_object = ilo_mock.return_value with task_manager.acquire(self.context, self.node.uuid) as task: @@ -109,14 +146,29 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): self.target_raid_config) result = task.driver.raid.create_configuration(task) prepare_raid_mock.assert_called_once_with(task, 'create_raid') + if task.node.clean_step: + self.assertEqual(states.CLEANWAIT, result) + else: + self.assertEqual(states.DEPLOYWAIT, result) (ilo_mock_object.create_raid_configuration. assert_called_once_with(self.target_raid_config)) - self.assertEqual(states.CLEANWAIT, result) + + def test_create_configuration_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration() + + def test_create_configuration_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration() @mock.patch.object(raid, 'update_raid_info', autospec=True) @mock.patch.object(raid, 'filter_target_raid_config') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_create_configuration_with_read_raid( + def _test_create_configuration_with_read_raid( self, ilo_mock, filter_target_raid_config_mock, update_raid_mock): raid_conf = {u'logical_disks': [{u'size_gb': 89, @@ -129,9 +181,15 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): ilo_mock_object = ilo_mock.return_value driver_internal_info = self.node.driver_internal_info driver_internal_info['ilo_raid_create_in_progress'] = True - driver_internal_info['skip_current_clean_step'] = False + if self.node.clean_step: + driver_internal_info['skip_current_clean_step'] = False + driver_internal_info['cleaning_reboot'] = True + else: + driver_internal_info['skip_current_deploy_step'] = False + driver_internal_info['deployment_reboot'] = True self.node.driver_internal_info = driver_internal_info self.node.save() + with task_manager.acquire(self.context, self.node.uuid) as task: filter_target_raid_config_mock.return_value = ( self.target_raid_config) @@ -140,12 +198,25 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): update_raid_mock.assert_called_once_with(task.node, raid_conf) self.assertNotIn('ilo_raid_create_in_progress', task.node.driver_internal_info) - self.assertNotIn('skip_current_clean_step', - task.node.driver_internal_info) + if task.node.clean_step: + self.assertNotIn('skip_current_clean_step', + task.node.driver_internal_info) + + def test_create_configuration_with_read_raid_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_with_read_raid() + + def test_create_configuration_with_read_raid_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_with_read_raid() @mock.patch.object(raid, 'filter_target_raid_config') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_create_configuration_with_read_raid_failed( + def _test_create_configuration_with_read_raid_failed( self, ilo_mock, filter_target_raid_config_mock): raid_conf = {u'logical_disks': []} driver_internal_info = self.node.driver_internal_info @@ -154,20 +225,40 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): self.node.driver_internal_info = driver_internal_info self.node.save() ilo_mock_object = ilo_mock.return_value + if self.node.clean_step: + exept = exception.NodeCleaningFailure + else: + exept = exception.InstanceDeployFailure with task_manager.acquire(self.context, self.node.uuid) as task: filter_target_raid_config_mock.return_value = ( self.target_raid_config) ilo_mock_object.read_raid_configuration.return_value = raid_conf - self.assertRaises(exception.NodeCleaningFailure, + self.assertRaises(exept, task.driver.raid.create_configuration, task) self.assertNotIn('ilo_raid_create_in_progress', task.node.driver_internal_info) - self.assertNotIn('skip_current_clean_step', - task.node.driver_internal_info) + if task.node.clean_step: + self.assertNotIn('skip_current_clean_step', + task.node.driver_internal_info) + else: + self.assertNotIn('skip_current_deploy_step', + task.node.driver_internal_info) + + def test_create_configuration_with_read_raid_failed_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_with_read_raid_failed() + + def test_create_configuration_with_read_raid_failed_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_with_read_raid_failed() @mock.patch.object(raid, 'filter_target_raid_config') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_create_configuration_empty_target_raid_config( + def _test_create_configuration_empty_target_raid_config( self, ilo_mock, filter_target_raid_config_mock): self.node.target_raid_config = {} self.node.save() @@ -180,10 +271,22 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): task.driver.raid.create_configuration, task) self.assertFalse(ilo_mock_object.create_raid_configuration.called) + def test_create_configuration_empty_target_raid_config_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_empty_target_raid_config() + + def test_create_configuration_empty_target_raid_config_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_empty_target_raid_config() + @mock.patch.object(ilo_raid.Ilo5RAID, '_prepare_for_read_raid') @mock.patch.object(raid, 'filter_target_raid_config') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_create_configuration_skip_root( + def _test_create_configuration_skip_root( self, ilo_mock, filter_target_raid_config_mock, prepare_raid_mock): ilo_mock_object = ilo_mock.return_value @@ -198,16 +301,31 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): task, create_root_volume=False) (ilo_mock_object.create_raid_configuration. assert_called_once_with(exp_target_raid_config)) - self.assertEqual(states.CLEANWAIT, result) + if task.node.clean_step: + self.assertEqual(states.CLEANWAIT, result) + else: + self.assertEqual(states.DEPLOYWAIT, result) prepare_raid_mock.assert_called_once_with(task, 'create_raid') self.assertEqual( exp_target_raid_config, task.node.driver_internal_info['target_raid_config']) + def test_create_configuration_skip_root_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_skip_root() + + def test_create_configuration_skip_root_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_skip_root() + @mock.patch.object(ilo_raid.Ilo5RAID, '_prepare_for_read_raid') @mock.patch.object(raid, 'filter_target_raid_config') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_create_configuration_skip_non_root( + def _test_create_configuration_skip_non_root( self, ilo_mock, filter_target_raid_config_mock, prepare_raid_mock): ilo_mock_object = ilo_mock.return_value with task_manager.acquire(self.context, self.node.uuid) as task: @@ -222,14 +340,29 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): (ilo_mock_object.create_raid_configuration. assert_called_once_with(exp_target_raid_config)) prepare_raid_mock.assert_called_once_with(task, 'create_raid') - self.assertEqual(states.CLEANWAIT, result) + if task.node.clean_step: + self.assertEqual(states.CLEANWAIT, result) + else: + self.assertEqual(states.DEPLOYWAIT, result) self.assertEqual( exp_target_raid_config, task.node.driver_internal_info['target_raid_config']) + def test_create_configuration_skip_non_root_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_skip_non_root() + + def test_create_configuration_skip_non_root_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_skip_non_root() + @mock.patch.object(raid, 'filter_target_raid_config') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_create_configuration_skip_root_skip_non_root( + def _test_create_configuration_skip_root_skip_non_root( self, ilo_mock, filter_target_raid_config_mock): ilo_mock_object = ilo_mock.return_value with task_manager.acquire(self.context, self.node.uuid) as task: @@ -242,42 +375,83 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): task, False, False) self.assertFalse(ilo_mock_object.create_raid_configuration.called) - @mock.patch.object(ilo_raid.Ilo5RAID, '_set_clean_failed') + def test_create_configuration_skip_root_skip_non_root_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_skip_root_skip_non_root() + + def test_create_configuration_skip_root_skip_non_root_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_skip_root_skip_non_root() + + @mock.patch.object(ilo_raid.Ilo5RAID, '_set_step_failed') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_create_configuration_ilo_error(self, ilo_mock, - set_clean_failed_mock): + def _test_create_configuration_ilo_error(self, ilo_mock, + set_step_failed_mock): ilo_mock_object = ilo_mock.return_value exc = ilo_error.IloError('error') ilo_mock_object.create_raid_configuration.side_effect = exc with task_manager.acquire(self.context, self.node.uuid) as task: task.driver.raid.create_configuration( task, create_nonroot_volumes=False) - set_clean_failed_mock.assert_called_once_with( + set_step_failed_mock.assert_called_once_with( task, 'Failed to create raid configuration ' 'on node %s' % self.node.uuid, exc) self.assertNotIn('ilo_raid_create_in_progress', task.node.driver_internal_info) - self.assertNotIn('cleaning_reboot', - task.node.driver_internal_info) - self.assertNotIn('skip_current_clean_step', - task.node.driver_internal_info) + if task.node.clean_step: + self.assertNotIn('skip_current_clean_step', + task.node.driver_internal_info) + else: + self.assertNotIn('skip_current_deploy_step', + task.node.driver_internal_info) + + def test_create_configuration_ilo_error_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_ilo_error() + + def test_create_configuration_ilo_error_cleaning_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_create_configuration_ilo_error() @mock.patch.object(ilo_raid.Ilo5RAID, '_prepare_for_read_raid') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_delete_configuration(self, ilo_mock, prepare_raid_mock): + def _test_delete_configuration(self, ilo_mock, prepare_raid_mock): ilo_mock_object = ilo_mock.return_value with task_manager.acquire(self.context, self.node.uuid) as task: result = task.driver.raid.delete_configuration(task) - self.assertEqual(states.CLEANWAIT, result) + if task.node.clean_step: + self.assertEqual(states.CLEANWAIT, result) + else: + self.assertEqual(states.DEPLOYWAIT, result) ilo_mock_object.delete_raid_configuration.assert_called_once_with() prepare_raid_mock.assert_called_once_with(task, 'delete_raid') + def test_delete_configuration_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration() + + def test_delete_configuration_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration() + @mock.patch.object(ilo_raid.LOG, 'info', spec_set=True, autospec=True) @mock.patch.object(ilo_raid.Ilo5RAID, '_prepare_for_read_raid') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_delete_configuration_no_logical_drive( + def _test_delete_configuration_no_logical_drive( self, ilo_mock, prepare_raid_mock, log_mock): ilo_mock_object = ilo_mock.return_value exc = ilo_error.IloLogicalDriveNotFoundError('No logical drive found') @@ -286,8 +460,20 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): task.driver.raid.delete_configuration(task) self.assertTrue(log_mock.called) + def test_delete_configuration_no_logical_drive_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration_no_logical_drive() + + def test_delete_configuration_no_logical_drive_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration_no_logical_drive() + @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_delete_configuration_with_read_raid(self, ilo_mock): + def _test_delete_configuration_with_read_raid(self, ilo_mock): raid_conf = {u'logical_disks': []} driver_internal_info = self.node.driver_internal_info driver_internal_info['ilo_raid_delete_in_progress'] = True @@ -295,17 +481,33 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): self.node.driver_internal_info = driver_internal_info self.node.save() ilo_mock_object = ilo_mock.return_value + if self.node.clean_step: + skip_field_name = 'skip_current_clean_step' + else: + skip_field_name = 'skip_current_deploy_step' with task_manager.acquire(self.context, self.node.uuid) as task: ilo_mock_object.read_raid_configuration.return_value = raid_conf task.driver.raid.delete_configuration(task) self.assertEqual(self.node.raid_config, {}) self.assertNotIn('ilo_raid_delete_in_progress', task.node.driver_internal_info) - self.assertNotIn('skip_current_clean_step', + self.assertNotIn(skip_field_name, task.node.driver_internal_info) + def test_delete_configuration_with_read_raid_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration_with_read_raid() + + def test_delete_configuration_with_read_raid_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration_with_read_raid() + @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_delete_configuration_with_read_raid_failed(self, ilo_mock): + def _test_delete_configuration_with_read_raid_failed(self, ilo_mock): raid_conf = {u'logical_disks': [{'size_gb': 200, 'raid_level': 0, 'is_root_volume': True}]} @@ -315,19 +517,39 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): self.node.driver_internal_info = driver_internal_info self.node.save() ilo_mock_object = ilo_mock.return_value + if self.node.clean_step: + exept = exception.NodeCleaningFailure + else: + exept = exception.InstanceDeployFailure with task_manager.acquire(self.context, self.node.uuid) as task: ilo_mock_object.read_raid_configuration.return_value = raid_conf - self.assertRaises(exception.NodeCleaningFailure, + self.assertRaises(exept, task.driver.raid.delete_configuration, task) self.assertNotIn('ilo_raid_delete_in_progress', task.node.driver_internal_info) - self.assertNotIn('skip_current_clean_step', - task.node.driver_internal_info) + if task.node.clean_step: + self.assertNotIn('skip_current_clean_step', + task.node.driver_internal_info) + else: + self.assertNotIn('skip_current_deploy_step', + task.node.driver_internal_info) - @mock.patch.object(ilo_raid.Ilo5RAID, '_set_clean_failed') + def test_delete_configuration_with_read_raid_failed_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration_with_read_raid_failed() + + def test_delete_configuration_with_read_raid_failed_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration_with_read_raid_failed() + + @mock.patch.object(ilo_raid.Ilo5RAID, '_set_step_failed') @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) - def test_delete_configuration_ilo_error(self, ilo_mock, - set_clean_failed_mock): + def _test_delete_configuration_ilo_error(self, ilo_mock, + set_step_failed_mock): ilo_mock_object = ilo_mock.return_value exc = ilo_error.IloError('error') ilo_mock_object.delete_raid_configuration.side_effect = exc @@ -340,7 +562,19 @@ class Ilo5RAIDTestCase(db_base.DbTestCase): task.node.driver_internal_info) self.assertNotIn('skip_current_clean_step', task.node.driver_internal_info) - set_clean_failed_mock.assert_called_once_with( + set_step_failed_mock.assert_called_once_with( task, 'Failed to delete raid configuration ' 'on node %s' % self.node.uuid, exc) + + def test_delete_configuration_ilo_error_cleaning(self): + self.node.clean_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration_ilo_error() + + def test_delete_configuration_ilo_error_deploying(self): + self.node.deploy_step = {'step': 'create_configuration', + 'interface': 'raid'} + self.node.save() + self._test_delete_configuration_ilo_error() diff --git a/releasenotes/notes/add-deploy-steps-ilo-raid-interface-732314cea19fe8ac.yaml b/releasenotes/notes/add-deploy-steps-ilo-raid-interface-732314cea19fe8ac.yaml new file mode 100644 index 0000000000..8de7e286df --- /dev/null +++ b/releasenotes/notes/add-deploy-steps-ilo-raid-interface-732314cea19fe8ac.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Adds support for deploy steps to ``raid`` interface of ``ilo5`` + hardware type. The methods ``apply_configuration`` and + ``delete_configuration`` can be used as deploy steps.