Exemple #1
0
def _collect_files(image_path):
    """Mount image and return a dictionary of paths found there.

    Mounts given image under a temporary directory, walk its contents
    and produce a dictionary of absolute->relative paths found on the
    image.

    :param image_path: ISO9660 or FAT-formatted image to mount.
    :raises: ImageCreationFailed, if image inspection failed.
    :returns: a dict mapping absolute paths to relative to the mount point.
    """
    if not image_path:
        yield {}
        return

    with utils.tempdir() as mount_dir:
        try:
            utils.mount(image_path, mount_dir, '-o', 'loop')

        except processutils.ProcessExecutionError as e:
            LOG.exception("Mounting filesystem image %(image)s "
                          "failed", {'image': image_path})
            raise exception.ImageCreationFailed(image_type='iso', error=e)

        try:
            yield _read_dir(mount_dir)

        except EnvironmentError as e:
            LOG.exception("Examining image %(images)s failed: ",
                          {'image': image_path})
            _umount_without_raise(mount_dir)
            raise exception.ImageCreationFailed(image_type='iso', error=e)

        _umount_without_raise(mount_dir)
Exemple #2
0
def create_vfat_image(output_file, files_info=None, parameters=None,
                      parameters_file='parameters.txt', fs_size_kib=100):
    """Creates the fat fs image on the desired file.

    This method copies the given files to a root directory (optional),
    writes the parameters specified to the parameters file within the
    root directory (optional), and then creates a vfat image of the root
    directory.

    :param output_file: The path to the file where the fat fs image needs
        to be created.
    :param files_info: A dict containing absolute path of file to be copied
        -> relative path within the vfat image. For example,
        {
         '/absolute/path/to/file' -> 'relative/path/within/root'
         ...
        }
    :param parameters: A dict containing key-value pairs of parameters.
    :param parameters_file: The filename for the parameters file.
    :param fs_size_kib: size of the vfat filesystem in KiB.
    :raises: ImageCreationFailed, if image creation failed while doing any
        of filesystem manipulation activities like creating dirs, mounting,
        creating filesystem, copying files, etc.
    """
    try:
        utils.dd('/dev/zero', output_file, 'count=1', "bs=%dKiB" % fs_size_kib)
    except processutils.ProcessExecutionError as e:
        raise exception.ImageCreationFailed(image_type='vfat', error=e)

    with utils.tempdir() as tmpdir:

        try:
            # The label helps ramdisks to find the partition containing
            # the parameters (by using /dev/disk/by-label/ir-vfd-dev).
            # NOTE: FAT filesystem label can be up to 11 characters long.
            utils.mkfs('vfat', output_file, label="ir-vfd-dev")
            utils.mount(output_file, tmpdir, '-o', 'umask=0')
        except processutils.ProcessExecutionError as e:
            raise exception.ImageCreationFailed(image_type='vfat', error=e)

        try:
            if files_info:
                _create_root_fs(tmpdir, files_info)

            if parameters:
                parameters_file = os.path.join(tmpdir, parameters_file)
                params_list = ['%(key)s=%(val)s' % {'key': k, 'val': v}
                               for k, v in parameters.items()]
                file_contents = '\n'.join(params_list)
                utils.write_to_file(parameters_file, file_contents)

        except Exception as e:
            LOG.exception(_LE("vfat image creation failed. Error: %s"), e)
            raise exception.ImageCreationFailed(image_type='vfat', error=e)

        finally:
            try:
                utils.umount(tmpdir)
            except processutils.ProcessExecutionError as e:
                raise exception.ImageCreationFailed(image_type='vfat', error=e)
