def _prepare_boot_iso(task, root_uuid): """Prepare a boot ISO to boot the node. :param task: a TaskManager instance containing the node to act on. :param root_uuid: the uuid of the root partition. :raises: MissingParameterValue, if any of the required parameters are missing. :raises: InvalidParameterValue, if any of the parameters have invalid value. :raises: ImageCreationFailed, if creating boot ISO for BIOS boot_mode failed. """ deploy_info = _parse_deploy_info(task.node) driver_internal_info = task.node.driver_internal_info # fetch boot iso if deploy_info.get('irmc_boot_iso'): boot_iso_href = deploy_info['irmc_boot_iso'] if _is_image_href_ordinary_file_name(boot_iso_href): driver_internal_info['irmc_boot_iso'] = boot_iso_href else: boot_iso_filename = _get_iso_name(task.node, label='boot') boot_iso_fullpathname = os.path.join( CONF.irmc.remote_image_share_root, boot_iso_filename) images.fetch(task.context, boot_iso_href, boot_iso_fullpathname) driver_internal_info['irmc_boot_iso'] = boot_iso_filename # create boot iso else: image_href = deploy_info['image_source'] image_props = ['kernel_id', 'ramdisk_id'] image_properties = images.get_image_properties( task.context, image_href, image_props) kernel_href = (task.node.instance_info.get('kernel') or image_properties['kernel_id']) ramdisk_href = (task.node.instance_info.get('ramdisk') or image_properties['ramdisk_id']) deploy_iso_href = deploy_info['irmc_deploy_iso'] boot_mode = boot_mode_utils.get_boot_mode(task.node) kernel_params = CONF.pxe.pxe_append_params boot_iso_filename = _get_iso_name(task.node, label='boot') boot_iso_fullpathname = os.path.join( CONF.irmc.remote_image_share_root, boot_iso_filename) images.create_boot_iso(task.context, boot_iso_fullpathname, kernel_href, ramdisk_href, deploy_iso_href=deploy_iso_href, root_uuid=root_uuid, kernel_params=kernel_params, boot_mode=boot_mode) driver_internal_info['irmc_boot_iso'] = boot_iso_filename # save driver_internal_info['irmc_boot_iso'] task.node.driver_internal_info = driver_internal_info task.node.save()
def _prepare_boot_iso(task, root_uuid): """Prepare a boot ISO to boot the node. :param task: a TaskManager instance containing the node to act on. :param root_uuid: the uuid of the root partition. :raises: MissingParameterValue, if any of the required parameters are missing. :raises: InvalidParameterValue, if any of the parameters have invalid value. :raises: ImageCreationFailed, if creating boot ISO for BIOS boot_mode failed. """ deploy_info = _parse_deploy_info(task.node) driver_internal_info = task.node.driver_internal_info # fetch boot iso if deploy_info.get('irmc_boot_iso'): boot_iso_href = deploy_info['irmc_boot_iso'] if service_utils.is_image_href_ordinary_file_name(boot_iso_href): driver_internal_info['irmc_boot_iso'] = boot_iso_href else: boot_iso_filename = _get_boot_iso_name(task.node) boot_iso_fullpathname = os.path.join( CONF.irmc.remote_image_share_root, boot_iso_filename) images.fetch(task.context, boot_iso_href, boot_iso_fullpathname) driver_internal_info['irmc_boot_iso'] = boot_iso_filename # create boot iso else: image_href = deploy_info['image_source'] image_props = ['kernel_id', 'ramdisk_id'] image_properties = images.get_image_properties( task.context, image_href, image_props) kernel_href = (task.node.instance_info.get('kernel') or image_properties['kernel_id']) ramdisk_href = (task.node.instance_info.get('ramdisk') or image_properties['ramdisk_id']) deploy_iso_filename = _get_deploy_iso_name(task.node) deploy_iso = ('file://' + os.path.join( CONF.irmc.remote_image_share_root, deploy_iso_filename)) boot_mode = deploy_utils.get_boot_mode_for_deploy(task.node) kernel_params = CONF.pxe.pxe_append_params boot_iso_filename = _get_boot_iso_name(task.node) boot_iso_fullpathname = os.path.join( CONF.irmc.remote_image_share_root, boot_iso_filename) images.create_boot_iso(task.context, boot_iso_fullpathname, kernel_href, ramdisk_href, deploy_iso, root_uuid, kernel_params, boot_mode) driver_internal_info['irmc_boot_iso'] = boot_iso_filename # save driver_internal_info['irmc_boot_iso'] task.node.driver_internal_info = driver_internal_info task.node.save()
def prepare_boot_iso(task, d_info, root_uuid=None): """Prepare boot ISO image Build bootable ISO out of `[instance_info]/kernel`, `[instance_info]/ramdisk` and `[driver_info]/bootloader` if present. Otherwise, read `kernel_id` and `ramdisk_id` from `[instance_info]/image_source` Glance image metadata. Push produced ISO image up to Glance and return temporary Swift URL to the image. :param task: a TaskManager instance containing the node to act on. :param d_info: Deployment information of the node :param root_uuid: Root UUID :returns: bootable ISO HTTP URL. :raises: MissingParameterValue, if any of the required parameters are missing. :raises: InvalidParameterValue, if any of the parameters have invalid value. :raises: ImageCreationFailed, if creating ISO image failed. """ node = task.node kernel_href = node.instance_info.get('kernel') ramdisk_href = node.instance_info.get('ramdisk') base_iso = node.instance_info.get('boot_iso') if (not kernel_href or not ramdisk_href) and not base_iso: image_href = d_info['image_source'] image_properties = (images.get_image_properties( task.context, image_href, ['kernel_id', 'ramdisk_id'])) if not kernel_href: kernel_href = image_properties.get('kernel_id') if not ramdisk_href: ramdisk_href = image_properties.get('ramdisk_id') if (not kernel_href or not ramdisk_href): raise exception.InvalidParameterValue( _("Unable to find kernel or ramdisk for " "to generate boot ISO for %(node)s") % {'node': task.node.uuid}) bootloader_str = 'bootloader' bootloader_href = _find_param(bootloader_str, d_info) return _prepare_iso_image(task, kernel_href, ramdisk_href, bootloader_href, root_uuid=root_uuid, base_iso=base_iso)
def test_get_glance_image_properties_default_all(self, image_service_mock): prop_dict = {'properties': {'p1': 'v1', 'p2': 'v2'}} image_service_obj_mock = image_service_mock.return_value image_service_obj_mock.show.return_value = prop_dict ret_val = images.get_image_properties('con', 'uuid') image_service_mock.assert_called_once_with('uuid', context='con') image_service_obj_mock.show.assert_called_once_with('uuid') self.assertEqual({'p1': 'v1', 'p2': 'v2'}, ret_val)
def test_get_glance_image_properties_with_prop_subset(self, image_service_mock): prop_dict = {"properties": {"p1": "v1", "p2": "v2", "p3": "v3"}} image_service_obj_mock = image_service_mock.return_value image_service_obj_mock.show.return_value = prop_dict ret_val = images.get_image_properties("con", "uuid", ["p1", "p3"]) image_service_mock.assert_called_once_with("uuid", context="con") image_service_obj_mock.show.assert_called_once_with("uuid") self.assertEqual({"p1": "v1", "p3": "v3"}, ret_val)
def test_get_glance_image_properties_default_all( self, image_service_mock): prop_dict = {'properties': {'p1': 'v1', 'p2': 'v2'}} image_service_obj_mock = image_service_mock.return_value image_service_obj_mock.show.return_value = prop_dict ret_val = images.get_image_properties('con', 'uuid') image_service_mock.assert_called_once_with('uuid', context='con') image_service_obj_mock.show.assert_called_once_with('uuid') self.assertEqual({'p1': 'v1', 'p2': 'v2'}, ret_val)
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'. 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. :param task: a TaskManager instance containing the node to act on. :param root_uuid: the uuid of the root partition. :returns: boot ISO URL. Should be either of below: * A Swift object - It should be of format 'swift:<object-name>'. It is assumed that the image object is present in CONF.ilo.swift_ilo_container; * A Glance image - It should be format 'glance://<glance-image-uuid>' or just <glance-image-uuid>; * An HTTP URL. On error finding the boot iso, it returns None. :raises: MissingParameterValue, if any of the required parameters are missing in the node's driver_info or instance_info. :raises: InvalidParameterValue, if any of the parameters have invalid value in the node's driver_info or instance_info. :raises: SwiftOperationError, if operation with Swift fails. :raises: ImageCreationFailed, if creation of boot ISO failed. :raises: exception.ImageRefValidationFailed if ilo_boot_iso is not HTTP(S) URL. """ LOG.debug("Trying to get a boot ISO to boot the baremetal node") # 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): 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): try: image_service.HttpImageService().validate_href(boot_iso) except exception.ImageRefValidationFailed: with excutils.save_and_reraise_exception(): LOG.error("Virtual media deploy accepts only Glance " "images or HTTP(S) URLs as " "instance_info['ilo_boot_iso']. Either %s " "is not a valid HTTP(S) URL or is " "not reachable.", boot_iso) return task.node.instance_info['ilo_boot_iso'] # Option 2 - Check if user has provided a boot_iso in Glance. If boot_iso # is a supported non-glance href execution will proceed to option 3. deploy_info = _parse_deploy_info(task.node) image_href = deploy_info['image_source'] image_properties = ( images.get_image_properties( task.context, image_href, ['boot_iso', 'kernel_id', 'ramdisk_id'])) 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 # will require synchronisation across conductor nodes for the shared boot # ISO. Such a synchronisation mechanism doesn't exist in ironic as of now. # 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_for_deploy(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_uuid, root_uuid, kernel_params, 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 _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'. 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. :param task: a TaskManager instance containing the node to act on. :param root_uuid: the uuid of the root partition. :returns: boot ISO URL. Should be either of below: * A Swift object - It should be of format 'swift:<object-name>'. It is assumed that the image object is present in CONF.ilo.swift_ilo_container; * A Glance image - It should be format 'glance://<glance-image-uuid>' or just <glance-image-uuid>; * An HTTP URL. On error finding the boot iso, it returns None. :raises: MissingParameterValue, if any of the required parameters are missing in the node's driver_info or instance_info. :raises: InvalidParameterValue, if any of the parameters have invalid value in the node's driver_info or instance_info. :raises: SwiftOperationError, if operation with Swift fails. :raises: ImageCreationFailed, if creation of boot ISO failed. :raises: exception.ImageRefValidationFailed if ilo_boot_iso is not HTTP(S) URL. """ LOG.debug("Trying to get a boot ISO to boot the baremetal node") # 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): 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): try: image_service.HttpImageService().validate_href(boot_iso) except exception.ImageRefValidationFailed: with excutils.save_and_reraise_exception(): LOG.error( "Virtual media deploy accepts only Glance " "images or HTTP(S) URLs as " "instance_info['ilo_boot_iso']. Either %s " "is not a valid HTTP(S) URL or is " "not reachable.", boot_iso) return task.node.instance_info['ilo_boot_iso'] # Option 2 - Check if user has provided a boot_iso in Glance. If boot_iso # is a supported non-glance href execution will proceed to option 3. deploy_info = _parse_deploy_info(task.node) image_href = deploy_info['image_source'] image_properties = (images.get_image_properties( task.context, image_href, ['boot_iso', 'kernel_id', 'ramdisk_id'])) 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 # 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 # will require synchronisation across conductor nodes for the shared boot # ISO. Such a synchronisation mechanism doesn't exist in ironic as of now. # 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'] use_web_server = CONF.ilo.use_web_server_for_images container = CONF.ilo.swift_ilo_container return virtual_media_base.prepare_iso_image( task, kernel_href, ramdisk_href, deploy_iso_href=deploy_iso_uuid, root_uuid=root_uuid, use_web_server=use_web_server, container=container)
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'. 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. :param task: a TaskManager instance containing the node to act on. :param root_uuid: the uuid of the root partition. :returns: boot ISO URL. Should be either of below: * A Swift object - It should be of format 'swift:<object-name>'. It is assumed that the image object is present in CONF.ilo.swift_ilo_container; * A Glance image - It should be format 'glance://<glance-image-uuid>' or just <glance-image-uuid>; * An HTTP URL. On error finding the boot iso, it returns None. :raises: MissingParameterValue, if any of the required parameters are missing in the node's driver_info or instance_info. :raises: InvalidParameterValue, if any of the parameters have invalid value in the node's driver_info or instance_info. :raises: SwiftOperationError, if operation with Swift fails. :raises: ImageCreationFailed, if creation of boot ISO failed. :raises: exception.ImageRefValidationFailed if ilo_boot_iso is not HTTP(S) URL. """ LOG.debug("Trying to get a boot ISO to boot the baremetal node") # 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): 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): try: image_service.HttpImageService().validate_href(boot_iso) except exception.ImageRefValidationFailed: with excutils.save_and_reraise_exception(): LOG.error("Virtual media deploy accepts only Glance " "images or HTTP(S) URLs as " "instance_info['ilo_boot_iso']. Either %s " "is not a valid HTTP(S) URL or is " "not reachable.", boot_iso) return task.node.instance_info['ilo_boot_iso'] # Option 2 - Check if user has provided a boot_iso in Glance. If boot_iso # is a supported non-glance href execution will proceed to option 3. deploy_info = _parse_deploy_info(task.node) image_href = deploy_info['image_source'] image_properties = ( images.get_image_properties( task.context, image_href, ['boot_iso', 'kernel_id', 'ramdisk_id'])) 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 # will require synchronisation across conductor nodes for the shared boot # ISO. Such a synchronisation mechanism doesn't exist in ironic as of now. # 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 _prepare_boot_iso(cls, task, root_uuid=None): """Prepare boot ISO image Build bootable ISO out of `[instance_info]/kernel`, `[instance_info]/ramdisk` and `[driver_info]/bootloader` if present. Otherwise, read `kernel_id` and `ramdisk_id` from `[instance_info]/image_source` Glance image metadata. Push produced ISO image up to Glance and return temporary Swift URL to the image. :param task: a TaskManager instance containing the node to act on. :returns: bootable ISO HTTP URL. :raises: MissingParameterValue, if any of the required parameters are missing. :raises: InvalidParameterValue, if any of the parameters have invalid value. :raises: ImageCreationFailed, if creating ISO image failed. """ node = task.node d_info = cls._parse_deploy_info(node) kernel_href = node.instance_info.get('kernel') ramdisk_href = node.instance_info.get('ramdisk') if not kernel_href or not ramdisk_href: image_href = d_info['image_source'] image_properties = (images.get_image_properties( task.context, image_href, ['kernel_id', 'ramdisk_id'])) if not kernel_href: kernel_href = image_properties.get('kernel_id') if not ramdisk_href: ramdisk_href = image_properties.get('ramdisk_id') if not kernel_href or not ramdisk_href: raise exception.InvalidParameterValue( _("Unable to find kernel or ramdisk for " "to generate boot ISO for %(node)s") % {'node': task.node.uuid}) bootloader_href = d_info.get('bootloader') if CONF.redfish.use_swift: use_web_server = False container = CONF.redfish.swift_container timeout = CONF.redfish.swift_object_expiry_timeout else: use_web_server = True container = None timeout = None return virtual_media_base.prepare_iso_image( task, kernel_href, ramdisk_href, bootloader_href=bootloader_href, root_uuid=root_uuid, timeout=timeout, use_web_server=use_web_server, container=container)