Make iLO BIOS interface clean steps asynchronous

Make iLO BIOS interface clean steps asynchronous to ensure the
BIOS settings on the node are consistent with the settings stored
in the database. Node goes through the power cycle after the
settings are applied. Once the node reboots, ironic gets the current
settings from the node, caches the settings in the database,
checks for any errors from the status message and marks the clean
step as failed or success accordingly.

Change-Id: I00deaa2f2b68d2a34f8592ea20c36349a87d6c23
Story: #2004066
Task: #27074
This commit is contained in:
vmud213 2018-09-13 15:30:53 +05:30
parent 680e5b5687
commit 335f6b4fd1
3 changed files with 468 additions and 148 deletions

View File

@ -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,

View File

@ -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,33 +52,29 @@ 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_common, 'get_ilo_object', spec_set=True,
@mock.patch.object(ilo_bios.IloBIOS, '_execute_post_boot_bios_step',
autospec=True)
def test_apply_configuration(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
data = [
@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",
},
@ -88,105 +88,320 @@ class IloBiosTestCase(test_common.BaseIloTest):
"name": "SET_D", "value": "VAL_D",
}
]
task.driver.bios.apply_configuration(task, data)
expected = {
"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)
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)
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)
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_common, 'get_ilo_object', spec_set=True,
@mock.patch.object(ilo_bios.IloBIOS, '_execute_post_boot_bios_step',
autospec=True)
def test_apply_configuration_with_ilo_error(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
data = [
@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",
}
]
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)
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_factory_reset(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
task.driver.bios.factory_reset(task)
data = {
"SET_A": "VAL_A",
"SET_B": "VAL_B",
"SET_C": "VAL_C",
"SET_D": "VAL_D"
}
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__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 = {
"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)

View File

@ -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
<https://storyboard.openstack.org/#!/story/2004066>`_ for details.