Merge "Add deploy steps for iLO Management interface"
This commit is contained in:
commit
f2086372ec
|
@ -57,40 +57,114 @@ BOOT_DEVICE_ILO_TO_GENERIC = {
|
|||
MANAGEMENT_PROPERTIES = ilo_common.REQUIRED_PROPERTIES.copy()
|
||||
MANAGEMENT_PROPERTIES.update(ilo_common.CLEAN_PROPERTIES)
|
||||
|
||||
_ACTIVATE_ILO_LICENSE_ARGSINFO = {
|
||||
'ilo_license_key': {
|
||||
'description': (
|
||||
'The HPE iLO Advanced license key to activate enterprise '
|
||||
'features.'
|
||||
),
|
||||
'required': True
|
||||
}
|
||||
}
|
||||
|
||||
def _execute_ilo_clean_step(node, step, *args, **kwargs):
|
||||
"""Executes a particular clean step.
|
||||
_RESET_ILO_CREDENTIALS_ARGSINFO = {
|
||||
'ilo_password': {
|
||||
'description': (
|
||||
'Password string for iLO user with administrative privileges '
|
||||
'being set in the driver_info property "ilo_username".'
|
||||
),
|
||||
'required': True
|
||||
}
|
||||
}
|
||||
|
||||
_FIRMWARE_UPDATE_ARGSINFO = {
|
||||
'firmware_update_mode': {
|
||||
'description': (
|
||||
"This argument indicates the mode (or mechanism) of firmware "
|
||||
"update procedure. Supported value is 'ilo'."
|
||||
),
|
||||
'required': True
|
||||
},
|
||||
'firmware_images': {
|
||||
'description': (
|
||||
"This argument represents the ordered list of JSON "
|
||||
"dictionaries of firmware images. Each firmware image "
|
||||
"dictionary consists of three mandatory fields, namely 'url', "
|
||||
"'checksum' and 'component'. These fields represent firmware "
|
||||
"image location URL, md5 checksum of image file and firmware "
|
||||
"component type respectively. The supported firmware URL "
|
||||
"schemes are 'file', 'http', 'https' and 'swift'. The "
|
||||
"supported values for firmware component are 'ilo', 'cpld', "
|
||||
"'power_pic', 'bios' and 'chassis'. The firmware images will "
|
||||
"be applied (in the order given) one by one on the baremetal "
|
||||
"server. For more information, see "
|
||||
"https://docs.openstack.org/ironic/latest/admin/drivers/ilo.html#initiating-firmware-update-as-manual-clean-step" # noqa
|
||||
),
|
||||
'required': True
|
||||
}
|
||||
}
|
||||
|
||||
_FIRMWARE_UPDATE_SUM_ARGSINFO = {
|
||||
'url': {
|
||||
'description': (
|
||||
"The image location for SPP (Service Pack for Proliant) ISO."
|
||||
),
|
||||
'required': True
|
||||
},
|
||||
'checksum': {
|
||||
'description': (
|
||||
"The md5 checksum of the SPP image file."
|
||||
),
|
||||
'required': True
|
||||
},
|
||||
'components': {
|
||||
'description': (
|
||||
"The list of firmware component filenames. If not specified, "
|
||||
"SUM updates all the firmware components."
|
||||
),
|
||||
'required': False
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def _execute_ilo_step(node, step, *args, **kwargs):
|
||||
"""Executes a particular deploy or clean step.
|
||||
|
||||
:param node: an Ironic node object.
|
||||
:param step: a clean step to be executed.
|
||||
:param args: The args to be passed to the clean step.
|
||||
:param kwargs: The kwargs to be passed to the clean step.
|
||||
:raises: NodeCleaningFailure, on failure to execute step.
|
||||
:param step: a step to be executed.
|
||||
:param args: The args to be passed to the step.
|
||||
:param kwargs: The kwargs to be passed to the step.
|
||||
:raises: NodeCleaningFailure, on failure to execute the clean step.
|
||||
:raises: InstanceDeployFailure, on failure to execute the deploy step.
|
||||
"""
|
||||
ilo_object = ilo_common.get_ilo_object(node)
|
||||
|
||||
try:
|
||||
clean_step = getattr(ilo_object, step)
|
||||
step_method = getattr(ilo_object, step)
|
||||
except AttributeError:
|
||||
# The specified clean step is not present in the proliantutils
|
||||
# The specified clean/deploy step is not present in the proliantutils
|
||||
# package. Raise exception to update the proliantutils package
|
||||
# to newer version.
|
||||
raise exception.NodeCleaningFailure(
|
||||
_("Clean step '%s' not found. 'proliantutils' package needs to be "
|
||||
"updated.") % step)
|
||||
msg = (_("Step '%s' not found. 'proliantutils' package needs to be "
|
||||
"updated.") % step)
|
||||
if node.clean_step:
|
||||
raise exception.NodeCleaningFailure(msg)
|
||||
raise exception.InstanceDeployFailure(msg)
|
||||
try:
|
||||
clean_step(*args, **kwargs)
|
||||
step_method(*args, **kwargs)
|
||||
except ilo_error.IloCommandNotSupportedError:
|
||||
# This clean step is not supported on Gen8 and below servers.
|
||||
# Log the failure and continue with cleaning.
|
||||
LOG.warning("'%(step)s' clean step is not supported on node "
|
||||
"%(uuid)s. Skipping the clean step.",
|
||||
# This step is not supported on Gen8 and below servers.
|
||||
# Log the failure and continue with cleaning or deployment.
|
||||
LOG.warning("'%(step)s' step is not supported on node "
|
||||
"%(uuid)s. Skipping the step.",
|
||||
{'step': step, 'uuid': node.uuid})
|
||||
except ilo_error.IloError as ilo_exception:
|
||||
raise exception.NodeCleaningFailure(_(
|
||||
"Clean step %(step)s failed "
|
||||
"on node %(node)s with error: %(err)s") %
|
||||
{'node': node.uuid, 'step': step, 'err': ilo_exception})
|
||||
msg = (_("Step %(step)s failed on node %(node)s with "
|
||||
"error: %(err)s") %
|
||||
{'node': node.uuid, 'step': step, 'err': ilo_exception})
|
||||
if node.clean_step:
|
||||
raise exception.NodeCleaningFailure(msg)
|
||||
raise exception.InstanceDeployFailure(msg)
|
||||
|
||||
|
||||
def _should_collect_logs(command):
|
||||
|
@ -232,39 +306,54 @@ class IloManagement(base.ManagementInterface):
|
|||
return ipmi_management.get_sensors_data(task)
|
||||
|
||||
@METRICS.timer('IloManagement.reset_ilo')
|
||||
@base.deploy_step(priority=0)
|
||||
@base.clean_step(priority=CONF.ilo.clean_priority_reset_ilo)
|
||||
def reset_ilo(self, task):
|
||||
"""Resets the iLO.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:raises: NodeCleaningFailure, on failure to execute step.
|
||||
:raises: NodeCleaningFailure, on failure to execute of clean step.
|
||||
:raises: InstanceDeployFailure, on failure to execute of deploy step.
|
||||
"""
|
||||
return _execute_ilo_clean_step(task.node, 'reset_ilo')
|
||||
node = task.node
|
||||
_execute_ilo_step(node, 'reset_ilo')
|
||||
|
||||
# Reset iLO ejects virtual media
|
||||
# Re-create the environment for agent boot, if required
|
||||
task.driver.boot.clean_up_ramdisk(task)
|
||||
deploy_opts = deploy_utils.build_agent_options(node)
|
||||
task.driver.boot.prepare_ramdisk(task, deploy_opts)
|
||||
|
||||
@METRICS.timer('IloManagement.reset_ilo_credential')
|
||||
@base.deploy_step(priority=0, argsinfo=_RESET_ILO_CREDENTIALS_ARGSINFO)
|
||||
@base.clean_step(priority=CONF.ilo.clean_priority_reset_ilo_credential)
|
||||
def reset_ilo_credential(self, task):
|
||||
def reset_ilo_credential(self, task, change_password=None):
|
||||
"""Resets the iLO password.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:raises: NodeCleaningFailure, on failure to execute step.
|
||||
:param change_password: Value for password to update on iLO.
|
||||
:raises: NodeCleaningFailure, on failure to execute of clean step.
|
||||
:raises: InstanceDeployFailure, on failure to execute of deploy step.
|
||||
"""
|
||||
info = task.node.driver_info
|
||||
password = info.pop('ilo_change_password', None)
|
||||
password = change_password
|
||||
if not password:
|
||||
password = info.pop('ilo_change_password', None)
|
||||
|
||||
if not password:
|
||||
LOG.info("Missing 'ilo_change_password' parameter in "
|
||||
"driver_info. Clean step 'reset_ilo_credential' is "
|
||||
"driver_info. Step 'reset_ilo_credential' is "
|
||||
"not performed on node %s.", task.node.uuid)
|
||||
return
|
||||
|
||||
_execute_ilo_clean_step(task.node, 'reset_ilo_credential', password)
|
||||
_execute_ilo_step(task.node, 'reset_ilo_credential', password)
|
||||
|
||||
info['ilo_password'] = password
|
||||
task.node.driver_info = info
|
||||
task.node.save()
|
||||
|
||||
@METRICS.timer('IloManagement.reset_bios_to_default')
|
||||
@base.deploy_step(priority=0)
|
||||
@base.clean_step(priority=CONF.ilo.clean_priority_reset_bios_to_default)
|
||||
def reset_bios_to_default(self, task):
|
||||
"""Resets the BIOS settings to default values.
|
||||
|
@ -273,11 +362,13 @@ class IloManagement(base.ManagementInterface):
|
|||
only on HP Proliant Gen9 and above servers.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:raises: NodeCleaningFailure, on failure to execute step.
|
||||
:raises: NodeCleaningFailure, on failure to execute of clean step.
|
||||
:raises: InstanceDeployFailure, on failure to execute of deploy step.
|
||||
"""
|
||||
return _execute_ilo_clean_step(task.node, 'reset_bios_to_default')
|
||||
return _execute_ilo_step(task.node, 'reset_bios_to_default')
|
||||
|
||||
@METRICS.timer('IloManagement.reset_secure_boot_keys_to_default')
|
||||
@base.deploy_step(priority=0)
|
||||
@base.clean_step(priority=CONF.ilo.
|
||||
clean_priority_reset_secure_boot_keys_to_default)
|
||||
def reset_secure_boot_keys_to_default(self, task):
|
||||
|
@ -287,11 +378,13 @@ class IloManagement(base.ManagementInterface):
|
|||
operation is supported only on HP Proliant Gen9 and above servers.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:raises: NodeCleaningFailure, on failure to execute step.
|
||||
:raises: NodeCleaningFailure, on failure to execute of clean step.
|
||||
:raises: InstanceDeployFailure, on failure to execute of deploy step.
|
||||
"""
|
||||
return _execute_ilo_clean_step(task.node, 'reset_secure_boot_keys')
|
||||
return _execute_ilo_step(task.node, 'reset_secure_boot_keys')
|
||||
|
||||
@METRICS.timer('IloManagement.clear_secure_boot_keys')
|
||||
@base.deploy_step(priority=0)
|
||||
@base.clean_step(priority=CONF.ilo.clean_priority_clear_secure_boot_keys)
|
||||
def clear_secure_boot_keys(self, task):
|
||||
"""Clear all secure boot keys.
|
||||
|
@ -300,9 +393,10 @@ class IloManagement(base.ManagementInterface):
|
|||
on HP Proliant Gen9 and above servers.
|
||||
|
||||
:param task: a task from TaskManager.
|
||||
:raises: NodeCleaningFailure, on failure to execute step.
|
||||
:raises: NodeCleaningFailure, on failure to execute of clean step.
|
||||
:raises: InstanceDeployFailure, on failure to execute of deploy step.
|
||||
"""
|
||||
return _execute_ilo_clean_step(task.node, 'clear_secure_boot_keys')
|
||||
return _execute_ilo_step(task.node, 'clear_secure_boot_keys')
|
||||
|
||||
@METRICS.timer('IloManagement.activate_license')
|
||||
@base.clean_step(priority=0, abortable=False, argsinfo={
|
||||
|
@ -319,7 +413,7 @@ class IloManagement(base.ManagementInterface):
|
|||
|
||||
:param task: a TaskManager object.
|
||||
:raises: InvalidParameterValue, if any of the arguments are invalid.
|
||||
:raises: NodeCleaningFailure, on failure to execute clean step.
|
||||
:raises: NodeCleaningFailure, on failure to execute of clean step.
|
||||
"""
|
||||
ilo_license_key = kwargs.get('ilo_license_key')
|
||||
node = task.node
|
||||
|
@ -334,36 +428,13 @@ class IloManagement(base.ManagementInterface):
|
|||
|
||||
LOG.debug("Activating iLO license for node %(node)s ...",
|
||||
{'node': node.uuid})
|
||||
_execute_ilo_clean_step(node, 'activate_license', ilo_license_key)
|
||||
_execute_ilo_step(node, 'activate_license', ilo_license_key)
|
||||
LOG.info("iLO license activated for node %s.", node.uuid)
|
||||
|
||||
@METRICS.timer('IloManagement.update_firmware')
|
||||
@base.clean_step(priority=0, abortable=False, argsinfo={
|
||||
'firmware_update_mode': {
|
||||
'description': (
|
||||
"This argument indicates the mode (or mechanism) of firmware "
|
||||
"update procedure. Supported value is 'ilo'."
|
||||
),
|
||||
'required': True
|
||||
},
|
||||
'firmware_images': {
|
||||
'description': (
|
||||
"This argument represents the ordered list of JSON "
|
||||
"dictionaries of firmware images. Each firmware image "
|
||||
"dictionary consists of three mandatory fields, namely 'url', "
|
||||
"'checksum' and 'component'. These fields represent firmware "
|
||||
"image location URL, md5 checksum of image file and firmware "
|
||||
"component type respectively. The supported firmware URL "
|
||||
"schemes are 'file', 'http', 'https' and 'swift'. The "
|
||||
"supported values for firmware component are 'ilo', 'cpld', "
|
||||
"'power_pic', 'bios' and 'chassis'. The firmware images will "
|
||||
"be applied (in the order given) one by one on the baremetal "
|
||||
"server. For more information, see "
|
||||
"https://docs.openstack.org/ironic/latest/admin/drivers/ilo.html#initiating-firmware-update-as-manual-clean-step" # noqa
|
||||
),
|
||||
'required': True
|
||||
}
|
||||
})
|
||||
@base.deploy_step(priority=0, argsinfo=_FIRMWARE_UPDATE_ARGSINFO)
|
||||
@base.clean_step(priority=0, abortable=False,
|
||||
argsinfo=_FIRMWARE_UPDATE_ARGSINFO)
|
||||
@firmware_processor.verify_firmware_update_args
|
||||
def update_firmware(self, task, **kwargs):
|
||||
"""Updates the firmware.
|
||||
|
@ -371,7 +442,8 @@ class IloManagement(base.ManagementInterface):
|
|||
:param task: a TaskManager object.
|
||||
:raises: InvalidParameterValue if update firmware mode is not 'ilo'.
|
||||
Even applicable for invalid input cases.
|
||||
:raises: NodeCleaningFailure, on failure to execute step.
|
||||
:raises: NodeCleaningFailure, on failure to execute of clean step.
|
||||
:raises: InstanceDeployFailure, on failure to execute of deploy step.
|
||||
"""
|
||||
node = task.node
|
||||
fw_location_objs_n_components = []
|
||||
|
@ -409,7 +481,10 @@ class IloManagement(base.ManagementInterface):
|
|||
"on node: %(node)s ... failed",
|
||||
{'firmware_image': firmware_image_info,
|
||||
'node': node.uuid})
|
||||
raise exception.NodeCleaningFailure(node=node.uuid, reason=ilo_exc)
|
||||
if node.clean_step:
|
||||
raise exception.NodeCleaningFailure(node=node.uuid,
|
||||
reason=ilo_exc)
|
||||
raise exception.InstanceDeployFailure(reason=ilo_exc)
|
||||
|
||||
# Updating of firmware images happen here.
|
||||
try:
|
||||
|
@ -419,13 +494,14 @@ class IloManagement(base.ManagementInterface):
|
|||
"node: %(node)s ... in progress",
|
||||
{'firmware_file': fw_location, 'node': node.uuid})
|
||||
|
||||
_execute_ilo_clean_step(
|
||||
_execute_ilo_step(
|
||||
node, 'update_firmware', fw_location, component)
|
||||
|
||||
LOG.debug("Firmware update for %(firmware_file)s on "
|
||||
"node: %(node)s ... done",
|
||||
{'firmware_file': fw_location, 'node': node.uuid})
|
||||
except exception.NodeCleaningFailure:
|
||||
except (exception.NodeCleaningFailure,
|
||||
exception.InstanceDeployFailure):
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error("Firmware update for %(firmware_file)s on "
|
||||
"node: %(node)s failed.",
|
||||
|
@ -434,35 +510,23 @@ class IloManagement(base.ManagementInterface):
|
|||
for fw_loc_obj_n_comp_tup in fw_location_objs_n_components:
|
||||
fw_loc_obj_n_comp_tup[0].remove()
|
||||
|
||||
# Firmware might have ejected the virtual media, if it was used.
|
||||
# Re-create the environment for agent boot, if required
|
||||
task.driver.boot.clean_up_ramdisk(task)
|
||||
deploy_opts = deploy_utils.build_agent_options(node)
|
||||
task.driver.boot.prepare_ramdisk(task, deploy_opts)
|
||||
|
||||
LOG.info("All Firmware update operations completed successfully "
|
||||
"for node: %s.", node.uuid)
|
||||
|
||||
@METRICS.timer('IloManagement.update_firmware_sum')
|
||||
@base.clean_step(priority=0, abortable=False, argsinfo={
|
||||
'url': {
|
||||
'description': (
|
||||
"The image location for SPP (Service Pack for Proliant) ISO."
|
||||
),
|
||||
'required': True
|
||||
},
|
||||
'checksum': {
|
||||
'description': (
|
||||
"The md5 checksum of the SPP image file."
|
||||
),
|
||||
'required': True
|
||||
},
|
||||
'components': {
|
||||
'description': (
|
||||
"The list of firmware component filenames. If not specified, "
|
||||
"SUM updates all the firmware components."
|
||||
),
|
||||
'required': False}
|
||||
})
|
||||
@base.clean_step(priority=0, abortable=False,
|
||||
argsinfo=_FIRMWARE_UPDATE_SUM_ARGSINFO)
|
||||
def update_firmware_sum(self, task, **kwargs):
|
||||
"""Updates the firmware using Smart Update Manager (SUM).
|
||||
|
||||
:param task: a TaskManager object.
|
||||
:raises: NodeCleaningFailure, on failure to execute step.
|
||||
:raises: NodeCleaningFailure, on failure to execute of clean step.
|
||||
"""
|
||||
node = task.node
|
||||
# The arguments are validated and sent to the ProliantHardwareManager
|
||||
|
|
|
@ -24,6 +24,7 @@ from ironic.common import states
|
|||
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 boot as ilo_boot
|
||||
from ironic.drivers.modules.ilo import common as ilo_common
|
||||
from ironic.drivers.modules.ilo import management as ilo_management
|
||||
from ironic.drivers.modules import ipmitool
|
||||
|
@ -198,50 +199,84 @@ class IloManagementTestCase(test_common.BaseIloTest):
|
|||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test__execute_ilo_clean_step_ok(self, get_ilo_object_mock):
|
||||
def test__execute_ilo_step_ok(self, get_ilo_object_mock):
|
||||
ilo_mock = get_ilo_object_mock.return_value
|
||||
clean_step_mock = getattr(ilo_mock, 'fake-step')
|
||||
ilo_management._execute_ilo_clean_step(
|
||||
step_mock = getattr(ilo_mock, 'fake-step')
|
||||
ilo_management._execute_ilo_step(
|
||||
self.node, 'fake-step', 'args', kwarg='kwarg')
|
||||
clean_step_mock.assert_called_once_with('args', kwarg='kwarg')
|
||||
step_mock.assert_called_once_with('args', kwarg='kwarg')
|
||||
|
||||
@mock.patch.object(ilo_management, 'LOG', spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test__execute_ilo_clean_step_not_supported(self, get_ilo_object_mock,
|
||||
log_mock):
|
||||
def test__execute_ilo_step_not_supported(self, get_ilo_object_mock,
|
||||
log_mock):
|
||||
ilo_mock = get_ilo_object_mock.return_value
|
||||
exc = ilo_error.IloCommandNotSupportedError("error")
|
||||
clean_step_mock = getattr(ilo_mock, 'fake-step')
|
||||
clean_step_mock.side_effect = exc
|
||||
ilo_management._execute_ilo_clean_step(
|
||||
step_mock = getattr(ilo_mock, 'fake-step')
|
||||
step_mock.side_effect = exc
|
||||
ilo_management._execute_ilo_step(
|
||||
self.node, 'fake-step', 'args', kwarg='kwarg')
|
||||
clean_step_mock.assert_called_once_with('args', kwarg='kwarg')
|
||||
step_mock.assert_called_once_with('args', kwarg='kwarg')
|
||||
self.assertTrue(log_mock.warning.called)
|
||||
|
||||
@mock.patch.object(ilo_common, 'get_ilo_object', spec_set=True,
|
||||
autospec=True)
|
||||
def test__execute_ilo_clean_step_fail(self, get_ilo_object_mock):
|
||||
def _test__execute_ilo_step_fail(self, get_ilo_object_mock):
|
||||
if self.node.clean_step:
|
||||
step = self.node.clean_step
|
||||
step_name = step['step']
|
||||
exept = exception.NodeCleaningFailure
|
||||
else:
|
||||
step = self.node.deploy_step
|
||||
step_name = step['step']
|
||||
exept = exception.InstanceDeployFailure
|
||||
ilo_mock = get_ilo_object_mock.return_value
|
||||
exc = ilo_error.IloError("error")
|
||||
clean_step_mock = getattr(ilo_mock, 'fake-step')
|
||||
clean_step_mock.side_effect = exc
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
ilo_management._execute_ilo_clean_step,
|
||||
self.node, 'fake-step', 'args', kwarg='kwarg')
|
||||
clean_step_mock.assert_called_once_with('args', kwarg='kwarg')
|
||||
step_mock = getattr(ilo_mock, step_name)
|
||||
step_mock.side_effect = exc
|
||||
self.assertRaises(exept,
|
||||
ilo_management._execute_ilo_step,
|
||||
self.node, step_name, 'args', kwarg='kwarg')
|
||||
step_mock.assert_called_once_with('args', kwarg='kwarg')
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
def test__execute_ilo_step_fail_clean(self):
|
||||
self.node.clean_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'fake-step',
|
||||
'argsinfo': {}}
|
||||
self.node.save()
|
||||
self._test__execute_ilo_step_fail()
|
||||
|
||||
def test__execute_ilo_step_fail_deploy(self):
|
||||
self.node.deploy_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'fake-step',
|
||||
'argsinfo': {}}
|
||||
self.node.save()
|
||||
self._test__execute_ilo_step_fail()
|
||||
|
||||
@mock.patch.object(deploy_utils, 'build_agent_options',
|
||||
spec_set=True, autospec=True)
|
||||
def test_reset_ilo(self, clean_step_mock):
|
||||
@mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'clean_up_ramdisk',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'prepare_ramdisk',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_reset_ilo(
|
||||
self, execute_step_mock, prepare_mock, cleanup_mock, build_mock):
|
||||
build_mock.return_value = {'a': 'b'}
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.management.reset_ilo(task)
|
||||
clean_step_mock.assert_called_once_with(task.node, 'reset_ilo')
|
||||
execute_step_mock.assert_called_once_with(task.node, 'reset_ilo')
|
||||
cleanup_mock.assert_called_once_with(mock.ANY, task)
|
||||
build_mock.assert_called_once_with(task.node)
|
||||
prepare_mock.assert_called_once_with(
|
||||
mock.ANY, mock.ANY, {'a': 'b'})
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_reset_ilo_credential_ok(self, clean_step_mock):
|
||||
def test_reset_ilo_credential_ok(self, step_mock):
|
||||
info = self.node.driver_info
|
||||
info['ilo_change_password'] = "fake-password"
|
||||
self.node.driver_info = info
|
||||
|
@ -249,66 +284,79 @@ class IloManagementTestCase(test_common.BaseIloTest):
|
|||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.management.reset_ilo_credential(task)
|
||||
clean_step_mock.assert_called_once_with(
|
||||
step_mock.assert_called_once_with(
|
||||
task.node, 'reset_ilo_credential', 'fake-password')
|
||||
self.assertNotIn('ilo_change_password', task.node.driver_info)
|
||||
self.assertEqual('fake-password',
|
||||
task.node.driver_info['ilo_password'])
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_reset_ilo_credential_pass_as_arg_ok(self, step_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.management.reset_ilo_credential(
|
||||
task, change_password='fake-password')
|
||||
step_mock.assert_called_once_with(
|
||||
task.node, 'reset_ilo_credential', 'fake-password')
|
||||
self.assertNotIn('ilo_change_password', task.node.driver_info)
|
||||
self.assertEqual('fake-password',
|
||||
task.node.driver_info['ilo_password'])
|
||||
|
||||
@mock.patch.object(ilo_management, 'LOG', spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_reset_ilo_credential_no_password(self, clean_step_mock,
|
||||
def test_reset_ilo_credential_no_password(self, step_mock,
|
||||
log_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.management.reset_ilo_credential(task)
|
||||
self.assertFalse(clean_step_mock.called)
|
||||
self.assertFalse(step_mock.called)
|
||||
self.assertTrue(log_mock.info.called)
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_reset_bios_to_default(self, clean_step_mock):
|
||||
def test_reset_bios_to_default(self, step_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.management.reset_bios_to_default(task)
|
||||
clean_step_mock.assert_called_once_with(task.node,
|
||||
'reset_bios_to_default')
|
||||
step_mock.assert_called_once_with(task.node,
|
||||
'reset_bios_to_default')
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_reset_secure_boot_keys_to_default(self, clean_step_mock):
|
||||
def test_reset_secure_boot_keys_to_default(self, step_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.management.reset_secure_boot_keys_to_default(task)
|
||||
clean_step_mock.assert_called_once_with(task.node,
|
||||
'reset_secure_boot_keys')
|
||||
step_mock.assert_called_once_with(task.node,
|
||||
'reset_secure_boot_keys')
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_clear_secure_boot_keys(self, clean_step_mock):
|
||||
def test_clear_secure_boot_keys(self, step_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.management.clear_secure_boot_keys(task)
|
||||
clean_step_mock.assert_called_once_with(task.node,
|
||||
'clear_secure_boot_keys')
|
||||
step_mock.assert_called_once_with(task.node,
|
||||
'clear_secure_boot_keys')
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_activate_license(self, clean_step_mock):
|
||||
def test_activate_license(self, step_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
activate_license_args = {
|
||||
'ilo_license_key': 'XXXXX-YYYYY-ZZZZZ-XYZZZ-XXYYZ'}
|
||||
task.driver.management.activate_license(task,
|
||||
**activate_license_args)
|
||||
clean_step_mock.assert_called_once_with(
|
||||
step_mock.assert_called_once_with(
|
||||
task.node, 'activate_license', 'XXXXX-YYYYY-ZZZZZ-XYZZZ-XXYYZ')
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
def test_activate_license_no_or_invalid_format_license_key(
|
||||
self, clean_step_mock):
|
||||
self, step_mock):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
for license_key_value in (None, [], {}):
|
||||
|
@ -317,48 +365,32 @@ class IloManagementTestCase(test_common.BaseIloTest):
|
|||
task.driver.management.activate_license,
|
||||
task,
|
||||
**activate_license_args)
|
||||
self.assertFalse(clean_step_mock.called)
|
||||
self.assertFalse(step_mock.called)
|
||||
|
||||
@mock.patch.object(deploy_utils, 'build_agent_options',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'clean_up_ramdisk',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_boot.IloVirtualMediaBoot, 'prepare_ramdisk',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management, 'LOG')
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management.firmware_processor, 'FirmwareProcessor',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_common, 'remove_single_or_list_of_files',
|
||||
spec_set=True, autospec=True)
|
||||
def test_update_firmware_calls_clean_step_foreach_url(
|
||||
self, remove_file_mock, FirmwareProcessor_mock, clean_step_mock,
|
||||
LOG_mock):
|
||||
def _test_update_firmware_calls_step_foreach_url(
|
||||
self, remove_file_mock, FirmwareProcessor_mock, execute_step_mock,
|
||||
LOG_mock, prepare_mock, cleanup_mock, build_mock):
|
||||
if self.node.clean_step:
|
||||
step = self.node.clean_step
|
||||
else:
|
||||
step = self.node.deploy_step
|
||||
build_mock.return_value = {'a': 'b'}
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
# | GIVEN |
|
||||
firmware_images = [
|
||||
{
|
||||
'url': 'file:///any_path',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'http://any_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'cpld'
|
||||
},
|
||||
{
|
||||
'url': 'https://any_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'power_pic'
|
||||
},
|
||||
{
|
||||
'url': 'swift://container/object',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
},
|
||||
{
|
||||
'url': 'file:///any_path',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'chassis'
|
||||
}
|
||||
]
|
||||
firmware_update_args = step['argsinfo']
|
||||
FirmwareProcessor_mock.return_value.process_fw_on.side_effect = [
|
||||
ilo_management.firmware_processor.FirmwareImageLocation(
|
||||
'fw_location_for_filepath', 'filepath'),
|
||||
|
@ -371,12 +403,8 @@ class IloManagementTestCase(test_common.BaseIloTest):
|
|||
ilo_management.firmware_processor.FirmwareImageLocation(
|
||||
'fw_location_for_another_filepath', 'filepath2')
|
||||
]
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': firmware_images}
|
||||
# | WHEN |
|
||||
task.driver.management.update_firmware(task,
|
||||
**firmware_update_args)
|
||||
# | THEN |
|
||||
calls = [mock.call(task.node, 'update_firmware',
|
||||
'fw_location_for_filepath', 'ilo'),
|
||||
mock.call(task.node, 'update_firmware',
|
||||
|
@ -388,139 +416,338 @@ class IloManagementTestCase(test_common.BaseIloTest):
|
|||
mock.call(task.node, 'update_firmware',
|
||||
'fw_location_for_another_filepath', 'chassis'),
|
||||
]
|
||||
clean_step_mock.assert_has_calls(calls)
|
||||
self.assertEqual(5, clean_step_mock.call_count)
|
||||
execute_step_mock.assert_has_calls(calls)
|
||||
self.assertEqual(5, execute_step_mock.call_count)
|
||||
cleanup_mock.assert_called_once_with(mock.ANY, task)
|
||||
build_mock.assert_called_once_with(task.node)
|
||||
prepare_mock.assert_called_once_with(
|
||||
mock.ANY, mock.ANY, {'a': 'b'})
|
||||
|
||||
def test_update_firmware_throws_if_invalid_update_mode_provided(self):
|
||||
def test_update_firmware_calls_step_foreach_url_clean(self):
|
||||
firmware_images = [
|
||||
{
|
||||
'url': 'file:///any_path',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'http://any_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'cpld'
|
||||
},
|
||||
{
|
||||
'url': 'https://any_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'power_pic'
|
||||
},
|
||||
{
|
||||
'url': 'swift://container/object',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
},
|
||||
{
|
||||
'url': 'file:///any_path',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'chassis'
|
||||
}
|
||||
]
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': firmware_images}
|
||||
self.node.clean_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_calls_step_foreach_url()
|
||||
|
||||
def test_update_firmware_calls_step_foreach_url_deploy(self):
|
||||
firmware_images = [
|
||||
{
|
||||
'url': 'file:///any_path',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'http://any_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'cpld'
|
||||
},
|
||||
{
|
||||
'url': 'https://any_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'power_pic'
|
||||
},
|
||||
{
|
||||
'url': 'swift://container/object',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
},
|
||||
{
|
||||
'url': 'file:///any_path',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'chassis'
|
||||
}
|
||||
]
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': firmware_images}
|
||||
self.node.deploy_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_calls_step_foreach_url()
|
||||
|
||||
def _test_update_firmware_invalid_update_mode_provided(self):
|
||||
if self.node.clean_step:
|
||||
step = self.node.clean_step
|
||||
else:
|
||||
step = self.node.deploy_step
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
# | GIVEN |
|
||||
firmware_update_args = step['argsinfo']
|
||||
firmware_update_args = {'firmware_update_mode': 'invalid_mode',
|
||||
'firmware_images': None}
|
||||
# | WHEN & THEN |
|
||||
self.assertRaises(exception.InvalidParameterValue,
|
||||
task.driver.management.update_firmware,
|
||||
task,
|
||||
**firmware_update_args)
|
||||
|
||||
def test_update_firmware_throws_error_for_no_firmware_url(self):
|
||||
def test_update_firmware_invalid_update_mode_provided_clean(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'invalid_mode',
|
||||
'firmware_images': None}
|
||||
self.node.clean_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_invalid_update_mode_provided()
|
||||
|
||||
def test_update_firmware_invalid_update_mode_provided_deploy(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'invalid_mode',
|
||||
'firmware_images': None}
|
||||
self.node.deploy_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_invalid_update_mode_provided()
|
||||
|
||||
def _test_update_firmware_error_for_no_firmware_url(self):
|
||||
if self.node.clean_step:
|
||||
step = self.node.clean_step
|
||||
else:
|
||||
step = self.node.deploy_step
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
# | GIVEN |
|
||||
firmware_update_args = step['argsinfo']
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': []}
|
||||
# | WHEN & THEN |
|
||||
self.assertRaises(exception.InvalidParameterValue,
|
||||
task.driver.management.update_firmware,
|
||||
task,
|
||||
**firmware_update_args)
|
||||
|
||||
def test_update_firmware_throws_error_for_invalid_component_type(self):
|
||||
def test_update_firmware_error_for_no_firmware_url_clean(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': []}
|
||||
self.node.clean_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_error_for_no_firmware_url()
|
||||
|
||||
def test_update_firmware_error_for_no_firmware_url_deploy(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': []}
|
||||
self.node.deploy_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_error_for_no_firmware_url()
|
||||
|
||||
def _test_update_firmware_throws_error_for_invalid_component_type(self):
|
||||
if self.node.clean_step:
|
||||
step = self.node.clean_step
|
||||
exept = exception.NodeCleaningFailure
|
||||
else:
|
||||
step = self.node.deploy_step
|
||||
exept = exception.InstanceDeployFailure
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
# | GIVEN |
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'xyz'
|
||||
}
|
||||
]}
|
||||
# | WHEN & THEN |
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
firmware_update_args = step['argsinfo']
|
||||
self.assertRaises(exept,
|
||||
task.driver.management.update_firmware,
|
||||
task,
|
||||
**firmware_update_args)
|
||||
|
||||
def test_update_firmware_error_for_invalid_component_type_clean(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'xyz'
|
||||
}
|
||||
]}
|
||||
self.node.clean_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_throws_error_for_invalid_component_type()
|
||||
|
||||
def test_update_firmware_error_for_invalid_component_type_deploy(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'xyz'
|
||||
}
|
||||
]}
|
||||
self.node.deploy_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_throws_error_for_invalid_component_type()
|
||||
|
||||
@mock.patch.object(ilo_management, 'LOG')
|
||||
@mock.patch.object(ilo_management.firmware_processor.FirmwareProcessor,
|
||||
'process_fw_on', spec_set=True, autospec=True)
|
||||
def test_update_firmware_throws_error_for_checksum_validation_error(
|
||||
def _test_update_firmware_throws_error_for_checksum_validation_error(
|
||||
self, process_fw_on_mock, LOG_mock):
|
||||
if self.node.clean_step:
|
||||
step = self.node.clean_step
|
||||
exept = exception.NodeCleaningFailure
|
||||
else:
|
||||
step = self.node.deploy_step
|
||||
exept = exception.InstanceDeployFailure
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
# | GIVEN |
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'invalid_checksum',
|
||||
'component': 'bios'
|
||||
}
|
||||
]}
|
||||
firmware_update_args = step['argsinfo']
|
||||
process_fw_on_mock.side_effect = exception.ImageRefValidationFailed
|
||||
# | WHEN & THEN |
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
self.assertRaises(exept,
|
||||
task.driver.management.update_firmware,
|
||||
task,
|
||||
**firmware_update_args)
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
def test_update_firmware_error_for_checksum_validation_error_clean(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'invalid_checksum',
|
||||
'component': 'bios'
|
||||
}
|
||||
]}
|
||||
self.node.clean_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_throws_error_for_checksum_validation_error()
|
||||
|
||||
def test_update_firmware_error_for_checksum_validation_error_deploy(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'invalid_checksum',
|
||||
'component': 'bios'
|
||||
}
|
||||
]}
|
||||
self.node.deploy_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_throws_error_for_checksum_validation_error()
|
||||
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management.firmware_processor, 'FirmwareProcessor',
|
||||
spec_set=True, autospec=True)
|
||||
def test_update_firmware_doesnt_update_any_if_processing_on_any_url_fails(
|
||||
def _test_update_firmware_doesnt_update_any_if_any_url_fails(
|
||||
self, FirmwareProcessor_mock, clean_step_mock):
|
||||
"""update_firmware throws error for failure in processing any url
|
||||
|
||||
update_firmware doesn't invoke firmware update of proliantutils
|
||||
for any url if processing on any firmware url fails.
|
||||
"""
|
||||
if self.node.clean_step:
|
||||
step = self.node.clean_step
|
||||
exept = exception.NodeCleaningFailure
|
||||
else:
|
||||
step = self.node.deploy_step
|
||||
exept = exception.InstanceDeployFailure
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
# | GIVEN |
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'any_invalid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
}]
|
||||
}
|
||||
firmware_update_args = step['argsinfo']
|
||||
FirmwareProcessor_mock.return_value.process_fw_on.side_effect = [
|
||||
ilo_management.firmware_processor.FirmwareImageLocation(
|
||||
'extracted_firmware_url_of_any_valid_url', 'filename'),
|
||||
exception.IronicException
|
||||
]
|
||||
# | WHEN & THEN |
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
self.assertRaises(exept,
|
||||
task.driver.management.update_firmware,
|
||||
task,
|
||||
**firmware_update_args)
|
||||
self.assertFalse(clean_step_mock.called)
|
||||
|
||||
def test_update_firmware_doesnt_update_any_if_any_url_fails_clean(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'any_invalid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
}]
|
||||
}
|
||||
self.node.clean_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_doesnt_update_any_if_any_url_fails()
|
||||
|
||||
def test_update_firmware_doesnt_update_any_if_any_url_fails_deploy(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'any_invalid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
}]
|
||||
}
|
||||
self.node.deploy_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_doesnt_update_any_if_any_url_fails()
|
||||
|
||||
@mock.patch.object(ilo_management, 'LOG')
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_clean_step',
|
||||
@mock.patch.object(ilo_management, '_execute_ilo_step',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management.firmware_processor, 'FirmwareProcessor',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(ilo_management.firmware_processor.FirmwareImageLocation,
|
||||
'remove', spec_set=True, autospec=True)
|
||||
def test_update_firmware_cleans_all_files_if_exc_thrown(
|
||||
def _test_update_firmware_cleans_all_files_if_exc_thrown(
|
||||
self, remove_mock, FirmwareProcessor_mock, clean_step_mock,
|
||||
LOG_mock):
|
||||
if self.node.clean_step:
|
||||
step = self.node.clean_step
|
||||
exept = exception.NodeCleaningFailure
|
||||
else:
|
||||
step = self.node.deploy_step
|
||||
exept = exception.InstanceDeployFailure
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
# | GIVEN |
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'any_invalid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
}]
|
||||
}
|
||||
firmware_update_args = step['argsinfo']
|
||||
fw_loc_obj_1 = (ilo_management.firmware_processor.
|
||||
FirmwareImageLocation('extracted_firmware_url_1',
|
||||
'filename_1'))
|
||||
|
@ -530,10 +757,9 @@ class IloManagementTestCase(test_common.BaseIloTest):
|
|||
FirmwareProcessor_mock.return_value.process_fw_on.side_effect = [
|
||||
fw_loc_obj_1, fw_loc_obj_2
|
||||
]
|
||||
clean_step_mock.side_effect = exception.NodeCleaningFailure(
|
||||
clean_step_mock.side_effect = exept(
|
||||
node=self.node.uuid, reason='ilo_exc')
|
||||
# | WHEN & THEN |
|
||||
self.assertRaises(exception.NodeCleaningFailure,
|
||||
self.assertRaises(exept,
|
||||
task.driver.management.update_firmware,
|
||||
task,
|
||||
**firmware_update_args)
|
||||
|
@ -544,6 +770,46 @@ class IloManagementTestCase(test_common.BaseIloTest):
|
|||
remove_mock.assert_has_calls([mock.call(fw_loc_obj_1),
|
||||
mock.call(fw_loc_obj_2)])
|
||||
|
||||
def test_update_firmware_cleans_all_files_if_exc_thrown_clean(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'any_invalid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
}]
|
||||
}
|
||||
self.node.clean_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_cleans_all_files_if_exc_thrown()
|
||||
|
||||
def test_update_firmware_cleans_all_files_if_exc_thrown_deploy(self):
|
||||
firmware_update_args = {'firmware_update_mode': 'ilo',
|
||||
'firmware_images': [
|
||||
{
|
||||
'url': 'any_valid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'ilo'
|
||||
},
|
||||
{
|
||||
'url': 'any_invalid_url',
|
||||
'checksum': 'xxxx',
|
||||
'component': 'bios'
|
||||
}]
|
||||
}
|
||||
self.node.deploy_step = {'priority': 100, 'interface': 'management',
|
||||
'step': 'update_firmware',
|
||||
'argsinfo': firmware_update_args}
|
||||
self.node.save()
|
||||
self._test_update_firmware_cleans_all_files_if_exc_thrown()
|
||||
|
||||
@mock.patch.object(ilo_common, 'attach_vmedia', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(deploy_utils, 'agent_execute_clean_step',
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for deploy steps to ``management`` interface of ``ilo``
|
||||
hardware type. The methods ``reset_ilo``, ``reset_ilo_credential``,
|
||||
``reset_bios_to_default``, ``reset_secure_boot_keys_to_default``,
|
||||
``clear_secure_boot_keys`` and ``update_firmware`` can be used as
|
||||
deploy steps.
|
Loading…
Reference in New Issue