Пример #1
0
    def test_create_boot_iso_for_bios_with_no_boot_mode(
            self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=io.BytesIO)
        mock_file_handle.__enter__.return_value = 'tmpdir'
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
                               'ramdisk-uuid', 'deploy_iso-uuid',
                               'efiboot-uuid', 'root-uuid', 'kernel-params',
                               None, 'http://configdrive')

        fetch_images_mock.assert_any_call('ctx', 'kernel-uuid',
                                          'tmpdir/kernel-uuid')
        fetch_images_mock.assert_any_call('ctx', 'ramdisk-uuid',
                                          'tmpdir/ramdisk-uuid')
        fetch_images_mock.assert_any_call('ctx', 'http://configdrive',
                                          'tmpdir/configdrive')

        params = ['root=UUID=root-uuid', 'kernel-params']
        create_isolinux_mock.assert_called_once_with(
            'output_file',
            'tmpdir/kernel-uuid',
            'tmpdir/ramdisk-uuid',
            configdrive='tmpdir/configdrive',
            kernel_params=params)
Пример #2
0
    def test_create_boot_iso_for_bios(
            self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=file)
        mock_file_handle.__enter__.return_value = 'tmpdir'
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
                               'ramdisk-uuid', 'deploy_iso-uuid',
                               'root-uuid', 'kernel-params', 'bios')

        fetch_images_mock.assert_any_call(
            'ctx', 'kernel-uuid', 'tmpdir/kernel-uuid')
        fetch_images_mock.assert_any_call(
            'ctx', 'ramdisk-uuid', 'tmpdir/ramdisk-uuid')
        # Note (NobodyCam): the orginal assert asserted that fetch_images
        #                   was not called with parameters, this did not
        #                   work, So I instead assert that there were only
        #                   Two calls to the mock validating the above
        #                   asserts.
        self.assertEqual(2, fetch_images_mock.call_count)

        params = ['root=UUID=root-uuid', 'kernel-params']
        create_isolinux_mock.assert_called_once_with('output_file',
                                                     'tmpdir/kernel-uuid',
                                                     'tmpdir/ramdisk-uuid',
                                                     params)
Пример #3
0
    def test_create_boot_iso_for_uefi_deploy_iso(self, tempdir_mock,
                                                 fetch_images_mock,
                                                 create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=file)
        mock_file_handle.__enter__.return_value = 'tmpdir'
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso('ctx',
                               'output_file',
                               'kernel-uuid',
                               'ramdisk-uuid',
                               deploy_iso_href='deploy_iso-uuid',
                               root_uuid='root-uuid',
                               kernel_params='kernel-params',
                               boot_mode='uefi')

        fetch_images_mock.assert_any_call('ctx', 'kernel-uuid',
                                          'tmpdir/kernel-uuid')
        fetch_images_mock.assert_any_call('ctx', 'ramdisk-uuid',
                                          'tmpdir/ramdisk-uuid')
        fetch_images_mock.assert_any_call('ctx', 'deploy_iso-uuid',
                                          'tmpdir/deploy_iso-uuid')

        params = ['root=UUID=root-uuid', 'kernel-params']
        create_isolinux_mock.assert_called_once_with(
            'output_file',
            'tmpdir/kernel-uuid',
            'tmpdir/ramdisk-uuid',
            deploy_iso='tmpdir/deploy_iso-uuid',
            esp_image=None,
            kernel_params=params)
Пример #4
0
    def test_create_boot_iso_for_uefi_for_hrefs(self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=file)
        mock_file_handle.__enter__.return_value = "tmpdir"
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso(
            "ctx",
            "output_file",
            "http://kernel-href",
            "http://ramdisk-href",
            "http://deploy_iso-href",
            "root-uuid",
            "kernel-params",
            "uefi",
        )
        expected_calls = [
            mock.call("ctx", "http://kernel-href", "tmpdir/kernel-href"),
            mock.call("ctx", "http://ramdisk-href", "tmpdir/ramdisk-href"),
            mock.call("ctx", "http://deploy_iso-href", "tmpdir/deploy_iso-href"),
        ]
        fetch_images_mock.assert_has_calls(expected_calls)
        params = ["root=UUID=root-uuid", "kernel-params"]
        create_isolinux_mock.assert_called_once_with(
            "output_file", "tmpdir/deploy_iso-href", "tmpdir/kernel-href", "tmpdir/ramdisk-href", params
        )