Exemple #3
0
def _mount_deploy_iso(deploy_iso, mountdir):
    """This function opens up the deploy iso used for deploy.

    :param: deploy_iso: path to the deploy iso where its
                        contents are fetched to.
    :raises: ImageCreationFailed if mount fails.
    :returns: a tuple consisting of - 1. a dictionary containing
                                         the values as required
                                         by create_isolinux_image,
                                      2. efiboot.img relative path, and
                                      3. grub.cfg relative path.

    """
    e_img_rel_path = None
    e_img_path = None
    grub_rel_path = None
    grub_path = None

    try:
        utils.mount(deploy_iso, mountdir, '-o', 'loop')
    except processutils.ProcessExecutionError as e:
        LOG.exception("mounting the deploy iso failed.")
        raise exception.ImageCreationFailed(image_type='iso', error=e)

    try:
        for (dir, subdir, files) in os.walk(mountdir):
            if 'efiboot.img' in files:
                e_img_path = os.path.join(dir, 'efiboot.img')
                e_img_rel_path = os.path.relpath(e_img_path,
                                                 mountdir)
            if 'grub.cfg' in files:
                grub_path = os.path.join(dir, 'grub.cfg')
                grub_rel_path = os.path.relpath(grub_path,
                                                mountdir)
    except (OSError, IOError) as e:
        LOG.exception("examining the deploy iso failed.")
        _umount_without_raise(mountdir)
        raise exception.ImageCreationFailed(image_type='iso', error=e)

    # check if the variables are assigned some values or not during
    # walk of the mountdir.
    if not (e_img_path and e_img_rel_path and grub_path and grub_rel_path):
        error = (_("Deploy iso didn't contain efiboot.img or grub.cfg"))
        _umount_without_raise(mountdir)
        raise exception.ImageCreationFailed(image_type='iso', error=error)

    uefi_path_info = {e_img_path: e_img_rel_path,
                      grub_path: grub_rel_path}

    # Returning a tuple as it makes the code simpler and clean.
    # uefi_path_info: is needed by the caller for _create_root_fs to create
    # appropriate directory structures for uefi boot iso.
    # grub_rel_path: is needed to copy the new grub.cfg generated using
    # generate_cfg() to the same directory path structure where it was
    # present in deploy iso. This path varies for different OS vendors.
    # e_img_rel_path: is required by mkisofs to generate boot iso.
    return uefi_path_info, e_img_rel_path, grub_rel_path
Exemple #4
0
def create_isolinux_image_for_bios(output_file,
                                   kernel,
                                   ramdisk,
                                   kernel_params=None):
    """Creates an isolinux image on the specified file.

    Copies the provided kernel, ramdisk to a directory, generates the isolinux
    configuration file using the kernel parameters provided, and then generates
    a bootable ISO image.

    :param output_file: the path to the file where the iso image needs to be
        created.
    :param kernel: the kernel to use.
    :param ramdisk: the ramdisk to use.
    :param kernel_params: a list of strings(each element being a string like
        'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
        as the kernel cmdline.
    :raises: ImageCreationFailed, if image creation failed while copying files
        or while running command to generate iso.
    """
    ISOLINUX_BIN = 'isolinux/isolinux.bin'
    ISOLINUX_CFG = 'isolinux/isolinux.cfg'

    options = {'kernel': '/vmlinuz', 'ramdisk': '/initrd'}

    with utils.tempdir() as tmpdir:
        files_info = {
            kernel: 'vmlinuz',
            ramdisk: 'initrd',
            CONF.isolinux_bin: ISOLINUX_BIN,
        }
        try:
            _create_root_fs(tmpdir, files_info)
        except (OSError, IOError) as e:
            LOG.exception(_LE("Creating the filesystem root failed."))
            raise exception.ImageCreationFailed(image_type='iso', error=e)

        cfg = _generate_cfg(kernel_params, CONF.isolinux_config_template,
                            options)

        isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG)
        utils.write_to_file(isolinux_cfg, cfg)

        try:
            utils.execute('mkisofs', '-r', '-V', "VMEDIA_BOOT_ISO",
                          '-cache-inodes', '-J', '-l', '-no-emul-boot',
                          '-boot-load-size', '4', '-boot-info-table', '-b',
                          ISOLINUX_BIN, '-o', output_file, tmpdir)
        except processutils.ProcessExecutionError as e:
            LOG.exception(_LE("Creating ISO image failed."))
            raise exception.ImageCreationFailed(image_type='iso', error=e)
