diff options
author | Zuul <zuul@review.opendev.org> | 2020-09-27 19:42:39 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2020-09-27 19:42:39 +0000 |
commit | ac19e6050d6347c51841d09b2e84fb2833b84aa5 (patch) | |
tree | caea7d0344404c7673d837de5f93f290ebcf2f5f /ironic | |
parent | d108a5c34bcb32c4ae1f0ab84c9e868dc4be712c (diff) | |
parent | b4fafd887814d006b1a43e30a5f36c0f1c7dcae9 (diff) | |
download | ironic-ac19e6050d6347c51841d09b2e84fb2833b84aa5.tar.gz |
Merge "Adding changes for iso less vmedia support"
Diffstat (limited to 'ironic')
-rw-r--r-- | ironic/drivers/modules/ilo/boot.py | 193 | ||||
-rw-r--r-- | ironic/drivers/modules/ilo/common.py | 2 | ||||
-rw-r--r-- | ironic/drivers/modules/image_utils.py | 23 | ||||
-rw-r--r-- | ironic/tests/unit/drivers/modules/ilo/test_boot.py | 485 | ||||
-rw-r--r-- | ironic/tests/unit/drivers/modules/ilo/test_common.py | 15 |
5 files changed, 241 insertions, 477 deletions
diff --git a/ironic/drivers/modules/ilo/boot.py b/ironic/drivers/modules/ilo/boot.py index 32ad16828..5ac645133 100644 --- a/ironic/drivers/modules/ilo/boot.py +++ b/ironic/drivers/modules/ilo/boot.py @@ -15,12 +15,9 @@ Boot Interface for iLO drivers and its supporting methods. """ -import os -import tempfile from urllib import parse as urlparse from ironic_lib import metrics_utils -from ironic_lib import utils as ironic_utils from oslo_config import cfg from oslo_log import log as logging from oslo_utils import excutils @@ -32,7 +29,6 @@ from ironic.common.i18n import _ from ironic.common import image_service from ironic.common import images from ironic.common import states -from ironic.common import swift from ironic.conductor import utils as manager_utils from ironic.drivers import base from ironic.drivers.modules import boot_mode_utils @@ -62,11 +58,6 @@ REQUIRED_PROPERTIES_UEFI_HTTPS_BOOT = { "Required."), 'ilo_deploy_ramdisk': _("URL or Glance UUID of the ramdisk that is " "mounted at boot time. Required."), - 'ilo_bootloader': _("URL or Glance UUID of the EFI system partition " - "image containing EFI boot loader. This image will " - "be used by ironic when building UEFI-bootable ISO " - "out of kernel and ramdisk. Required for UEFI " - "boot from partition images.") } RESCUE_PROPERTIES_UEFI_HTTPS_BOOT = { 'ilo_rescue_kernel': _('URL or Glance UUID of the rescue kernel. This ' @@ -74,6 +65,8 @@ RESCUE_PROPERTIES_UEFI_HTTPS_BOOT = { 'ilo_rescue_ramdisk': _('URL or Glance UUID of the rescue ramdisk with ' 'agent that is used at node rescue time. ' 'The value is required for rescue mode.'), +} +OPTIONAL_PROPERTIES = { 'ilo_bootloader': _("URL or Glance UUID of the EFI system partition " "image containing EFI boot loader. This image will " "be used by ironic when building UEFI-bootable ISO " @@ -82,6 +75,11 @@ RESCUE_PROPERTIES_UEFI_HTTPS_BOOT = { } COMMON_PROPERTIES = REQUIRED_PROPERTIES +KERNEL_RAMDISK_LABELS = { + 'deploy': REQUIRED_PROPERTIES_UEFI_HTTPS_BOOT, + 'rescue': RESCUE_PROPERTIES_UEFI_HTTPS_BOOT +} + def parse_driver_info(node, mode='deploy'): """Gets the driver specific Node deployment info. @@ -101,36 +99,43 @@ def parse_driver_info(node, mode='deploy'): """ info = node.driver_info d_info = {} - if mode == 'rescue': + if mode == 'rescue' and info.get('ilo_rescue_iso'): d_info['ilo_rescue_iso'] = info.get('ilo_rescue_iso') - else: + elif mode == 'deploy' and info.get('ilo_deploy_iso'): d_info['ilo_deploy_iso'] = info.get('ilo_deploy_iso') + else: + params_to_check = KERNEL_RAMDISK_LABELS[mode] - error_msg = (_("Error validating iLO virtual media for %s. Some " - "parameters were missing in node's driver_info") % mode) - deploy_utils.check_for_missing_params(d_info, error_msg) + d_info = {option: info.get(option) + for option in params_to_check} - return d_info + if not any(d_info.values()): + # NOTE(dtantsur): avoid situation when e.g. deploy_kernel comes + # from driver_info but deploy_ramdisk comes from configuration, + # since it's a sign of a potential operator's mistake. + d_info = {k: getattr(CONF.conductor, k.replace('ilo_', '')) + for k in params_to_check} + error_msg = (_("Error validating iLO virtual media for %s. Some " + "parameters were missing in node's driver_info.") % mode) + deploy_utils.check_for_missing_params(d_info, error_msg) -def _get_boot_iso_object_name(node): - """Returns the boot iso object name for a given node. + d_info.update( + {k: info.get(k, getattr(CONF.conductor, k.replace('ilo_', ''), None)) + for k in OPTIONAL_PROPERTIES}) - :param node: the node for which object name is to be provided. - """ - return "boot-%s" % node.uuid + return d_info def _get_boot_iso(task, root_uuid): """This method returns a boot ISO to boot the node. It chooses one of the three options in the order as below: - 1. Does nothing if 'ilo_boot_iso' is present in node's instance_info and - 'boot_iso_created_in_web_server' is not set in 'driver_internal_info'. + 1. Does nothing if 'ilo_boot_iso' is present in node's instance_info. 2. Image deployed has a meta-property 'boot_iso' in Glance. This should refer to the UUID of the boot_iso which exists in Glance. - 3. Generates a boot ISO on the fly using kernel and ramdisk mentioned in - the image deployed. It uploads the generated boot ISO to Swift. + 3. Returns a boot ISO created on the fly using kernel and ramdisk + mentioned in the image deployed. :param task: a TaskManager instance containing the node to act on. :param root_uuid: the uuid of the root partition. @@ -155,12 +160,7 @@ def _get_boot_iso(task, root_uuid): # Option 1 - Check if user has provided ilo_boot_iso in node's # instance_info - driver_internal_info = task.node.driver_internal_info - boot_iso_created_in_web_server = ( - driver_internal_info.get('boot_iso_created_in_web_server')) - - if (task.node.instance_info.get('ilo_boot_iso') - and not boot_iso_created_in_web_server): + if task.node.instance_info.get('ilo_boot_iso'): LOG.debug("Using ilo_boot_iso provided in node's instance_info") boot_iso = task.node.instance_info['ilo_boot_iso'] if not service_utils.is_glance_image(boot_iso): @@ -183,24 +183,14 @@ def _get_boot_iso(task, root_uuid): image_href = deploy_info['image_source'] image_properties = ( images.get_image_properties( - task.context, image_href, ['boot_iso', 'kernel_id', 'ramdisk_id'])) + task.context, image_href, ['boot_iso'])) boot_iso_uuid = image_properties.get('boot_iso') - kernel_href = (task.node.instance_info.get('kernel') - or image_properties.get('kernel_id')) - ramdisk_href = (task.node.instance_info.get('ramdisk') - or image_properties.get('ramdisk_id')) if boot_iso_uuid: LOG.debug("Found boot_iso %s in Glance", boot_iso_uuid) return boot_iso_uuid - if not kernel_href or not ramdisk_href: - LOG.error("Unable to find kernel or ramdisk for " - "image %(image)s to generate boot ISO for %(node)s", - {'image': image_href, 'node': task.node.uuid}) - return - # NOTE(rameshg87): Functionality to share the boot ISOs created for # similar instances (instances with same deployed image) is # not implemented as of now. Creation/Deletion of such a shared boot ISO @@ -209,70 +199,7 @@ def _get_boot_iso(task, root_uuid): # Option 3 - Create boot_iso from kernel/ramdisk, upload to Swift # or web server and provide its name. - deploy_iso_uuid = deploy_info['ilo_deploy_iso'] - boot_mode = boot_mode_utils.get_boot_mode(task.node) - boot_iso_object_name = _get_boot_iso_object_name(task.node) - kernel_params = "" - if deploy_utils.get_boot_option(task.node) == "ramdisk": - i_info = task.node.instance_info - kernel_params = "root=/dev/ram0 text " - kernel_params += i_info.get("ramdisk_kernel_arguments", "") - else: - kernel_params = CONF.pxe.pxe_append_params - with tempfile.NamedTemporaryFile(dir=CONF.tempdir) as fileobj: - boot_iso_tmp_file = fileobj.name - images.create_boot_iso(task.context, boot_iso_tmp_file, - kernel_href, ramdisk_href, - deploy_iso_href=deploy_iso_uuid, - root_uuid=root_uuid, - kernel_params=kernel_params, - boot_mode=boot_mode) - - if CONF.ilo.use_web_server_for_images: - boot_iso_url = ( - ilo_common.copy_image_to_web_server(boot_iso_tmp_file, - boot_iso_object_name)) - driver_internal_info = task.node.driver_internal_info - driver_internal_info['boot_iso_created_in_web_server'] = True - task.node.driver_internal_info = driver_internal_info - task.node.save() - LOG.debug("Created boot_iso %(boot_iso)s for node %(node)s", - {'boot_iso': boot_iso_url, 'node': task.node.uuid}) - return boot_iso_url - else: - container = CONF.ilo.swift_ilo_container - swift_api = swift.SwiftAPI() - swift_api.create_object(container, boot_iso_object_name, - boot_iso_tmp_file) - - LOG.debug("Created boot_iso %s in Swift", boot_iso_object_name) - return 'swift:%s' % boot_iso_object_name - - -def _clean_up_boot_iso_for_instance(node): - """Deletes the boot ISO if it was created for the instance. - - :param node: an ironic node object. - """ - ilo_boot_iso = node.instance_info.get('ilo_boot_iso') - if not ilo_boot_iso: - return - if ilo_boot_iso.startswith('swift'): - swift_api = swift.SwiftAPI() - container = CONF.ilo.swift_ilo_container - boot_iso_object_name = _get_boot_iso_object_name(node) - try: - swift_api.delete_object(container, boot_iso_object_name) - except exception.SwiftOperationError as e: - LOG.exception("Failed to clean up boot ISO for node " - "%(node)s. Error: %(error)s.", - {'node': node.uuid, 'error': e}) - elif CONF.ilo.use_web_server_for_images: - result = urlparse.urlparse(ilo_boot_iso) - ilo_boot_iso_name = os.path.basename(result.path) - boot_iso_path = os.path.join( - CONF.deploy.http_root, ilo_boot_iso_name) - ironic_utils.unlink_without_raise(boot_iso_path) + return image_utils.prepare_boot_iso(task, deploy_info, root_uuid) def _parse_deploy_info(node): @@ -308,19 +235,7 @@ def _validate_driver_info(task): """ node = task.node ilo_common.parse_driver_info(node) - if 'ilo_deploy_iso' not in node.driver_info: - raise exception.MissingParameterValue(_( - "Missing 'ilo_deploy_iso' parameter in node's 'driver_info'.")) - deploy_iso = node.driver_info['ilo_deploy_iso'] - if not service_utils.is_glance_image(deploy_iso): - try: - image_service.HttpImageService().validate_href(deploy_iso) - except exception.ImageRefValidationFailed: - raise exception.InvalidParameterValue(_( - "Virtual media boot accepts only Glance images or " - "HTTP(S) as driver_info['ilo_deploy_iso']. Either '%s' " - "is not a glance UUID or not a valid HTTP(S) URL or " - "the given URL is not reachable.") % deploy_iso) + parse_driver_info(node) def _validate_instance_image_info(task): @@ -542,12 +457,19 @@ class IloVirtualMediaBoot(base.BootInterface): deploy_nic_mac = deploy_utils.get_single_nic_with_vif_port_id(task) ramdisk_params['BOOTIF'] = deploy_nic_mac - if node.provision_state == states.RESCUING: + if (node.driver_info.get('ilo_rescue_iso') + and node.provision_state == states.RESCUING): iso = node.driver_info['ilo_rescue_iso'] - else: + ilo_common.setup_vmedia(task, iso, ramdisk_params) + elif node.driver_info.get('ilo_deploy_iso'): iso = node.driver_info['ilo_deploy_iso'] - - ilo_common.setup_vmedia(task, iso, ramdisk_params) + ilo_common.setup_vmedia(task, iso, ramdisk_params) + else: + mode = deploy_utils.rescue_or_deploy_mode(node) + d_info = parse_driver_info(node, mode) + iso = image_utils.prepare_deploy_iso(task, ramdisk_params, + mode, d_info) + ilo_common.setup_vmedia(task, iso) @METRICS.timer('IloVirtualMediaBoot.prepare_instance') def prepare_instance(self, task): @@ -635,19 +557,18 @@ class IloVirtualMediaBoot(base.BootInterface): LOG.debug("Cleaning up the instance.") manager_utils.node_power_action(task, states.POWER_OFF) disable_secure_boot_if_supported(task) - driver_internal_info = task.node.driver_internal_info if (deploy_utils.is_iscsi_boot(task) and task.node.driver_internal_info.get('ilo_uefi_iscsi_boot')): # It will clear iSCSI info from iLO task.driver.management.clear_iscsi_boot_target(task) + driver_internal_info = task.node.driver_internal_info driver_internal_info.pop('ilo_uefi_iscsi_boot', None) + task.node.driver_internal_info = driver_internal_info + task.node.save() else: - _clean_up_boot_iso_for_instance(task.node) - driver_internal_info.pop('boot_iso_created_in_web_server', None) + image_utils.cleanup_iso_image(task) ilo_common.cleanup_vmedia_boot(task) - task.node.driver_internal_info = driver_internal_info - task.node.save() @METRICS.timer('IloVirtualMediaBoot.clean_up_ramdisk') def clean_up_ramdisk(self, task): @@ -662,6 +583,12 @@ class IloVirtualMediaBoot(base.BootInterface): """ ilo_common.cleanup_vmedia_boot(task) + info = task.node.driver_info + mode = deploy_utils.rescue_or_deploy_mode(task.node) + if ((mode == 'rescue' and not info.get('ilo_rescue_iso')) + or (mode == 'deploy' and not info.get('ilo_deploy_iso'))): + image_utils.cleanup_iso_image(task) + def _configure_vmedia_boot(self, task, root_uuid): """Configure vmedia boot for the node. @@ -978,6 +905,18 @@ class IloUefiHttpsBoot(base.BootInterface): deploy_info = {option: info.get(option) for option in params_to_check} + if not any(deploy_info.values()): + # NOTE(dtantsur): avoid situation when e.g. deploy_kernel comes + # from driver_info but deploy_ramdisk comes from configuration, + # since it's a sign of a potential operator's mistake. + deploy_info = {k: getattr(CONF.conductor, k.replace('ilo_', '')) + for k in params_to_check} + + deploy_info.update( + {k: info.get(k, getattr(CONF.conductor, + k.replace('ilo_', ''), None)) + for k in OPTIONAL_PROPERTIES}) + self._validate_hrefs(deploy_info) error_msg = (_("Error validating %s for iLO UEFI HTTPS boot. Some " diff --git a/ironic/drivers/modules/ilo/common.py b/ironic/drivers/modules/ilo/common.py index 4ef8dc85e..d76d4a04a 100644 --- a/ironic/drivers/modules/ilo/common.py +++ b/ironic/drivers/modules/ilo/common.py @@ -645,7 +645,7 @@ def update_boot_mode(task): node.save() -def setup_vmedia(task, iso, ramdisk_options): +def setup_vmedia(task, iso, ramdisk_options=None): """Attaches virtual media and sets it as boot device. This method attaches the given bootable ISO as virtual media, prepares the diff --git a/ironic/drivers/modules/image_utils.py b/ironic/drivers/modules/image_utils.py index f341d6873..ce87adc93 100644 --- a/ironic/drivers/modules/image_utils.py +++ b/ironic/drivers/modules/image_utils.py @@ -43,14 +43,24 @@ class ImageHandler(object): "container": CONF.redfish.swift_container, "timeout": CONF.redfish.swift_object_expiry_timeout, "image_subdir": "redfish", - "file_permission": CONF.redfish.file_permission + "file_permission": CONF.redfish.file_permission, + "kernel_params": CONF.redfish.kernel_append_params }, "ilo5": { "swift_enabled": not CONF.ilo.use_web_server_for_images, "container": CONF.ilo.swift_ilo_container, "timeout": CONF.ilo.swift_object_expiry_timeout, "image_subdir": "ilo", - "file_permission": CONF.ilo.file_permission + "file_permission": CONF.ilo.file_permission, + "kernel_params": CONF.pxe.pxe_append_params + }, + "ilo": { + "swift_enabled": not CONF.ilo.use_web_server_for_images, + "container": CONF.ilo.swift_ilo_container, + "timeout": CONF.ilo.swift_object_expiry_timeout, + "image_subdir": "ilo", + "file_permission": CONF.ilo.file_permission, + "kernel_params": CONF.pxe.pxe_append_params }, } @@ -60,6 +70,8 @@ class ImageHandler(object): self._timeout = self._SWIFT_MAP[driver].get("timeout") self._image_subdir = self._SWIFT_MAP[driver].get("image_subdir") self._file_permission = self._SWIFT_MAP[driver].get("file_permission") + # To get the kernel parameters + self.kernel_params = self._SWIFT_MAP[driver].get("kernel_params") def _is_swift_enabled(self): try: @@ -303,6 +315,9 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href, "building ISO, or explicit ISO for %(node)s") % {'node': task.node.uuid}) + img_handler = ImageHandler(task.node.driver) + k_param = img_handler.kernel_params + i_info = task.node.instance_info # NOTE(TheJulia): Until we support modifying a base iso, most of @@ -315,8 +330,7 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href, kernel_params = None else: - kernel_params = i_info.get( - 'kernel_append_params', CONF.redfish.kernel_append_params) + kernel_params = i_info.get('kernel_append_params', k_param) if params and not base_iso: kernel_params = ' '.join( @@ -374,7 +388,6 @@ def _prepare_iso_image(task, kernel_href, ramdisk_href, iso_object_name = _get_iso_image_name(task.node) - img_handler = ImageHandler(task.node.driver) image_url = img_handler.publish_image( boot_iso_tmp_file, iso_object_name) diff --git a/ironic/tests/unit/drivers/modules/ilo/test_boot.py b/ironic/tests/unit/drivers/modules/ilo/test_boot.py index d681cb72c..0a435dde3 100644 --- a/ironic/tests/unit/drivers/modules/ilo/test_boot.py +++ b/ironic/tests/unit/drivers/modules/ilo/test_boot.py @@ -15,12 +15,9 @@ """Test class for boot methods used by iLO modules.""" -import io -import tempfile from unittest import mock from urllib import parse as urlparse -from ironic_lib import utils as ironic_utils from oslo_config import cfg from ironic.common import boot_devices @@ -29,7 +26,6 @@ from ironic.common.glance_service import service_utils from ironic.common import image_service from ironic.common import images from ironic.common import states -from ironic.common import swift from ironic.conductor import task_manager from ironic.conductor import utils as manager_utils from ironic.drivers.modules import boot_mode_utils @@ -56,9 +52,74 @@ class IloBootCommonMethodsTestCase(test_common.BaseIloTest): boot_interface = 'ilo-virtual-media' - def test_parse_driver_info(self): + def test_parse_driver_info_deploy_iso(self): self.node.driver_info['ilo_deploy_iso'] = 'deploy-iso' - expected_driver_info = {'ilo_deploy_iso': 'deploy-iso'} + expected_driver_info = {'ilo_bootloader': None, + 'ilo_deploy_iso': 'deploy-iso'} + + actual_driver_info = ilo_boot.parse_driver_info(self.node) + self.assertEqual(expected_driver_info, actual_driver_info) + + def test_parse_driver_info_rescue_iso(self): + self.node.driver_info['ilo_rescue_iso'] = 'rescue-iso' + expected_driver_info = {'ilo_bootloader': None, + 'ilo_rescue_iso': 'rescue-iso'} + + actual_driver_info = ilo_boot.parse_driver_info(self.node, 'rescue') + self.assertEqual(expected_driver_info, actual_driver_info) + + def test_parse_driver_info_deploy(self): + self.node.driver_info['ilo_deploy_kernel'] = 'kernel' + self.node.driver_info['ilo_deploy_ramdisk'] = 'ramdisk' + self.node.driver_info['ilo_bootloader'] = 'bootloader' + expected_driver_info = {'ilo_deploy_kernel': 'kernel', + 'ilo_deploy_ramdisk': 'ramdisk', + 'ilo_bootloader': 'bootloader'} + + actual_driver_info = ilo_boot.parse_driver_info(self.node) + self.assertEqual(expected_driver_info, actual_driver_info) + + def test_parse_driver_info_rescue(self): + self.node.driver_info['ilo_rescue_kernel'] = 'kernel' + self.node.driver_info['ilo_rescue_ramdisk'] = 'ramdisk' + self.node.driver_info['ilo_bootloader'] = 'bootloader' + expected_driver_info = {'ilo_rescue_kernel': 'kernel', + 'ilo_rescue_ramdisk': 'ramdisk', + 'ilo_bootloader': 'bootloader'} + + actual_driver_info = ilo_boot.parse_driver_info(self.node, 'rescue') + self.assertEqual(expected_driver_info, actual_driver_info) + + def test_parse_driver_info_deploy_config(self): + CONF.conductor.deploy_kernel = 'kernel' + CONF.conductor.deploy_ramdisk = 'ramdisk' + CONF.conductor.bootloader = 'bootloader' + expected_driver_info = {'ilo_deploy_kernel': 'kernel', + 'ilo_deploy_ramdisk': 'ramdisk', + 'ilo_bootloader': 'bootloader'} + + actual_driver_info = ilo_boot.parse_driver_info(self.node) + self.assertEqual(expected_driver_info, actual_driver_info) + + def test_parse_driver_info_rescue_config(self): + CONF.conductor.rescue_kernel = 'kernel' + CONF.conductor.rescue_ramdisk = 'ramdisk' + CONF.conductor.bootloader = 'bootloader' + + expected_driver_info = {'ilo_rescue_kernel': 'kernel', + 'ilo_rescue_ramdisk': 'ramdisk', + 'ilo_bootloader': 'bootloader'} + + actual_driver_info = ilo_boot.parse_driver_info(self.node, 'rescue') + self.assertEqual(expected_driver_info, actual_driver_info) + + def test_parse_driver_info_bootloader_none(self): + CONF.conductor.deploy_kernel = 'kernel' + CONF.conductor.deploy_ramdisk = 'ramdisk' + + expected_driver_info = {'ilo_deploy_kernel': 'kernel', + 'ilo_deploy_ramdisk': 'ramdisk', + 'ilo_bootloader': None} actual_driver_info = ilo_boot.parse_driver_info(self.node) self.assertEqual(expected_driver_info, actual_driver_info) @@ -72,11 +133,6 @@ class IloBootPrivateMethodsTestCase(test_common.BaseIloTest): boot_interface = 'ilo-virtual-media' - def test__get_boot_iso_object_name(self): - boot_iso_actual = ilo_boot._get_boot_iso_object_name(self.node) - boot_iso_expected = "boot-%s" % self.node.uuid - self.assertEqual(boot_iso_expected, boot_iso_actual) - @mock.patch.object(image_service.HttpImageService, 'validate_href', spec_set=True, autospec=True) def test__get_boot_iso_http_url(self, service_mock): @@ -116,294 +172,44 @@ class IloBootPrivateMethodsTestCase(test_common.BaseIloTest): image_props_mock): deploy_info_mock.return_value = {'image_source': 'image-uuid', 'ilo_deploy_iso': 'deploy_iso_uuid'} - image_props_mock.return_value = {'boot_iso': u'glance://uui\u0111', - 'kernel_id': None, - 'ramdisk_id': None} + image_props_mock.return_value = {'boot_iso': u'glance://uui\u0111'} with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: - driver_internal_info = task.node.driver_internal_info - driver_internal_info['boot_iso_created_in_web_server'] = False - task.node.driver_internal_info = driver_internal_info - task.node.save() boot_iso_actual = ilo_boot._get_boot_iso(task, 'root-uuid') deploy_info_mock.assert_called_once_with(task.node) image_props_mock.assert_called_once_with( - task.context, 'image-uuid', - ['boot_iso', 'kernel_id', 'ramdisk_id']) + task.context, 'image-uuid', ['boot_iso']) boot_iso_expected = u'glance://uui\u0111' self.assertEqual(boot_iso_expected, boot_iso_actual) - @mock.patch.object(boot_mode_utils, 'get_boot_mode_for_deploy', - spec_set=True, autospec=True) - @mock.patch.object(ilo_boot.LOG, 'error', spec_set=True, autospec=True) - @mock.patch.object(images, 'get_image_properties', spec_set=True, - autospec=True) - @mock.patch.object(ilo_boot, '_parse_deploy_info', spec_set=True, - autospec=True) - def test__get_boot_iso_uefi_no_glance_image(self, - deploy_info_mock, - image_props_mock, - log_mock, - boot_mode_mock): - deploy_info_mock.return_value = {'image_source': 'image-uuid', - 'ilo_deploy_iso': 'deploy_iso_uuid'} - image_props_mock.return_value = {'boot_iso': None, - 'kernel_id': None, - 'ramdisk_id': None} - properties = {'capabilities': 'boot_mode:uefi'} - - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - task.node.properties = properties - boot_iso_result = ilo_boot._get_boot_iso(task, 'root-uuid') - deploy_info_mock.assert_called_once_with(task.node) - image_props_mock.assert_called_once_with( - task.context, 'image-uuid', - ['boot_iso', 'kernel_id', 'ramdisk_id']) - self.assertTrue(log_mock.called) - self.assertFalse(boot_mode_mock.called) - self.assertIsNone(boot_iso_result) - - @mock.patch.object(tempfile, 'NamedTemporaryFile', spec_set=True, - autospec=True) - @mock.patch.object(images, 'create_boot_iso', spec_set=True, autospec=True) - @mock.patch.object(swift, 'SwiftAPI', spec_set=True, autospec=True) - @mock.patch.object(ilo_boot, '_get_boot_iso_object_name', spec_set=True, - autospec=True) - @mock.patch.object(driver_utils, 'get_node_capability', spec_set=True, + @mock.patch.object(image_utils, 'prepare_boot_iso', spec_set=True, autospec=True) @mock.patch.object(images, 'get_image_properties', spec_set=True, autospec=True) @mock.patch.object(ilo_boot, '_parse_deploy_info', spec_set=True, autospec=True) def test__get_boot_iso_create(self, deploy_info_mock, image_props_mock, - capability_mock, boot_object_name_mock, - swift_api_mock, - create_boot_iso_mock, tempfile_mock): - CONF.ilo.swift_ilo_container = 'ilo-cont' - CONF.pxe.pxe_append_params = 'kernel-params' - - swift_obj_mock = swift_api_mock.return_value - fileobj_mock = mock.MagicMock(spec=io.BytesIO) - fileobj_mock.name = 'tmpfile' - mock_file_handle = mock.MagicMock(spec=io.BytesIO) - mock_file_handle.__enter__.return_value = fileobj_mock - tempfile_mock.return_value = mock_file_handle + prepare_iso_mock): deploy_info_mock.return_value = {'image_source': 'image-uuid', 'ilo_deploy_iso': 'deploy_iso_uuid'} - image_props_mock.return_value = {'boot_iso': None, - 'kernel_id': 'kernel_uuid', - 'ramdisk_id': 'ramdisk_uuid'} - boot_object_name_mock.return_value = 'abcdef' - create_boot_iso_mock.return_value = '/path/to/boot-iso' - capability_mock.return_value = 'uefi' - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - boot_iso_actual = ilo_boot._get_boot_iso(task, 'root-uuid') - deploy_info_mock.assert_called_once_with(task.node) - image_props_mock.assert_called_once_with( - task.context, 'image-uuid', - ['boot_iso', 'kernel_id', 'ramdisk_id']) - boot_object_name_mock.assert_called_once_with(task.node) - create_boot_iso_mock.assert_called_once_with( - task.context, 'tmpfile', 'kernel_uuid', 'ramdisk_uuid', - deploy_iso_href='deploy_iso_uuid', - root_uuid='root-uuid', - kernel_params='kernel-params', - boot_mode='uefi') - swift_obj_mock.create_object.assert_called_once_with('ilo-cont', - 'abcdef', - 'tmpfile') - boot_iso_expected = 'swift:abcdef' - self.assertEqual(boot_iso_expected, boot_iso_actual) - - @mock.patch.object(ilo_common, 'copy_image_to_web_server', spec_set=True, - autospec=True) - @mock.patch.object(tempfile, 'NamedTemporaryFile', spec_set=True, - autospec=True) - @mock.patch.object(images, 'create_boot_iso', spec_set=True, autospec=True) - @mock.patch.object(ilo_boot, '_get_boot_iso_object_name', spec_set=True, - autospec=True) - @mock.patch.object(driver_utils, 'get_node_capability', spec_set=True, - autospec=True) - @mock.patch.object(images, 'get_image_properties', spec_set=True, - autospec=True) - @mock.patch.object(ilo_boot, '_parse_deploy_info', spec_set=True, - autospec=True) - def test__get_boot_iso_recreate_boot_iso_use_webserver( - self, deploy_info_mock, image_props_mock, - capability_mock, boot_object_name_mock, - create_boot_iso_mock, tempfile_mock, - copy_file_mock): - CONF.ilo.swift_ilo_container = 'ilo-cont' - CONF.ilo.use_web_server_for_images = True - CONF.deploy.http_url = "http://10.10.1.30/httpboot" - CONF.deploy.http_root = "/httpboot" - CONF.pxe.pxe_append_params = 'kernel-params' - - fileobj_mock = mock.MagicMock(spec=io.BytesIO) - fileobj_mock.name = 'tmpfile' - mock_file_handle = mock.MagicMock(spec=io.BytesIO) - mock_file_handle.__enter__.return_value = fileobj_mock - tempfile_mock.return_value = mock_file_handle - - ramdisk_href = "http://10.10.1.30/httpboot/ramdisk" - kernel_href = "http://10.10.1.30/httpboot/kernel" - deploy_info_mock.return_value = {'image_source': 'image-uuid', - 'ilo_deploy_iso': 'deploy_iso_uuid'} - image_props_mock.return_value = {'boot_iso': None, - 'kernel_id': kernel_href, - 'ramdisk_id': ramdisk_href} - boot_object_name_mock.return_value = 'new_boot_iso' - create_boot_iso_mock.return_value = '/path/to/boot-iso' - capability_mock.return_value = 'uefi' - copy_file_mock.return_value = "http://10.10.1.30/httpboot/new_boot_iso" - - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - driver_internal_info = task.node.driver_internal_info - driver_internal_info['boot_iso_created_in_web_server'] = True - instance_info = task.node.instance_info - old_boot_iso = 'http://10.10.1.30/httpboot/old_boot_iso' - instance_info['ilo_boot_iso'] = old_boot_iso - boot_iso_actual = ilo_boot._get_boot_iso(task, 'root-uuid') - deploy_info_mock.assert_called_once_with(task.node) - image_props_mock.assert_called_once_with( - task.context, 'image-uuid', - ['boot_iso', 'kernel_id', 'ramdisk_id']) - boot_object_name_mock.assert_called_once_with(task.node) - create_boot_iso_mock.assert_called_once_with( - task.context, 'tmpfile', kernel_href, ramdisk_href, - deploy_iso_href='deploy_iso_uuid', - root_uuid='root-uuid', - kernel_params='kernel-params', - boot_mode='uefi') - boot_iso_expected = 'http://10.10.1.30/httpboot/new_boot_iso' - self.assertEqual(boot_iso_expected, boot_iso_actual) - copy_file_mock.assert_called_once_with(fileobj_mock.name, - 'new_boot_iso') + image_props_mock.return_value = {'boot_iso': None} - @mock.patch.object(ilo_common, 'copy_image_to_web_server', spec_set=True, - autospec=True) - @mock.patch.object(tempfile, 'NamedTemporaryFile', spec_set=True, - autospec=True) - @mock.patch.object(images, 'create_boot_iso', spec_set=True, autospec=True) - @mock.patch.object(ilo_boot, '_get_boot_iso_object_name', spec_set=True, - autospec=True) - @mock.patch.object(driver_utils, 'get_node_capability', spec_set=True, - autospec=True) - @mock.patch.object(images, 'get_image_properties', spec_set=True, - autospec=True) - @mock.patch.object(ilo_boot, '_parse_deploy_info', spec_set=True, - autospec=True) - def test__get_boot_iso_create_use_webserver_true_ramdisk_webserver( - self, deploy_info_mock, image_props_mock, - capability_mock, boot_object_name_mock, - create_boot_iso_mock, tempfile_mock, - copy_file_mock): - CONF.ilo.swift_ilo_container = 'ilo-cont' - CONF.ilo.use_web_server_for_images = True - CONF.deploy.http_url = "http://10.10.1.30/httpboot" - CONF.deploy.http_root = "/httpboot" - CONF.pxe.pxe_append_params = 'kernel-params' - - fileobj_mock = mock.MagicMock(spec=io.BytesIO) - fileobj_mock.name = 'tmpfile' - mock_file_handle = mock.MagicMock(spec=io.BytesIO) - mock_file_handle.__enter__.return_value = fileobj_mock - tempfile_mock.return_value = mock_file_handle - - ramdisk_href = "http://10.10.1.30/httpboot/ramdisk" - kernel_href = "http://10.10.1.30/httpboot/kernel" - deploy_info_mock.return_value = {'image_source': 'image-uuid', - 'ilo_deploy_iso': 'deploy_iso_uuid'} - image_props_mock.return_value = {'boot_iso': None, - 'kernel_id': kernel_href, - 'ramdisk_id': ramdisk_href} - boot_object_name_mock.return_value = 'abcdef' - create_boot_iso_mock.return_value = '/path/to/boot-iso' - capability_mock.return_value = 'uefi' - copy_file_mock.return_value = "http://10.10.1.30/httpboot/abcdef" + prepare_iso_mock.return_value = 'swift:boot-iso' + d_info = {'image_source': 'image-uuid', + 'ilo_deploy_iso': 'deploy_iso_uuid'} with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: boot_iso_actual = ilo_boot._get_boot_iso(task, 'root-uuid') deploy_info_mock.assert_called_once_with(task.node) image_props_mock.assert_called_once_with( - task.context, 'image-uuid', - ['boot_iso', 'kernel_id', 'ramdisk_id']) - boot_object_name_mock.assert_called_once_with(task.node) - create_boot_iso_mock.assert_called_once_with( - task.context, 'tmpfile', kernel_href, ramdisk_href, - deploy_iso_href='deploy_iso_uuid', - root_uuid='root-uuid', - kernel_params='kernel-params', - boot_mode='uefi') - boot_iso_expected = 'http://10.10.1.30/httpboot/abcdef' + task.context, 'image-uuid', ['boot_iso']) + prepare_iso_mock.assert_called_once_with( + task, d_info, 'root-uuid') + boot_iso_expected = 'swift:boot-iso' self.assertEqual(boot_iso_expected, boot_iso_actual) - copy_file_mock.assert_called_once_with(fileobj_mock.name, - 'abcdef') - - @mock.patch.object(ilo_boot, '_get_boot_iso_object_name', spec_set=True, - autospec=True) - @mock.patch.object(swift, 'SwiftAPI', spec_set=True, autospec=True) - def test__clean_up_boot_iso_for_instance(self, swift_mock, - boot_object_name_mock): - swift_obj_mock = swift_mock.return_value - CONF.ilo.swift_ilo_container = 'ilo-cont' - boot_object_name_mock.return_value = 'boot-object' - i_info = self.node.instance_info - i_info['ilo_boot_iso'] = 'swift:bootiso' - self.node.instance_info = i_info - self.node.save() - ilo_boot._clean_up_boot_iso_for_instance(self.node) - swift_obj_mock.delete_object.assert_called_once_with('ilo-cont', - 'boot-object') - - @mock.patch.object(ilo_boot.LOG, 'exception', spec_set=True, - autospec=True) - @mock.patch.object(ilo_boot, '_get_boot_iso_object_name', spec_set=True, - autospec=True) - @mock.patch.object(swift, 'SwiftAPI', spec_set=True, autospec=True) - def test__clean_up_boot_iso_for_instance_exc(self, swift_mock, - boot_object_name_mock, - log_mock): - swift_obj_mock = swift_mock.return_value - exc = exception.SwiftObjectNotFoundError('error') - swift_obj_mock.delete_object.side_effect = exc - CONF.ilo.swift_ilo_container = 'ilo-cont' - boot_object_name_mock.return_value = 'boot-object' - i_info = self.node.instance_info - i_info['ilo_boot_iso'] = 'swift:bootiso' - self.node.instance_info = i_info - self.node.save() - ilo_boot._clean_up_boot_iso_for_instance(self.node) - swift_obj_mock.delete_object.assert_called_once_with('ilo-cont', - 'boot-object') - self.assertTrue(log_mock.called) - - @mock.patch.object(ironic_utils, 'unlink_without_raise', spec_set=True, - autospec=True) - def test__clean_up_boot_iso_for_instance_on_webserver(self, unlink_mock): - - CONF.ilo.use_web_server_for_images = True - CONF.deploy.http_root = "/webserver" - i_info = self.node.instance_info - i_info['ilo_boot_iso'] = 'http://x.y.z.a/webserver/boot-object' - self.node.instance_info = i_info - self.node.save() - boot_iso_path = "/webserver/boot-object" - ilo_boot._clean_up_boot_iso_for_instance(self.node) - unlink_mock.assert_called_once_with(boot_iso_path) - - @mock.patch.object(ilo_boot, '_get_boot_iso_object_name', spec_set=True, - autospec=True) - def test__clean_up_boot_iso_for_instance_no_boot_iso( - self, boot_object_name_mock): - ilo_boot._clean_up_boot_iso_for_instance(self.node) - self.assertFalse(boot_object_name_mock.called) @mock.patch.object(ilo_boot, 'parse_driver_info', spec_set=True, autospec=True) @@ -418,68 +224,15 @@ class IloBootPrivateMethodsTestCase(test_common.BaseIloTest): @mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True, autospec=True) - def test__validate_driver_info_MissingParam(self, mock_parse_driver_info): - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - self.assertRaisesRegex(exception.MissingParameterValue, - "Missing 'ilo_deploy_iso'", - ilo_boot._validate_driver_info, task) - mock_parse_driver_info.assert_called_once_with(task.node) - - @mock.patch.object(service_utils, 'is_glance_image', spec_set=True, - autospec=True) - @mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True, - autospec=True) - def test__validate_driver_info_valid_uuid(self, mock_parse_driver_info, - mock_is_glance_image): - mock_is_glance_image.return_value = True - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - deploy_iso = '8a81759a-f29b-454b-8ab3-161c6ca1882c' - task.node.driver_info['ilo_deploy_iso'] = deploy_iso - ilo_boot._validate_driver_info(task) - mock_parse_driver_info.assert_called_once_with(task.node) - mock_is_glance_image.assert_called_once_with(deploy_iso) - - @mock.patch.object(image_service.HttpImageService, 'validate_href', - spec_set=True, autospec=True) - @mock.patch.object(service_utils, 'is_glance_image', spec_set=True, - autospec=True) - @mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True, - autospec=True) - def test__validate_driver_info_InvalidParam(self, mock_parse_driver_info, - mock_is_glance_image, - mock_validate_href): - deploy_iso = 'http://abc.org/image/qcow2' - mock_validate_href.side_effect = exception.ImageRefValidationFailed( - image_href='http://abc.org/image/qcow2', reason='fail') - mock_is_glance_image.return_value = False - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: - task.node.driver_info['ilo_deploy_iso'] = deploy_iso - self.assertRaisesRegex(exception.InvalidParameterValue, - "Virtual media boot accepts", - ilo_boot._validate_driver_info, task) - mock_parse_driver_info.assert_called_once_with(task.node) - mock_validate_href.assert_called_once_with(mock.ANY, deploy_iso) - - @mock.patch.object(image_service.HttpImageService, 'validate_href', - spec_set=True, autospec=True) - @mock.patch.object(service_utils, 'is_glance_image', spec_set=True, - autospec=True) - @mock.patch.object(ilo_common, 'parse_driver_info', spec_set=True, + @mock.patch.object(ilo_boot, 'parse_driver_info', spec_set=True, autospec=True) - def test__validate_driver_info_valid_url(self, mock_parse_driver_info, - mock_is_glance_image, - mock_validate_href): - deploy_iso = 'http://abc.org/image/deploy.iso' - mock_is_glance_image.return_value = False + def test__validate_driver_info(self, mock_driver_info, + mock_parse_driver_info): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: - task.node.driver_info['ilo_deploy_iso'] = deploy_iso ilo_boot._validate_driver_info(task) mock_parse_driver_info.assert_called_once_with(task.node) - mock_validate_href.assert_called_once_with(mock.ANY, deploy_iso) + mock_driver_info.assert_called_once_with(task.node) @mock.patch.object(deploy_utils, 'validate_image_properties', spec_set=True, autospec=True) @@ -907,6 +660,48 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest): self.assertEqual('http://mybootiso', self.node.instance_info['ilo_boot_iso']) + @mock.patch.object(ilo_boot, 'prepare_node_for_deploy', + spec_set=True, autospec=True) + @mock.patch.object(ilo_common, 'eject_vmedia_devices', + spec_set=True, autospec=True) + @mock.patch.object(ilo_common, 'setup_vmedia', spec_set=True, + autospec=True) + @mock.patch.object(deploy_utils, 'get_single_nic_with_vif_port_id', + spec_set=True, autospec=True) + @mock.patch.object(deploy_utils, 'rescue_or_deploy_mode', + spec_set=True, autospec=True) + @mock.patch.object(ilo_boot, 'parse_driver_info', spec_set=True, + autospec=True) + @mock.patch.object(image_utils, 'prepare_deploy_iso', + spec_set=True, autospec=True) + def test_prepare_ramdisk_not_iso( + self, prepare_deploy_iso_mock, driver_info_mock, + mode_mock, get_nic_mock, setup_vmedia_mock, + eject_mock, prepare_node_for_deploy_mock): + self.node.provision_state = states.DEPLOYING + self.node.save() + mode = 'deploy' + ramdisk_params = {'a': 'b'} + d_info = { + 'ilo_deploy_kernel': 'kernel', + 'ilo_deploy_ramdisk': 'ramdisk', + 'ilo_bootloader': 'bootloader' + } + driver_info_mock.return_value = d_info + prepare_deploy_iso_mock.return_value = 'recreated-iso' + + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + mode_mock.return_value = 'deploy' + get_nic_mock.return_value = '12:34:56:78:90:ab' + task.driver.boot.prepare_ramdisk(task, ramdisk_params) + prepare_node_for_deploy_mock.assert_called_once_with(task) + eject_mock.assert_called_once_with(task) + driver_info_mock.assert_called_once_with(task.node, mode) + prepare_deploy_iso_mock.assert_called_once_with( + task, ramdisk_params, mode, d_info) + setup_vmedia_mock.assert_called_once_with(task, 'recreated-iso') + @mock.patch.object(manager_utils, 'node_set_boot_device', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'setup_vmedia_for_boot', spec_set=True, @@ -963,8 +758,8 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest): autospec=True) @mock.patch.object(ilo_common, 'cleanup_vmedia_boot', spec_set=True, autospec=True) - @mock.patch.object(ilo_boot, '_clean_up_boot_iso_for_instance', - spec_set=True, autospec=True) + @mock.patch.object(image_utils, 'cleanup_iso_image', spec_set=True, + autospec=True) def _test_clean_up_instance(self, cleanup_iso_mock, cleanup_vmedia_mock, node_power_mock, update_secure_boot_mode_mock, @@ -972,16 +767,13 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: driver_internal_info = task.node.driver_internal_info - driver_internal_info['boot_iso_created_in_web_server'] = False task.node.driver_internal_info = driver_internal_info task.node.save() is_iscsi_boot_mock.return_value = False task.driver.boot.clean_up_instance(task) - cleanup_iso_mock.assert_called_once_with(task.node) + cleanup_iso_mock.assert_called_once_with(task) cleanup_vmedia_mock.assert_called_once_with(task) driver_internal_info = task.node.driver_internal_info - self.assertNotIn('boot_iso_created_in_web_server', - driver_internal_info) node_power_mock.assert_called_once_with(task, states.POWER_OFF) update_secure_boot_mode_mock.assert_called_once_with(task, False) @@ -1024,8 +816,8 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest): @mock.patch.object(ilo_common, 'cleanup_vmedia_boot', spec_set=True, autospec=True) - @mock.patch.object(ilo_boot, '_clean_up_boot_iso_for_instance', - spec_set=True, autospec=True) + @mock.patch.object(image_utils, 'cleanup_iso_image', spec_set=True, + autospec=True) @mock.patch.object(deploy_utils, 'is_iscsi_boot', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'update_secure_boot_mode', spec_set=True, @@ -1039,22 +831,27 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest): shared=False) as task: is_iscsi_boot_mock.return_value = False task.driver.boot.clean_up_instance(task) - cleanup_iso_mock.assert_called_once_with(task.node) + cleanup_iso_mock.assert_called_once_with(task) cleanup_vmedia_mock.assert_called_once_with(task) - driver_internal_info = task.node.driver_internal_info - self.assertNotIn('boot_iso_created_in_web_server', - driver_internal_info) node_power_mock.assert_called_once_with(task, states.POWER_OFF) update_secure_boot_mode_mock.assert_called_once_with(task, False) @mock.patch.object(ilo_common, 'cleanup_vmedia_boot', spec_set=True, autospec=True) - def test_clean_up_ramdisk(self, cleanup_vmedia_mock): + @mock.patch.object(deploy_utils, 'rescue_or_deploy_mode', + spec_set=True, autospec=True) + @mock.patch.object(image_utils, 'cleanup_iso_image', spec_set=True, + autospec=True) + def test_clean_up_ramdisk(self, cleanup_iso_mock, mode_mock, + cleanup_vmedia_mock): + mode_mock.return_value = 'deploy' with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.boot.clean_up_ramdisk(task) cleanup_vmedia_mock.assert_called_once_with(task) + mode_mock.assert_called_once_with(task.node) + cleanup_iso_mock.assert_called_once_with(task) @mock.patch.object(deploy_utils, 'is_iscsi_boot', spec_set=True, autospec=True) @@ -1234,7 +1031,7 @@ class IloVirtualMediaBootTestCase(test_common.BaseIloTest): def test_validate_rescue_no_rescue_ramdisk(self): with task_manager.acquire(self.context, self.node.uuid) as task: self.assertRaisesRegex(exception.MissingParameterValue, - 'Missing.*ilo_rescue_iso', + 'Some parameters were missing*', task.driver.boot.validate_rescue, task) diff --git a/ironic/tests/unit/drivers/modules/ilo/test_common.py b/ironic/tests/unit/drivers/modules/ilo/test_common.py index 2877e6195..c8adbf93f 100644 --- a/ironic/tests/unit/drivers/modules/ilo/test_common.py +++ b/ironic/tests/unit/drivers/modules/ilo/test_common.py @@ -1079,6 +1079,21 @@ class IloCommonMethodsTestCase(BaseIloTest): func_set_boot_device.assert_called_once_with(task, boot_devices.CDROM) + @mock.patch.object(manager_utils, 'node_set_boot_device', spec_set=True, + autospec=True) + @mock.patch.object(ilo_common, 'setup_vmedia_for_boot', spec_set=True, + autospec=True) + def test_setup_vmedia_without_params(self, + func_setup_vmedia_for_boot, + func_set_boot_device): + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + iso = '733d1c44-a2ea-414b-aca7-69decf20d810' + ilo_common.setup_vmedia(task, iso) + func_setup_vmedia_for_boot.assert_called_once_with(task, iso, None) + func_set_boot_device.assert_called_once_with(task, + boot_devices.CDROM) + @mock.patch.object(deploy_utils, 'is_secure_boot_requested', spec_set=True, autospec=True) @mock.patch.object(ilo_common, 'set_secure_boot_mode', spec_set=True, |