Пример #5
0
    def test_create_boot_iso_for_uefi_esp_image_for_hrefs(
            self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=file)
        mock_file_handle.__enter__.return_value = 'tmpdir'
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso('ctx',
                               'output_file',
                               'http://kernel-href',
                               'http://ramdisk-href',
                               esp_image_href='http://efiboot-href',
                               root_uuid='root-uuid',
                               kernel_params='kernel-params',
                               boot_mode='uefi')

        expected_calls = [
            mock.call('ctx', 'http://kernel-href', 'tmpdir/kernel-href'),
            mock.call('ctx', 'http://ramdisk-href', 'tmpdir/ramdisk-href'),
            mock.call('ctx', 'http://efiboot-href', 'tmpdir/efiboot-href')
        ]
        fetch_images_mock.assert_has_calls(expected_calls)
        params = ['root=UUID=root-uuid', 'kernel-params']
        create_isolinux_mock.assert_called_once_with(
            'output_file',
            'tmpdir/kernel-href',
            'tmpdir/ramdisk-href',
            deploy_iso=None,
            esp_image='tmpdir/efiboot-href',
            kernel_params=params)
Пример #6
0
    def test_create_boot_iso_for_bios(self, tempdir_mock, fetch_images_mock,
                                      create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=file)
        mock_file_handle.__enter__.return_value = 'tmpdir'
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
                               'ramdisk-uuid', 'deploy_iso-uuid',
                               'efiboot-uuid', 'root-uuid', 'kernel-params',
                               'bios')

        fetch_images_mock.assert_any_call('ctx', 'kernel-uuid',
                                          'tmpdir/kernel-uuid')
        fetch_images_mock.assert_any_call('ctx', 'ramdisk-uuid',
                                          'tmpdir/ramdisk-uuid')
        # Note (NobodyCam): the original assert asserted that fetch_images
        #                   was not called with parameters, this did not
        #                   work, So I instead assert that there were only
        #                   Two calls to the mock validating the above
        #                   asserts.
        self.assertEqual(2, fetch_images_mock.call_count)

        params = ['root=UUID=root-uuid', 'kernel-params']
        create_isolinux_mock.assert_called_once_with('output_file',
                                                     'tmpdir/kernel-uuid',
                                                     'tmpdir/ramdisk-uuid',
                                                     params)
Пример #7
0
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()
Пример #8
0
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()
Пример #9
0
    def test_create_boot_iso_for_bios_with_no_boot_mode(self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=file)
        mock_file_handle.__enter__.return_value = "tmpdir"
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso(
            "ctx", "output_file", "kernel-uuid", "ramdisk-uuid", "deploy_iso-uuid", "root-uuid", "kernel-params", None
        )

        fetch_images_mock.assert_any_call("ctx", "kernel-uuid", "tmpdir/kernel-uuid")
        fetch_images_mock.assert_any_call("ctx", "ramdisk-uuid", "tmpdir/ramdisk-uuid")

        params = ["root=UUID=root-uuid", "kernel-params"]
        create_isolinux_mock.assert_called_once_with("output_file", "tmpdir/kernel-uuid", "tmpdir/ramdisk-uuid", params)
Пример #10
0
    def test_create_boot_iso(self, tempdir_mock, fetch_images_mock,
                             create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=file)
        mock_file_handle.__enter__.return_value = 'tmpdir'
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
                               'ramdisk-uuid', 'root-uuid', 'kernel-params')

        fetch_images_mock.assert_any_call('ctx', 'kernel-uuid',
                'tmpdir/kernel-uuid')
        fetch_images_mock.assert_any_call('ctx', 'ramdisk-uuid',
                'tmpdir/ramdisk-uuid')
        params = ['root=UUID=root-uuid', 'kernel-params']
        create_isolinux_mock.assert_called_once_with('output_file',
                'tmpdir/kernel-uuid', 'tmpdir/ramdisk-uuid', params)
Пример #11
0
    def test_create_boot_iso_for_existing_iso(self, tempdir_mock,
                                              fetch_images_mock,
                                              create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=io.BytesIO)
        mock_file_handle.__enter__.return_value = 'tmpdir'
        tempdir_mock.return_value = mock_file_handle
        base_iso = 'http://fake.local:1234/fake.iso'
        images.create_boot_iso('ctx', 'output_file', 'kernel-uuid',
                               'ramdisk-uuid', 'deploy_iso-uuid',
                               'efiboot-uuid', None,
                               None, None, base_iso=base_iso)

        fetch_images_mock.assert_any_call(
            'ctx', base_iso, 'output_file')

        create_isolinux_mock.assert_not_called()