Exemple #5
0
def prepare_configdrive_image(task, content):
    """Prepare an image with configdrive.

    :param task: a TaskManager instance containing the node to act on.
    :param content: Config drive as a base64-encoded string.
    :raises: ImageCreationFailed, if it failed while creating the image.
    :raises: SwiftOperationError, if any operation with Swift fails.
    :returns: image URL for the image.
    """
    # FIXME(dtantsur): download and convert?
    if '://' in content:
        raise exception.ImageCreationFailed(
            _('URLs are not supported for configdrive images yet'))

    with tempfile.TemporaryFile(dir=CONF.tempdir) as comp_tmpfile_obj:
        comp_tmpfile_obj.write(base64.b64decode(content))
        comp_tmpfile_obj.seek(0)
        gz = gzip.GzipFile(fileobj=comp_tmpfile_obj, mode='rb')
        with tempfile.NamedTemporaryFile(dir=CONF.tempdir,
                                         suffix='.img') as image_tmpfile_obj:
            shutil.copyfileobj(gz, image_tmpfile_obj)
            image_tmpfile_obj.flush()
            return prepare_disk_image(task,
                                      image_tmpfile_obj.name,
                                      prefix='configdrive')
Exemple #6
0
    def test__continue_deploy_create_boot_iso_fail(self, get_iso_mock,
            cleanup_vmedia_boot_mock, continue_deploy_mock, node_power_mock):
        kwargs = {'address': '123456'}
        continue_deploy_mock.return_value = 'root-uuid'
        get_iso_mock.side_effect = exception.ImageCreationFailed(
                                             image_type='iso', error="error")
        self.node.provision_state = states.DEPLOYWAIT
        self.node.target_provision_state = states.ACTIVE
        self.node.save()

        with task_manager.acquire(self.context, self.node.uuid,
                                  shared=False) as task:
            task.driver.vendor._continue_deploy(task, **kwargs)

            cleanup_vmedia_boot_mock.assert_called_once_with(task)
            continue_deploy_mock.assert_called_once_with(task, **kwargs)
            get_iso_mock.assert_called_once_with(task, 'root-uuid')
            node_power_mock.assert_called_once_with(task, states.POWER_OFF)
            self.assertEqual(states.DEPLOYFAIL, task.node.provision_state)
            self.assertEqual(states.ACTIVE, task.node.target_provision_state)
            self.assertIsNotNone(task.node.last_error)
