diff --git a/ironic/drivers/modules/ilo/bios.py b/ironic/drivers/modules/ilo/bios.py index 3d6359914e..74ccb503d5 100644 --- a/ironic/drivers/modules/ilo/bios.py +++ b/ironic/drivers/modules/ilo/bios.py @@ -21,12 +21,14 @@ from oslo_utils import importutils from ironic.common import exception from ironic.common.i18n import _ +from ironic.common import states +from ironic.conductor import utils as manager_utils from ironic.drivers import base +from ironic.drivers.modules import deploy_utils from ironic.drivers.modules.ilo import common as ilo_common from ironic import objects LOG = logging.getLogger(__name__) - METRICS = metrics_utils.get_metrics_logger(__name__) ilo_error = importutils.try_import('proliantutils.exception') @@ -51,6 +53,100 @@ class IloBIOS(base.BIOSInterface): """ ilo_common.parse_driver_info(task.node) + def _execute_pre_boot_bios_step(self, task, step, data=None): + """Perform operations required prior to the reboot. + + Depending on the clean step, it executes the operations required + and moves the node to CLEANWAIT state prior to reboot. + :param task: a task from TaskManager. + :param step: name of the clean step to be performed + :param data: if the clean step is apply_configuration it holds + the settings data. + :raises: NodeCleaningFailure if it fails any conditions expected + """ + node = task.node + + if step not in ('apply_configuration', 'factory_reset'): + errmsg = _('Could not find the step %(step)s for the ' + 'node %(node)s.') + raise exception.NodeCleaningFailure( + errmsg % {'step': step, 'node': node.uuid}) + + try: + ilo_object = ilo_common.get_ilo_object(node) + ilo_object.set_bios_settings(data) if step == ( + 'apply_configuration') else ilo_object.reset_bios_to_default() + except (exception.MissingParameterValue, + exception.InvalidParameterValue, + ilo_error.IloError, + ilo_error.IloCommandNotSupportedError) as ir_exception: + errmsg = _('Clean step %(step)s failed ' + 'on the node %(node)s with error: %(err)s') + raise exception.NodeCleaningFailure( + errmsg % {'step': step, 'node': node.uuid, + 'err': ir_exception}) + + deploy_opts = deploy_utils.build_agent_options(node) + task.driver.boot.prepare_ramdisk(task, deploy_opts) + manager_utils.node_power_action(task, states.REBOOT) + + driver_internal_info = node.driver_internal_info + driver_internal_info['cleaning_reboot'] = True + driver_internal_info['skip_current_clean_step'] = False + + if step == 'apply_configuration': + driver_internal_info['apply_bios'] = True + else: + driver_internal_info['reset_bios'] = True + + node.driver_internal_info = driver_internal_info + node.save() + return states.CLEANWAIT + + def _execute_post_boot_bios_step(self, task, step): + """Perform operations required after the reboot. + + Caches BIOS settings in the database and clear the flags assocated + with the clean step post reboot. + :param task: a task from TaskManager. + :param step: name of the clean step to be performed + :raises: NodeCleaningFailure if it fails any conditions expected + """ + node = task.node + + driver_internal_info = node.driver_internal_info + driver_internal_info.pop('apply_bios', None) + driver_internal_info.pop('reset_bios', None) + task.node.driver_internal_info = driver_internal_info + task.node.save() + + if step not in ('apply_configuration', 'factory_reset'): + errmsg = _('Could not find the step %(step)s for the ' + 'node %(node)s.') + raise exception.NodeCleaningFailure( + errmsg % {'step': step, 'node': node.uuid}) + + try: + ilo_object = ilo_common.get_ilo_object(node) + status = ilo_object.get_bios_settings_result() + except (exception.MissingParameterValue, + exception.InvalidParameterValue, + ilo_error.IloError, + ilo_error.IloCommandNotSupportedError) as ir_exception: + + errmsg = _('Clean step %(step)s failed ' + 'on the node %(node)s with error: %(err)s') + raise exception.NodeCleaningFailure( + errmsg % {'step': step, 'node': node.uuid, + 'err': ir_exception}) + + if status.get('status') == 'failed': + errmsg = _('Clean step %(step)s failed ' + 'on the node %(node)s with error: %(err)s') + raise exception.NodeCleaningFailure( + errmsg % {'step': step, 'node': node.uuid, + 'err': status.get('results')}) + @METRICS.timer('IloBIOS.apply_configuration') @base.clean_step(priority=0, abortable=False, argsinfo={ 'settings': { @@ -67,24 +163,17 @@ class IloBIOS(base.BIOSInterface): the node fails. """ + node = task.node + driver_internal_info = node.driver_internal_info data = {} for setting in settings: data.update({setting['name']: setting['value']}) - - node = task.node - - errmsg = _("Clean step \"apply_configuration\" failed " - "on node %(node)s with error: %(err)s") - - try: - ilo_object = ilo_common.get_ilo_object(node) - ilo_object.set_bios_settings(data) - except (exception.MissingParameterValue, - exception.InvalidParameterValue, - ilo_error.IloError, - ilo_error.IloCommandNotSupportedError) as ir_exception: - raise exception.NodeCleaningFailure( - errmsg % {'node': node.uuid, 'err': ir_exception}) + if not driver_internal_info.get('apply_bios'): + return self._execute_pre_boot_bios_step( + task, 'apply_configuration', data) + else: + return self._execute_post_boot_bios_step( + task, 'apply_configuration') @METRICS.timer('IloBIOS.factory_reset') @base.clean_step(priority=0, abortable=False) @@ -97,19 +186,12 @@ class IloBIOS(base.BIOSInterface): """ node = task.node + driver_internal_info = node.driver_internal_info - errmsg = _("Clean step \"factory_reset\" failed " - "on node %(node)s with error: %(err)s") - - try: - ilo_object = ilo_common.get_ilo_object(node) - ilo_object.reset_bios_to_default() - except (exception.MissingParameterValue, - exception.InvalidParameterValue, - ilo_error.IloError, - ilo_error.IloCommandNotSupportedError) as ir_exception: - raise exception.NodeCleaningFailure( - errmsg % {'node': node.uuid, 'err': ir_exception}) + if not driver_internal_info.get('reset_bios'): + return self._execute_pre_boot_bios_step(task, 'factory_reset') + else: + return self._execute_post_boot_bios_step(task, 'factory_reset') @METRICS.timer('IloBIOS.cache_bios_settings') def cache_bios_settings(self, task): @@ -127,7 +209,7 @@ class IloBIOS(base.BIOSInterface): "on node %(node)s with error: %(err)s") try: ilo_object = ilo_common.get_ilo_object(node) - bios_settings = ilo_object.get_pending_bios_settings() + bios_settings = ilo_object.get_current_bios_settings() except (exception.MissingParameterValue, exception.InvalidParameterValue, diff --git a/ironic/tests/unit/drivers/modules/ilo/test_bios.py b/ironic/tests/unit/drivers/modules/ilo/test_bios.py index e285d879c6..0d0c12b665 100644 --- a/ironic/tests/unit/drivers/modules/ilo/test_bios.py +++ b/ironic/tests/unit/drivers/modules/ilo/test_bios.py @@ -21,6 +21,10 @@ from oslo_utils import importutils from ironic.common import exception from ironic.conductor import task_manager +from ironic.conductor import utils as manager_utils +from ironic.drivers.modules import deploy_utils +from ironic.drivers.modules.ilo import bios as ilo_bios +from ironic.drivers.modules.ilo import boot as ilo_boot from ironic.drivers.modules.ilo import common as ilo_common from ironic import objects from ironic.tests.unit.db import utils as db_utils @@ -48,145 +52,356 @@ class IloBiosTestCase(test_common.BaseIloTest): task.driver.bios.validate(task) mock_drvinfo.assert_called_once_with(task.node) - @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, - autospec=True) - def _test_ilo_error(self, error_type, - test_methods_not_called, method_details, ilo_mock): - error_dict = { - "missing_parameter": exception.MissingParameterValue, - "invalid_parameter": exception.InvalidParameterValue - } - - exc = error_dict.get(error_type)('error') - ilo_mock.side_effect = exc + def _test_ilo_error(self, exc_cls, + test_methods_not_called, + test_methods_called, + method_details, exception_mock): + exception_mock.side_effect = exc_cls('error') method = method_details.get("name") args = method_details.get("args") self.assertRaises(exception.NodeCleaningFailure, method, *args) for test_method in test_methods_not_called: - eval("ilo_mock.return_value.%s.assert_not_called()" % ( - test_method)) + test_method.assert_not_called() + for called_method in test_methods_called: + called_method["name"].assert_called_once_with( + *called_method["args"]) + @mock.patch.object(ilo_bios.IloBIOS, '_execute_post_boot_bios_step', + autospec=True) + @mock.patch.object(ilo_bios.IloBIOS, '_execute_pre_boot_bios_step', + autospec=True) + def test_apply_configuration_pre_boot(self, exe_pre_boot_mock, + exe_post_boot_mock): + settings = [ + { + "name": "SET_A", "value": "VAL_A", + }, + { + "name": "SET_B", "value": "VAL_B", + }, + { + "name": "SET_C", "value": "VAL_C", + }, + { + "name": "SET_D", "value": "VAL_D", + } + ] + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + driver_internal_info = task.node.driver_internal_info + driver_internal_info.pop('apply_bios', None) + task.node.driver_internal_info = driver_internal_info + task.node.save() + actual_settings = {'SET_A': 'VAL_A', 'SET_B': 'VAL_B', + 'SET_C': 'VAL_C', 'SET_D': 'VAL_D'} + task.driver.bios.apply_configuration(task, settings) + + exe_pre_boot_mock.assert_called_once_with( + task.driver.bios, task, 'apply_configuration', actual_settings) + self.assertFalse(exe_post_boot_mock.called) + + @mock.patch.object(ilo_bios.IloBIOS, '_execute_post_boot_bios_step', + autospec=True) + @mock.patch.object(ilo_bios.IloBIOS, '_execute_pre_boot_bios_step', + autospec=True) + def test_apply_configuration_post_boot(self, exe_pre_boot_mock, + exe_post_boot_mock): + settings = [ + { + "name": "SET_A", "value": "VAL_A", + }, + { + "name": "SET_B", "value": "VAL_B", + }, + { + "name": "SET_C", "value": "VAL_C", + }, + { + "name": "SET_D", "value": "VAL_D", + } + ] + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + driver_internal_info = task.node.driver_internal_info + driver_internal_info['apply_bios'] = True + task.node.driver_internal_info = driver_internal_info + task.node.save() + task.driver.bios.apply_configuration(task, settings) + + exe_post_boot_mock.assert_called_once_with( + task.driver.bios, task, 'apply_configuration') + self.assertFalse(exe_pre_boot_mock.called) + + @mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'prepare_ramdisk', + spec_set=True, autospec=True) + @mock.patch.object(manager_utils, 'node_power_action', spec_set=True, + autospec=True) + @mock.patch.object(deploy_utils, 'build_agent_options', spec_set=True, + autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) - def test_apply_configuration(self, get_ilo_object_mock): + def test__execute_pre_boot_bios_step_apply_configuration( + self, get_ilo_object_mock, build_agent_mock, + node_power_mock, prepare_mock): + with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: ilo_object_mock = get_ilo_object_mock.return_value - data = [ - { - "name": "SET_A", "value": "VAL_A", - }, - { - "name": "SET_B", "value": "VAL_B", - }, - { - "name": "SET_C", "value": "VAL_C", - }, - { - "name": "SET_D", "value": "VAL_D", - } - ] - task.driver.bios.apply_configuration(task, data) - expected = { + data = { "SET_A": "VAL_A", "SET_B": "VAL_B", "SET_C": "VAL_C", "SET_D": "VAL_D" } - ilo_object_mock.set_bios_settings.assert_called_once_with(expected) - - def test_apply_configuration_missing_parameter(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=True) as task: - mdobj = { - "name": task.driver.bios.apply_configuration, - "args": (task, []) - } - self._test_ilo_error("missing_parameter", ["set_bios_settings"], - mdobj) - - def test_apply_configuration_invalid_parameter(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=True) as task: - mdobj = { - "name": task.driver.bios.apply_configuration, - "args": (task, []) - } - self._test_ilo_error("invalid_parameter", ["set_bios_settings"], - mdobj) + step = 'apply_configuration' + task.driver.bios._execute_pre_boot_bios_step(task, step, data) + driver_info = task.node.driver_internal_info + self.assertTrue( + all(x in driver_info for x in ( + 'apply_bios', 'cleaning_reboot', + 'skip_current_clean_step'))) + ilo_object_mock.set_bios_settings.assert_called_once_with(data) + self.assertFalse(ilo_object_mock.reset_bios_to_default.called) + build_agent_mock.assert_called_once_with(task.node) + self.assertTrue(prepare_mock.called) + self.assertTrue(node_power_mock.called) + @mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'prepare_ramdisk', + spec_set=True, autospec=True) + @mock.patch.object(manager_utils, 'node_power_action', spec_set=True, + autospec=True) + @mock.patch.object(deploy_utils, 'build_agent_options', spec_set=True, + autospec=True) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) - def test_apply_configuration_with_ilo_error(self, get_ilo_object_mock): + def test__execute_pre_boot_bios_step_factory_reset( + self, get_ilo_object_mock, build_agent_mock, + node_power_mock, prepare_mock): + with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: ilo_object_mock = get_ilo_object_mock.return_value - data = [ - { - "name": "SET_A", "value": "VAL_A", - }, - { - "name": "SET_B", "value": "VAL_B", - }, - ] - exc = ilo_error.IloError('error') - ilo_object_mock.set_bios_settings.side_effect = exc - self.assertRaises(exception.NodeCleaningFailure, - task.driver.bios.apply_configuration, - task, data) - - @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, - autospec=True) - def test_factory_reset(self, get_ilo_object_mock): - with task_manager.acquire(self.context, self.node.uuid, - shared=True) as task: - ilo_object_mock = get_ilo_object_mock.return_value - task.driver.bios.factory_reset(task) + data = { + "SET_A": "VAL_A", + "SET_B": "VAL_B", + "SET_C": "VAL_C", + "SET_D": "VAL_D" + } + step = 'factory_reset' + task.driver.bios._execute_pre_boot_bios_step(task, step, data) + driver_info = task.node.driver_internal_info + self.assertTrue( + all(x in driver_info for x in ( + 'reset_bios', 'cleaning_reboot', + 'skip_current_clean_step'))) ilo_object_mock.reset_bios_to_default.assert_called_once_with() - - def test_factory_reset_missing_parameter(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=True) as task: - mdobj = { - "name": task.driver.bios.factory_reset, - "args": (task,) - } - self._test_ilo_error("missing_parameter", - ["reset_bios_to_default"], mdobj) - - def test_factory_reset_invalid_parameter(self): - with task_manager.acquire(self.context, self.node.uuid, - shared=True) as task: - mdobj = { - "name": task.driver.bios.factory_reset, - "args": (task,) - } - self._test_ilo_error("invalid_parameter", - ["reset_bios_to_default"], mdobj) + self.assertFalse(ilo_object_mock.set_bios_settings.called) + build_agent_mock.assert_called_once_with(task.node) + self.assertTrue(prepare_mock.called) + self.assertTrue(node_power_mock.called) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) - def test_factory_reset_with_ilo_error(self, get_ilo_object_mock): + def test__execute_pre_boot_bios_step_invalid( + self, get_ilo_object_mock): + with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: - ilo_object_mock = get_ilo_object_mock.return_value - exc = ilo_error.IloError('error') - ilo_object_mock.reset_bios_to_default.side_effect = exc + data = { + "SET_A": "VAL_A", + "SET_B": "VAL_B", + "SET_C": "VAL_C", + "SET_D": "VAL_D" + } + step = 'invalid_step' self.assertRaises(exception.NodeCleaningFailure, - task.driver.bios.factory_reset, task) + task.driver.bios._execute_pre_boot_bios_step, + task, step, data) @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, autospec=True) - def test_factory_reset_with_unknown_error(self, get_ilo_object_mock): + def test__execute_pre_boot_bios_step_iloobj_failed( + self, get_ilo_object_mock): + with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: - ilo_object_mock = get_ilo_object_mock.return_value - exc = ilo_error.IloCommandNotSupportedError('error') - ilo_object_mock.reset_bios_to_default.side_effect = exc + data = { + "SET_A": "VAL_A", + "SET_B": "VAL_B", + "SET_C": "VAL_C", + "SET_D": "VAL_D" + } + get_ilo_object_mock.side_effect = exception.MissingParameterValue( + 'err') + step = 'apply_configuration' self.assertRaises(exception.NodeCleaningFailure, - task.driver.bios.factory_reset, task) + task.driver.bios._execute_pre_boot_bios_step, + task, step, data) + + @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, + autospec=True) + def test__execute_pre_boot_bios_step_set_bios_failed( + self, get_ilo_object_mock): + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + data = { + "SET_A": "VAL_A", + "SET_B": "VAL_B", + "SET_C": "VAL_C", + "SET_D": "VAL_D" + } + ilo_object_mock = get_ilo_object_mock.return_value + ilo_object_mock.set_bios_settings.side_effect = ilo_error.IloError( + 'err') + step = 'apply_configuration' + self.assertRaises(exception.NodeCleaningFailure, + task.driver.bios._execute_pre_boot_bios_step, + task, step, data) + + @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, + autospec=True) + def test__execute_pre_boot_bios_step_reset_bios_failed( + self, get_ilo_object_mock): + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + data = { + "SET_A": "VAL_A", + "SET_B": "VAL_B", + "SET_C": "VAL_C", + "SET_D": "VAL_D" + } + ilo_object_mock = get_ilo_object_mock.return_value + ilo_object_mock.reset_bios_to_default.side_effect = ( + ilo_error.IloError('err')) + step = 'factory_reset' + self.assertRaises(exception.NodeCleaningFailure, + task.driver.bios._execute_pre_boot_bios_step, + task, step, data) + + @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, + autospec=True) + def test__execute_post_boot_bios_step_apply_configuration( + self, get_ilo_object_mock): + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + driver_info = task.node.driver_internal_info + driver_info.update({'apply_bios': True}) + task.node.driver_internal_info = driver_info + task.node.save() + ilo_object_mock = get_ilo_object_mock.return_value + step = 'apply_configuration' + task.driver.bios._execute_post_boot_bios_step(task, step) + driver_info = task.node.driver_internal_info + self.assertTrue('apply_bios' not in driver_info) + ilo_object_mock.get_bios_settings_result.assert_called_once_with() + + @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, + autospec=True) + def test__execute_post_boot_bios_step_factory_reset( + self, get_ilo_object_mock): + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + driver_info = task.node.driver_internal_info + driver_info.update({'reset_bios': True}) + task.node.driver_internal_info = driver_info + task.node.save() + ilo_object_mock = get_ilo_object_mock.return_value + step = 'factory_reset' + task.driver.bios._execute_post_boot_bios_step(task, step) + driver_info = task.node.driver_internal_info + self.assertTrue('reset_bios' not in driver_info) + ilo_object_mock.get_bios_settings_result.assert_called_once_with() + + @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, + autospec=True) + def test__execute_post_boot_bios_step_invalid( + self, get_ilo_object_mock): + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + driver_info = task.node.driver_internal_info + driver_info.update({'apply_bios': True}) + task.node.driver_internal_info = driver_info + task.node.save() + step = 'invalid_step' + self.assertRaises(exception.NodeCleaningFailure, + task.driver.bios._execute_post_boot_bios_step, + task, step) + self.assertTrue( + 'apply_bios' not in task.node.driver_internal_info) + + @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, + autospec=True) + def test__execute_post_boot_bios_step_iloobj_failed( + self, get_ilo_object_mock): + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + driver_info = task.node.driver_internal_info + driver_info.update({'apply_bios': True}) + task.node.driver_internal_info = driver_info + task.node.save() + get_ilo_object_mock.side_effect = exception.MissingParameterValue( + 'err') + step = 'apply_configuration' + self.assertRaises(exception.NodeCleaningFailure, + task.driver.bios._execute_post_boot_bios_step, + task, step) + self.assertTrue( + 'apply_bios' not in task.node.driver_internal_info) + + @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, + autospec=True) + def test__execute_post_boot_bios_get_settings_error( + self, get_ilo_object_mock): + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + driver_info = task.node.driver_internal_info + driver_info.update({'apply_bios': True}) + task.node.driver_internal_info = driver_info + task.node.save() + ilo_object_mock = get_ilo_object_mock.return_value + + step = 'apply_configuration' + mdobj = { + "name": task.driver.bios._execute_post_boot_bios_step, + "args": (task, step,) + } + + self._test_ilo_error(ilo_error.IloCommandNotSupportedError, + [], + [], mdobj, + ilo_object_mock.get_bios_settings_result) + self.assertTrue( + 'apply_bios' not in task.node.driver_internal_info) + + @mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True, + autospec=True) + def test__execute_post_boot_bios_get_settings_failed( + self, get_ilo_object_mock): + + with task_manager.acquire(self.context, self.node.uuid, + shared=True) as task: + driver_info = task.node.driver_internal_info + driver_info.update({'reset_bios': True}) + task.node.driver_internal_info = driver_info + task.node.save() + ilo_object_mock = get_ilo_object_mock.return_value + ilo_object_mock.get_bios_settings_result.return_value = ( + {'status': 'failed', 'message': 'Some data'}) + step = 'factory_reset' + self.assertRaises(exception.NodeCleaningFailure, + task.driver.bios._execute_post_boot_bios_step, + task, step) + self.assertTrue( + 'reset_bios' not in task.node.driver_internal_info) @mock.patch.object(objects.BIOSSettingList, 'create') @mock.patch.object(objects.BIOSSettingList, 'save') @@ -205,7 +420,7 @@ class IloBiosTestCase(test_common.BaseIloTest): "SET_D": True } - ilo_object_mock.get_pending_bios_settings.return_value = settings + ilo_object_mock.get_current_bios_settings.return_value = settings expected_bios_settings = [ {"name": "SET_A", "value": True}, {"name": "SET_B", "value": True}, @@ -230,7 +445,7 @@ class IloBiosTestCase(test_common.BaseIloTest): ) sync_node_mock.return_value = all_settings task.driver.bios.cache_bios_settings(task) - ilo_object_mock.get_pending_bios_settings.assert_called_once_with() + ilo_object_mock.get_current_bios_settings.assert_called_once_with() actual_arg = sorted(sync_node_mock.call_args[0][2], key=lambda x: x.get("name")) expected_arg = sorted(expected_bios_settings, @@ -244,25 +459,29 @@ class IloBiosTestCase(test_common.BaseIloTest): delete_mock.assert_called_once_with( self.context, task.node.id, del_names) - def test_cache_bios_settings_missing_parameter(self): + @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) + def test_cache_bios_settings_missing_parameter(self, get_ilo_object_mock): with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: mdobj = { "name": task.driver.bios.cache_bios_settings, "args": (task,) } - self._test_ilo_error("missing_parameter", - ["get_pending_bios_settings"], mdobj) + self._test_ilo_error(exception.MissingParameterValue, + [], + [], mdobj, get_ilo_object_mock) - def test_cache_bios_settings_invalid_parameter(self): + @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) + def test_cache_bios_settings_invalid_parameter(self, get_ilo_object_mock): with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: mdobj = { "name": task.driver.bios.cache_bios_settings, "args": (task,) } - self._test_ilo_error("invalid_parameter", - ["get_pending_bios_settings"], mdobj) + self._test_ilo_error(exception.InvalidParameterValue, + [], + [], mdobj, get_ilo_object_mock) @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) def test_cache_bios_settings_with_ilo_error(self, get_ilo_object_mock): @@ -270,10 +489,15 @@ class IloBiosTestCase(test_common.BaseIloTest): with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: ilo_object_mock = get_ilo_object_mock.return_value - exc = ilo_error.IloError('error') - ilo_object_mock.get_pending_bios_settings.side_effect = exc - self.assertRaises(exception.NodeCleaningFailure, - task.driver.bios.cache_bios_settings, task) + mdobj = { + "name": task.driver.bios.cache_bios_settings, + "args": (task,) + } + self._test_ilo_error(ilo_error.IloError, + [], + [], + mdobj, + ilo_object_mock.get_current_bios_settings) @mock.patch.object(ilo_common, 'get_ilo_object', autospec=True) def test_cache_bios_settings_with_unknown_error(self, get_ilo_object_mock): @@ -281,7 +505,13 @@ class IloBiosTestCase(test_common.BaseIloTest): with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: ilo_object_mock = get_ilo_object_mock.return_value - exc = ilo_error.IloCommandNotSupportedError('error') - ilo_object_mock.get_pending_bios_settings.side_effect = exc - self.assertRaises(exception.NodeCleaningFailure, - task.driver.bios.cache_bios_settings, task) + + mdobj = { + "name": task.driver.bios.cache_bios_settings, + "args": (task,) + } + self._test_ilo_error(ilo_error.IloCommandNotSupportedError, + [], + [], + mdobj, + ilo_object_mock.get_current_bios_settings) diff --git a/releasenotes/notes/ilo-async-bios-clean-steps-15e49545ba818997.yaml b/releasenotes/notes/ilo-async-bios-clean-steps-15e49545ba818997.yaml new file mode 100644 index 0000000000..91819d1705 --- /dev/null +++ b/releasenotes/notes/ilo-async-bios-clean-steps-15e49545ba818997.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Makes all ``ilo`` driver BIOS interface clean steps as asynchronous. This is + required to ensure the settings on the baremetal node are consistent with + the settings stored in the database irrespective of the node clean step + status. Refer bug `2004066 + `_ for details.