Пример #12
0
    def test_create_boot_iso_for_uefi_for_hrefs(
            self, tempdir_mock, fetch_images_mock, create_isolinux_mock):
        mock_file_handle = mock.MagicMock(spec=file)
        mock_file_handle.__enter__.return_value = 'tmpdir'
        tempdir_mock.return_value = mock_file_handle

        images.create_boot_iso('ctx', 'output_file', 'http://kernel-href',
                               'http://ramdisk-href', 'http://deploy_iso-href',
                               'root-uuid', 'kernel-params', 'uefi')
        expected_calls = [mock.call('ctx', 'http://kernel-href',
                                    'tmpdir/kernel-href'),
                          mock.call('ctx', 'http://ramdisk-href',
                                    'tmpdir/ramdisk-href'),
                          mock.call('ctx', 'http://deploy_iso-href',
                                    'tmpdir/deploy_iso-href')]
        fetch_images_mock.assert_has_calls(expected_calls)
        params = ['root=UUID=root-uuid', 'kernel-params']
        create_isolinux_mock.assert_called_once_with(
            'output_file', 'tmpdir/deploy_iso-href', 'tmpdir/kernel-href',
            'tmpdir/ramdisk-href', params)
Пример #13
0
def _get_boot_iso(task, root_uuid):
    """This method returns a boot ISO to boot the node.

    It chooses one of the two options in the order as below:
    1. Image deployed has a meta-property 'boot_iso' in Glance. This should
       refer to the UUID of the boot_iso which exists in Glance.
    2. 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: the information about the boot ISO. Returns the information in
        the format 'glance:<glance-boot-iso-uuid>' or
        'swift:<swift-boot_iso-object-name>'.  In case of Swift, it is assumed
        that the object exists in CONF.ilo.swift_ilo_container.
        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.
    """
    # Option 1 - Check if user has provided a boot_iso in Glance.
    LOG.debug("Trying to get a boot ISO to boot the baremetal node")
    deploy_info = _parse_deploy_info(task.node)

    image_href = deploy_info['image_source']
    glance_properties = (
        images.get_glance_image_properties(task.context,
            image_href, ['boot_iso', 'kernel_id', 'ramdisk_id']))

    boot_iso_uuid = glance_properties.get('boot_iso')
    kernel_uuid = glance_properties.get('kernel_id')
    ramdisk_uuid = glance_properties.get('ramdisk_id')

    if boot_iso_uuid:
        LOG.debug("Found boot_iso %s in Glance", boot_iso_uuid)
        return 'glance:%s' % boot_iso_uuid

    # NOTE(faizan) For uefi boot_mode, operator should provide efi capable
    # boot-iso in glance
    if driver_utils.get_node_capability(task.node, 'boot_mode') == 'uefi':
        LOG.error(_LE("Unable to find boot_iso in Glance, required to deploy "
                      "node %(node)s in UEFI boot mode."),
                  {'node': task.node.uuid})
        return

    if not kernel_uuid or not ramdisk_uuid:
        LOG.error(_LE("Unable to find 'kernel_id' and 'ramdisk_id' in Glance "
                      "image %(image)s for generating 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 2 - Create boot_iso from kernel/ramdisk, upload to Swift
    # and provide its name.
    boot_iso_object_name = _get_boot_iso_object_name(task.node)
    kernel_params = CONF.pxe.pxe_append_params
    container = CONF.ilo.swift_ilo_container

    with tempfile.NamedTemporaryFile() as fileobj:
        boot_iso_tmp_file = fileobj.name
        images.create_boot_iso(task.context, boot_iso_tmp_file,
                kernel_uuid, ramdisk_uuid, root_uuid, kernel_params)
        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
Пример #14
0
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
Пример #15
0
def prepare_iso_image(task,
                      kernel_href,
                      ramdisk_href,
                      deploy_iso_href=None,
                      bootloader_href=None,
                      root_uuid=None,
                      kernel_params=None,
                      timeout=None,
                      use_web_server=False,
                      container=None):
    """Prepare an ISO to boot the node.

        Build bootable ISO out of `kernel_href` and `ramdisk_href` (and
        `bootloader` if it's UEFI boot), then push built image up to Swift and
        return a temporary URL.

        :param task: a TaskManager instance containing the node to act on.
        :param kernel_href: URL or Glance UUID of the kernel to use
        :param ramdisk_href: URL or Glance UUID of the ramdisk to use
        :param bootloader_href: URL or Glance UUID of the EFI bootloader
             image to use when creating UEFI bootbable ISO
        :param root_uuid: optional uuid of the root partition.
        :param kernel_params: a dictionary containing 'parameter name'->'value'
            mapping to be passed to kernel command line.
        :param timeout: swift object expiry timeout
        :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.
    """
    if not kernel_href or not ramdisk_href:
        raise exception.InvalidParameterValue(
            _("Unable to find kernel or ramdisk for "
              "building ISO for %(node)s") % {'node': task.node.uuid})

    boot_mode = boot_mode_utils.get_boot_mode_for_deploy(task.node)

    LOG.debug(
        "Trying to create %(boot_mode)s ISO image for node %(node)s "
        "with kernel %(kernel_href)s, ramdisk %(ramdisk_href)s, "
        "bootloader %(bootloader_href)s and kernel params %(params)s"
        "", {
            'node': task.node.uuid,
            'boot_mode': boot_mode,
            'kernel_href': kernel_href,
            'ramdisk_href': ramdisk_href,
            'bootloader_href': bootloader_href,
            'params': kernel_params
        })

    with tempfile.NamedTemporaryFile(dir=CONF.tempdir,
                                     suffix='.iso') 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_href,
                               esp_image_href=bootloader_href,
                               root_uuid=root_uuid,
                               kernel_params=kernel_params,
                               boot_mode=boot_mode)

        iso_object_name = get_iso_image_name(task.node)

        if use_web_server:
            boot_iso_url = (deploy_utils.copy_image_to_web_server(
                boot_iso_tmp_file, 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:
            swift_api = swift.SwiftAPI()

            object_headers = None
            if task.node.driver == 'redfish':
                object_headers = {'X-Delete-After': str(timeout)}

            swift_api.create_object(container,
                                    iso_object_name,
                                    boot_iso_tmp_file,
                                    object_headers=object_headers)

            LOG.debug("Created ISO %(name)s in Swift for node %(node)s", {
                'node': task.node.uuid,
                'name': iso_object_name
            })

            if task.node.driver == 'redfish':
                boot_iso_url = swift_api.get_temp_url(container,
                                                      iso_object_name, timeout)
                return boot_iso_url
            else:
                return 'swift:%s' % iso_object_name
Пример #16
0
    def _prepare_iso_image(cls,
                           task,
                           kernel_href,
                           ramdisk_href,
                           bootloader_href=None,
                           root_uuid=None,
                           params=None):
        """Prepare an ISO to boot the node.

        Build bootable ISO out of `kernel_href` and `ramdisk_href` (and
        `bootloader` if it's UEFI boot), then push built image up to Swift and
        return a temporary URL.

        :param task: a TaskManager instance containing the node to act on.
        :param kernel_href: URL or Glance UUID of the kernel to use
        :param ramdisk_href: URL or Glance UUID of the ramdisk to use
        :param bootloader_href: URL or Glance UUID of the EFI bootloader
             image to use when creating UEFI bootbable ISO
        :param root_uuid: optional uuid of the root partition.
        :param params: a dictionary containing 'parameter name'->'value'
            mapping to be passed to kernel command line.
        :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.
        """
        if not kernel_href or not ramdisk_href:
            raise exception.InvalidParameterValue(
                _("Unable to find kernel or ramdisk for "
                  "building ISO for %(node)s") % {'node': task.node.uuid})

        i_info = task.node.instance_info

        if deploy_utils.get_boot_option(task.node) == "ramdisk":
            kernel_params = "root=/dev/ram0 text "
            kernel_params += i_info.get("ramdisk_kernel_arguments", "")

        else:
            kernel_params = i_info.get('kernel_append_params',
                                       CONF.redfish.kernel_append_params)

        if params:
            kernel_params = ' '.join(
                (kernel_params, ' '.join('%s=%s' % kv
                                         for kv in params.items())))

        boot_mode = boot_mode_utils.get_boot_mode_for_deploy(task.node)

        LOG.debug(
            "Trying to create %(boot_mode)s ISO image for node %(node)s "
            "with kernel %(kernel_href)s, ramdisk %(ramdisk_href)s, "
            "bootloader %(bootloader_href)s and kernel params %(params)s"
            "", {
                'node': task.node.uuid,
                'boot_mode': boot_mode,
                'kernel_href': kernel_href,
                'ramdisk_href': ramdisk_href,
                'bootloader_href': bootloader_href,
                'params': kernel_params
            })

        with tempfile.NamedTemporaryFile(dir=CONF.tempdir,
                                         suffix='.iso') as fileobj:
            boot_iso_tmp_file = fileobj.name
            images.create_boot_iso(task.context,
                                   boot_iso_tmp_file,
                                   kernel_href,
                                   ramdisk_href,
                                   esp_image_href=bootloader_href,
                                   root_uuid=root_uuid,
                                   kernel_params=kernel_params,
                                   boot_mode=boot_mode)

            iso_object_name = cls._get_iso_image_name(task.node)

            image_url = cls._publish_image(boot_iso_tmp_file, iso_object_name)

        LOG.debug(
            "Created ISO %(name)s in Swift for node %(node)s, exposed "
            "as temporary URL %(url)s", {
                'node': task.node.uuid,
                'name': iso_object_name,
                'url': image_url
            })

        return image_url
Пример #17
0
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
Пример #18
0
def _prepare_iso_image(task,
                       kernel_href,
                       ramdisk_href,
                       bootloader_href=None,
                       configdrive=None,
                       root_uuid=None,
                       params=None,
                       base_iso=None):
    """Prepare an ISO to boot the node.

    Build bootable ISO out of `kernel_href` and `ramdisk_href` (and
    `bootloader` if it's UEFI boot), then push built image up to Swift and
    return a temporary URL.

    If `configdrive` is specified it will be eventually written onto
    the boot ISO image.

    :param task: a TaskManager instance containing the node to act on.
    :param kernel_href: URL or Glance UUID of the kernel to use
    :param ramdisk_href: URL or Glance UUID of the ramdisk to use
    :param bootloader_href: URL or Glance UUID of the EFI bootloader
         image to use when creating UEFI bootbable ISO
    :param configdrive: URL to or a compressed blob of a ISO9660 or
        FAT-formatted OpenStack config drive image. This image will be
        written onto the built ISO image. Optional.
    :param root_uuid: optional uuid of the root partition.
    :param params: a dictionary containing 'parameter name'->'value'
        mapping to be passed to kernel command line.
    :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.
    """
    if (not kernel_href or not ramdisk_href) and not base_iso:
        raise exception.InvalidParameterValue(
            _("Unable to find kernel, ramdisk for "
              "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
    # this logic actually does nothing in the end. But it should!
    if deploy_utils.get_boot_option(task.node) == "ramdisk":
        if not base_iso:
            kernel_params = "root=/dev/ram0 text "
            kernel_params += i_info.get("ramdisk_kernel_arguments", "")
        else:
            kernel_params = None

    else:
        kernel_params = i_info.get('kernel_append_params', k_param)

    if params and not base_iso:
        kernel_params = ' '.join(
            (kernel_params, ' '.join('%s=%s' % kv for kv in params.items())))

    boot_mode = boot_mode_utils.get_boot_mode_for_deploy(task.node)

    LOG.debug(
        "Trying to create %(boot_mode)s ISO image for node %(node)s "
        "with kernel %(kernel_href)s, ramdisk %(ramdisk_href)s, "
        "bootloader %(bootloader_href)s and kernel params %(params)s"
        "", {
            'node': task.node.uuid,
            'boot_mode': boot_mode,
            'kernel_href': kernel_href,
            'ramdisk_href': ramdisk_href,
            'bootloader_href': bootloader_href,
            'params': kernel_params
        })

    with tempfile.NamedTemporaryFile(dir=CONF.tempdir,
                                     suffix='.iso') as boot_fileobj:

        with tempfile.NamedTemporaryFile(dir=CONF.tempdir,
                                         suffix='.img') as cfgdrv_fileobj:

            configdrive_href = configdrive

            # FIXME(TheJulia): This is treated as conditional with
            # a base_iso as the intent, eventually, is to support
            # injection into the supplied image.

            if configdrive and not base_iso:
                parsed_url = urlparse.urlparse(configdrive)
                if not parsed_url.scheme:
                    cfgdrv_blob = base64.decode_as_bytes(configdrive)

                    with open(cfgdrv_fileobj.name, 'wb') as f:
                        f.write(cfgdrv_blob)

                    configdrive_href = urlparse.urlunparse(
                        ('file', '', cfgdrv_fileobj.name, '', '', ''))

                LOG.debug(
                    "Built configdrive out of configdrive blob "
                    "for node %(node)s", {'node': task.node.uuid})

            boot_iso_tmp_file = boot_fileobj.name
            images.create_boot_iso(task.context,
                                   boot_iso_tmp_file,
                                   kernel_href,
                                   ramdisk_href,
                                   esp_image_href=bootloader_href,
                                   configdrive_href=configdrive_href,
                                   root_uuid=root_uuid,
                                   kernel_params=kernel_params,
                                   boot_mode=boot_mode,
                                   base_iso=base_iso)

            iso_object_name = _get_iso_image_name(task.node)

            image_url = img_handler.publish_image(boot_iso_tmp_file,
                                                  iso_object_name)

    LOG.debug(
        "Created ISO %(name)s in object store for node %(node)s, "
        "exposed as temporary URL "
        "%(url)s", {
            'node': task.node.uuid,
            'name': iso_object_name,
            'url': image_url
        })

    return image_url
Пример #19
0
def _prepare_iso_image(task,
                       kernel_href,
                       ramdisk_href,
                       bootloader_href=None,
                       root_uuid=None,
                       params=None,
                       base_iso=None,
                       inject_files=None):
    """Prepare an ISO to boot the node.

    Build bootable ISO out of `kernel_href` and `ramdisk_href` (and
    `bootloader` if it's UEFI boot), then push built image up to Swift and
    return a temporary URL.

    :param task: a TaskManager instance containing the node to act on.
    :param kernel_href: URL or Glance UUID of the kernel to use
    :param ramdisk_href: URL or Glance UUID of the ramdisk to use
    :param bootloader_href: URL or Glance UUID of the EFI bootloader
         image to use when creating UEFI bootbable ISO
    :param root_uuid: optional uuid of the root partition.
    :param params: a dictionary containing 'parameter name'->'value'
        mapping to be passed to kernel command line.
    :param inject_files: Mapping of local source file paths to their location
        on the final ISO image.
    :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.
    """
    if (not kernel_href or not ramdisk_href) and not base_iso:
        raise exception.InvalidParameterValue(
            _("Unable to find kernel, ramdisk for "
              "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
    # this logic actually does nothing in the end. But it should!
    if deploy_utils.get_boot_option(task.node) == "ramdisk":
        if not base_iso:
            kernel_params = "root=/dev/ram0 text "
            kernel_params += i_info.get("ramdisk_kernel_arguments", "")
        else:
            kernel_params = None

    else:
        kernel_params = i_info.get('kernel_append_params', k_param)

    if params and not base_iso:
        kernel_params = ' '.join(
            (kernel_params, ' '.join('%s=%s' % kv for kv in params.items())))

    boot_mode = boot_mode_utils.get_boot_mode(task.node)

    LOG.debug(
        "Trying to create %(boot_mode)s ISO image for node %(node)s "
        "with kernel %(kernel_href)s, ramdisk %(ramdisk_href)s, "
        "bootloader %(bootloader_href)s and kernel params %(params)s"
        "", {
            'node': task.node.uuid,
            'boot_mode': boot_mode,
            'kernel_href': kernel_href,
            'ramdisk_href': ramdisk_href,
            'bootloader_href': bootloader_href,
            'params': kernel_params
        })

    with tempfile.NamedTemporaryFile(dir=CONF.tempdir,
                                     suffix='.iso') as boot_fileobj:

        boot_iso_tmp_file = boot_fileobj.name
        images.create_boot_iso(task.context,
                               boot_iso_tmp_file,
                               kernel_href,
                               ramdisk_href,
                               esp_image_href=bootloader_href,
                               root_uuid=root_uuid,
                               kernel_params=kernel_params,
                               boot_mode=boot_mode,
                               base_iso=base_iso,
                               inject_files=inject_files)

        iso_object_name = _get_name(task.node, prefix='boot', suffix='.iso')

        image_url = img_handler.publish_image(boot_iso_tmp_file,
                                              iso_object_name)

    LOG.debug(
        "Created ISO %(name)s in object store for node %(node)s, "
        "exposed as temporary URL "
        "%(url)s", {
            'node': task.node.uuid,
            'name': iso_object_name,
            'url': image_url
        })

    return image_url