Exemple #7
0
def create_isolinux_image_for_uefi(output_file,
                                   kernel,
                                   ramdisk,
                                   deploy_iso=None,
                                   esp_image=None,
                                   kernel_params=None):
    """Creates an isolinux image on the specified file.

    Copies the provided kernel, ramdisk and EFI system partition image to
    a directory, generates the grub configuration file using kernel parameters
    and then generates a bootable ISO image for UEFI.

    :param output_file: the path to the file where the iso image needs to be
        created.
    :param kernel: the kernel to use.
    :param ramdisk: the ramdisk to use.
    :param deploy_iso: deploy ISO image to extract EFI system partition image
        from. If not specified, the `esp_image` option is required.
    :param esp_image: FAT12/16/32-formatted EFI system partition image
        containing the EFI boot loader (e.g. GRUB2) for each hardware
        architecture to boot. This image will be embedded into the ISO image.
        If not specified, the `deploy_iso` option is required.
    :param kernel_params: a list of strings(each element being a string like
        'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
        as the kernel cmdline.
    :raises: ImageCreationFailed, if image creation failed while copying files
        or while running command to generate iso.
    """
    EFIBOOT_LOCATION = 'boot/grub/efiboot.img'

    grub_options = {'linux': '/vmlinuz', 'initrd': '/initrd'}

    with utils.tempdir() as tmpdir:
        files_info = {
            kernel: 'vmlinuz',
            ramdisk: 'initrd',
        }

        with utils.tempdir() as mountdir:
            # Open the deploy iso used to initiate deploy and copy the
            # efiboot.img i.e. boot loader to the current temporary
            # directory.
            if deploy_iso and not esp_image:
                uefi_path_info, e_img_rel_path, grub_rel_path = (
                    _mount_deploy_iso(deploy_iso, mountdir))

                grub_cfg = os.path.join(tmpdir, grub_rel_path)

            # Use ELF boot loader provided
            elif esp_image and not deploy_iso:
                e_img_rel_path = EFIBOOT_LOCATION
                grub_rel_path = CONF.grub_config_path.lstrip(' ' + os.sep)
                grub_cfg = os.path.join(tmpdir, grub_rel_path)

                uefi_path_info = {
                    esp_image: e_img_rel_path,
                    grub_cfg: grub_rel_path
                }

            else:
                msg = _('Neither deploy ISO nor ESP image configured or '
                        'both of them configured')
                raise exception.ImageCreationFailed(image_type='iso',
                                                    error=msg)

            files_info.update(uefi_path_info)

            try:
                _create_root_fs(tmpdir, files_info)

            except (OSError, IOError) as e:
                LOG.exception("Creating the filesystem root failed.")
                raise exception.ImageCreationFailed(image_type='iso', error=e)

            finally:
                if deploy_iso:
                    _umount_without_raise(mountdir)

        # Generate and copy grub config file.
        grub_conf = _generate_cfg(kernel_params, CONF.grub_config_template,
                                  grub_options)
        utils.write_to_file(grub_cfg, grub_conf)

        # Create the boot_iso.
        try:
            utils.execute('mkisofs', '-r', '-V', "VMEDIA_BOOT_ISO", '-l', '-e',
                          e_img_rel_path, '-no-emul-boot', '-o', output_file,
                          tmpdir)

        except processutils.ProcessExecutionError as e:
            LOG.exception("Creating ISO image failed.")
            raise exception.ImageCreationFailed(image_type='iso', error=e)
Exemple #8
0
def create_isolinux_image_for_uefi(output_file,
                                   deploy_iso,
                                   kernel,
                                   ramdisk,
                                   kernel_params=None):
    """Creates an isolinux image on the specified file.

    Copies the provided kernel, ramdisk, efiboot.img to a directory, creates
    the path for grub config file, generates the isolinux configuration file
    using the kernel parameters provided, generates the grub configuration
    file using kernel parameters and then generates a bootable ISO image
    for uefi.

    :param output_file: the path to the file where the iso image needs to be
        created.
    :param deploy_iso: deploy iso used to initiate the deploy.
    :param kernel: the kernel to use.
    :param ramdisk: the ramdisk to use.
    :param kernel_params: a list of strings(each element being a string like
        'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
        as the kernel cmdline.
    :raises: ImageCreationFailed, if image creation failed while copying files
        or while running command to generate iso.
    """
    ISOLINUX_BIN = 'isolinux/isolinux.bin'
    ISOLINUX_CFG = 'isolinux/isolinux.cfg'

    isolinux_options = {'kernel': '/vmlinuz', 'ramdisk': '/initrd'}
    grub_options = {'linux': '/vmlinuz', 'initrd': '/initrd'}

    with utils.tempdir() as tmpdir:
        files_info = {
            kernel: 'vmlinuz',
            ramdisk: 'initrd',
            CONF.isolinux_bin: ISOLINUX_BIN,
        }

        # Open the deploy iso used to initiate deploy and copy the
        # efiboot.img i.e. boot loader to the current temporary
        # directory.
        with utils.tempdir() as mountdir:
            uefi_path_info, e_img_rel_path, grub_rel_path = (_mount_deploy_iso(
                deploy_iso, mountdir))

            # if either of these variables are not initialized then the
            # uefi efiboot.img cannot be created.
            files_info.update(uefi_path_info)
            try:
                _create_root_fs(tmpdir, files_info)
            except (OSError, IOError) as e:
                LOG.exception("Creating the filesystem root failed.")
                raise exception.ImageCreationFailed(image_type='iso', error=e)
            finally:
                _umount_without_raise(mountdir)

        cfg = _generate_cfg(kernel_params, CONF.isolinux_config_template,
                            isolinux_options)

        isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG)
        utils.write_to_file(isolinux_cfg, cfg)

        # Generate and copy grub config file.
        grub_cfg = os.path.join(tmpdir, grub_rel_path)
        grub_conf = _generate_cfg(kernel_params, CONF.grub_config_template,
                                  grub_options)
        utils.write_to_file(grub_cfg, grub_conf)

        # Create the boot_iso.
        try:
            utils.execute('mkisofs', '-r', '-V', "VMEDIA_BOOT_ISO",
                          '-cache-inodes', '-J', '-l', '-no-emul-boot',
                          '-boot-load-size', '4', '-boot-info-table', '-b',
                          ISOLINUX_BIN, '-eltorito-alt-boot', '-e',
                          e_img_rel_path, '-no-emul-boot', '-o', output_file,
                          tmpdir)
        except processutils.ProcessExecutionError as e:
            LOG.exception("Creating ISO image failed.")
            raise exception.ImageCreationFailed(image_type='iso', error=e)
Exemple #9
0
def create_isolinux_image_for_bios(output_file,
                                   kernel,
                                   ramdisk,
                                   kernel_params=None,
                                   inject_files=None):
    """Creates an isolinux image on the specified file.

    Copies the provided kernel, ramdisk to a directory, generates the isolinux
    configuration file using the kernel parameters provided, and then generates
    a bootable ISO image.

    :param output_file: the path to the file where the iso image needs to be
        created.
    :param kernel: the kernel to use.
    :param ramdisk: the ramdisk to use.
    :param kernel_params: a list of strings(each element being a string like
        'K=V' or 'K' or combination of them like 'K1=V1,K2,...') to be added
        as the kernel cmdline.
    :param inject_files: Mapping of local source file paths to their location
        on the final ISO image.
    :raises: ImageCreationFailed, if image creation failed while copying files
        or while running command to generate iso.
    """
    ISOLINUX_BIN = 'isolinux/isolinux.bin'
    ISOLINUX_CFG = 'isolinux/isolinux.cfg'
    LDLINUX_SRC_DIRS = [
        '/usr/lib/syslinux/modules/bios', '/usr/share/syslinux'
    ]
    LDLINUX_BIN = 'isolinux/ldlinux.c32'

    options = {'kernel': '/vmlinuz', 'ramdisk': '/initrd'}

    with utils.tempdir() as tmpdir:
        files_info = {
            kernel: 'vmlinuz',
            ramdisk: 'initrd',
            CONF.isolinux_bin: ISOLINUX_BIN,
        }
        if inject_files:
            files_info.update(inject_files)

        # ldlinux.c32 is required for syslinux 5.0 or later.
        if CONF.ldlinux_c32:
            ldlinux_src = CONF.ldlinux_c32
        else:
            for directory in LDLINUX_SRC_DIRS:
                ldlinux_src = os.path.join(directory, 'ldlinux.c32')
                if os.path.isfile(ldlinux_src):
                    break
            else:
                ldlinux_src = None
        if ldlinux_src:
            files_info[ldlinux_src] = LDLINUX_BIN

        try:
            _create_root_fs(tmpdir, files_info)

        except EnvironmentError as e:
            LOG.exception("Creating the filesystem root failed.")
            raise exception.ImageCreationFailed(image_type='iso', error=e)

        cfg = _generate_cfg(kernel_params, CONF.isolinux_config_template,
                            options)

        isolinux_cfg = os.path.join(tmpdir, ISOLINUX_CFG)
        utils.write_to_file(isolinux_cfg, cfg)

        try:
            utils.execute('mkisofs', '-r', '-V', _label(files_info),
                          '-cache-inodes', '-J', '-l', '-no-emul-boot',
                          '-boot-load-size', '4', '-boot-info-table', '-b',
                          ISOLINUX_BIN, '-o', output_file, tmpdir)
        except processutils.ProcessExecutionError as e:
            LOG.exception("Creating ISO image failed.")
            raise exception.ImageCreationFailed(image_type='iso', error=e)