Пример #1
0
def create_pxe_config(task, pxe_options, template=None):
    """Generate PXE configuration file and MAC address links for it.

    This method will generate the PXE configuration file for the task's
    node under a directory named with the UUID of that node. For each
    MAC address (port) of that node, a symlink for the configuration file
    will be created under the PXE configuration directory, so regardless
    of which port boots first they'll get the same PXE configuration.

    :param task: A TaskManager instance.
    :param pxe_options: A dictionary with the PXE configuration
        parameters.
    :param template: The PXE configuration template. If no template is
        given the CONF.pxe.pxe_config_template will be used.

    """
    LOG.debug("Building PXE config for node %s", task.node.uuid)

    if template is None:
        template = CONF.pxe.pxe_config_template

    _ensure_config_dirs_exist(task.node.uuid)

    pxe_config_file_path = get_pxe_config_file_path(task.node.uuid)
    pxe_config = _build_pxe_config(pxe_options, template)
    utils.write_to_file(pxe_config_file_path, pxe_config)

    if driver_utils.get_node_capability(task.node, 'boot_mode') == 'uefi':
        _link_ip_address_pxe_configs(task)
    else:
        _link_mac_pxe_configs(task)
Пример #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)
Пример #3
0
    def _create_auto_config(self, task):
        auto_info = {}
        managemenet_ip = task.node.instance_info.get('management_ip')
        auto_info['management_ip'] = managemenet_ip
        auto_info['management_netmask'] = \
            task.node.instance_info.get('management_netmask')
        auto_info['management_gateway'] = \
            task.node.instance_info.get('management_gateway')
        auto_info['hostname'] = \
            HOSTNAME_PREFIX + managemenet_ip.replace('.', '-')
        auto_info['os_ver'] = \
            task.node.instance_info.get('os_ver')
        auto_info['server_ip'] = CONF.my_ip
        extra_info = task.node.extra
        pxe_boot_interface_mac = self._get_boot_interface_mac(task)
        for nic in extra_info.get('nic_detailed'):
            address = nic.get('mac_address')
            LOG.info('address: %s', address)
            if nic.get('mac_address') == pxe_boot_interface_mac:
                auto_info['management_port'] = nic.get('name')
                break

        fileutils.ensure_tree(AUTO_FILE_DIR)
        auto_file_name = task.node.uuid + '_auto.cfg'
        auto_file_path = AUTO_FILE_DIR + auto_file_name
        tmpl_path, tmpl_file = os.path.split(CONF.pxe_auto.pxe_auto_template)
        env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path))
        template = env.get_template(tmpl_file)
        auto_info = template.render({
            'auto_info': auto_info,
            'server_ip': CONF.my_ip,
            'repo_server_ip': CONF.pxe_auto.repo_server,
            'UUID': task.node.uuid,
        })
        utils.write_to_file(auto_file_path, auto_info)
Пример #4
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)
Пример #5
0
def create_pxe_config(task, pxe_options, template=None):
    """Generate PXE configuration file and MAC address links for it.

    This method will generate the PXE configuration file for the task's
    node under a directory named with the UUID of that node. For each
    MAC address or DHCP IP address (port) of that node, a symlink for
    the configuration file will be created under the PXE configuration
    directory, so regardless of which port boots first they'll get the
    same PXE configuration.
    If elilo is the bootloader in use, then its configuration file will
    be created based on hex form of DHCP IP address.
    If grub2 bootloader is in use, then its configuration will be created
    based on DHCP IP address in the form nn.nn.nn.nn.

    :param task: A TaskManager instance.
    :param pxe_options: A dictionary with the PXE configuration
        parameters.
    :param template: The PXE configuration template. If no template is
        given the node specific template will be used.

    """
    LOG.debug("Building PXE config for node %s", task.node.uuid)

    if template is None:
        template = deploy_utils.get_pxe_config_template(task.node)

    _ensure_config_dirs_exist(task.node.uuid)

    pxe_config_file_path = get_pxe_config_file_path(task.node.uuid)
    is_uefi_boot_mode = (deploy_utils.get_boot_mode_for_deploy(task.node) ==
                         'uefi')

    # grub bootloader panics with '{}' around any of its tags in its
    # config file. To overcome that 'ROOT' and 'DISK_IDENTIFIER' are enclosed
    # with '(' and ')' in uefi boot mode.
    # These changes do not have any impact on elilo bootloader.
    hex_form = True
    if is_uefi_boot_mode and utils.is_regex_string_in_file(template,
                                                           '^menuentry'):
        hex_form = False
        pxe_config_root_tag = '(( ROOT ))'
        pxe_config_disk_ident = '(( DISK_IDENTIFIER ))'
    else:
        # TODO(stendulker): We should use '(' ')' as the delimiters for all our
        # config files so that we do not need special handling for each of the
        # bootloaders. Should be removed once the Mitaka release starts.
        pxe_config_root_tag = '{{ ROOT }}'
        pxe_config_disk_ident = '{{ DISK_IDENTIFIER }}'

    params = {'pxe_options': pxe_options,
              'ROOT': pxe_config_root_tag,
              'DISK_IDENTIFIER': pxe_config_disk_ident}

    pxe_config = utils.render_template(template, params)
    utils.write_to_file(pxe_config_file_path, pxe_config)

    if is_uefi_boot_mode and not CONF.pxe.ipxe_enabled:
        _link_ip_address_pxe_configs(task, hex_form)
    else:
        _link_mac_pxe_configs(task)
Пример #6
0
def create_pxe_config(task, pxe_options, template=None):
    """Generate PXE configuration file and MAC address links for it.

    This method will generate the PXE configuration file for the task's
    node under a directory named with the UUID of that node. For each
    MAC address (port) of that node, a symlink for the configuration file
    will be created under the PXE configuration directory, so regardless
    of which port boots first they'll get the same PXE configuration.

    :param task: A TaskManager instance.
    :param pxe_options: A dictionary with the PXE configuration
        parameters.
    :param template: The PXE configuration template. If no template is
        given the CONF.pxe.pxe_config_template will be used.

    """
    LOG.debug("Building PXE config for node %s", task.node.uuid)

    if template is None:
        template = CONF.pxe.pxe_config_template

    _ensure_config_dirs_exist(task.node.uuid)

    pxe_config_file_path = get_pxe_config_file_path(task.node.uuid)
    pxe_config = _build_pxe_config(pxe_options, template)
    utils.write_to_file(pxe_config_file_path, pxe_config)

    if driver_utils.get_node_capability(task.node, 'boot_mode') == 'uefi':
        _link_ip_address_pxe_configs(task)
    else:
        _link_mac_pxe_configs(task)
Пример #7
0
def _create_token_file(task):
    """Save PKI token to file."""
    token_file_path = _get_token_file_path(task.node.uuid)
    token = task.context.auth_token
    if token:
        utils.write_to_file(token_file_path, token)
    else:
        utils.unlink_without_raise(token_file_path)
Пример #8
0
def _create_token_file(task, node):
    """Save PKI token to file."""
    token_file_path = _get_token_file_path(node['uuid'])
    token = task.context.auth_token
    if token:
        utils.write_to_file(token_file_path, token)
    else:
        utils.unlink_without_raise(token_file_path)
Пример #9
0
def _prepare_floppy_image(task, params):
    """Prepares the floppy image for passing the parameters.

    This method prepares a temporary vfat filesystem image. Then it adds
    two files into the image - one containing the authentication token and
    the other containing the parameters to be passed to the ramdisk. Then it
    uploads the file to Swift in 'swift_ilo_container', setting it to
    auto-expire after 'swift_object_expiry_timeout' seconds. Then it returns
    the temp url for the Swift object.

    :param task: a TaskManager instance containing the node to act on.
    :param params: a dictionary containing 'parameter name'->'value' mapping
        to be passed to the deploy ramdisk via the floppy image.
    :raises: ImageCreationFailed, if it failed while creating the floppy image.
    :raises: SwiftOperationError, if any operation with Swift fails.
    :returns: the Swift temp url for the floppy image.
    """
    with tempfile.NamedTemporaryFile() as vfat_image_tmpfile_obj:

        files_info = {}
        token_tmpfile_obj = None
        vfat_image_tmpfile = vfat_image_tmpfile_obj.name

        # If auth_strategy is noauth, then no need to write token into
        # the image file.
        if task.context.auth_token:
            token_tmpfile_obj = tempfile.NamedTemporaryFile()
            token_tmpfile = token_tmpfile_obj.name
            utils.write_to_file(token_tmpfile, task.context.auth_token)
            files_info[token_tmpfile] = 'token'

        try:
            images.create_vfat_image(vfat_image_tmpfile,
                                     files_info=files_info,
                                     parameters=params)
        finally:
            if token_tmpfile_obj:
                token_tmpfile_obj.close()

        container = CONF.ilo.swift_ilo_container
        object_name = _get_floppy_image_name(task.node)
        timeout = CONF.ilo.swift_object_expiry_timeout

        object_headers = {'X-Delete-After': timeout}
        swift_api = swift.SwiftAPI()
        swift_api.create_object(container,
                                object_name,
                                vfat_image_tmpfile,
                                object_headers=object_headers)
        temp_url = swift_api.get_temp_url(container, object_name, timeout)

        LOG.debug(
            "Uploaded floppy image %(object_name)s to %(container)s "
            "for deployment.", {
                'object_name': object_name,
                'container': container
            })
        return temp_url
Пример #10
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)
Пример #11
0
def create_pxe_config(task, pxe_options, template=None):
    """Generate PXE configuration file and MAC address links for it.

    This method will generate the PXE configuration file for the task's
    node under a directory named with the UUID of that node. For each
    MAC address or DHCP IP address (port) of that node, a symlink for
    the configuration file will be created under the PXE configuration
    directory, so regardless of which port boots first they'll get the
    same PXE configuration.
    If elilo is the bootloader in use, then its configuration file will
    be created based on hex form of DHCP IP address.
    If grub2 bootloader is in use, then its configuration will be created
    based on DHCP IP address in the form nn.nn.nn.nn.

    :param task: A TaskManager instance.
    :param pxe_options: A dictionary with the PXE configuration
        parameters.
    :param template: The PXE configuration template. If no template is
        given the CONF.pxe.pxe_config_template will be used.

    """
    LOG.debug("Building PXE config for node %s", task.node.uuid)

    if template is None:
        template = CONF.pxe.pxe_config_template

    _ensure_config_dirs_exist(task.node.uuid)

    pxe_config_file_path = get_pxe_config_file_path(task.node.uuid)
    is_uefi_boot_mode = (deploy_utils.get_boot_mode_for_deploy(task.node) ==
                         'uefi')

    # grub bootloader panics with '{}' around any of its tags in its
    # config file. To overcome that 'ROOT' and 'DISK_IDENTIFIER' are enclosed
    # with '(' and ')' in uefi boot mode.
    # These changes do not have any impact on elilo bootloader.
    hex_form = True
    if is_uefi_boot_mode and utils.is_regex_string_in_file(template,
                                                           '^menuentry'):
        hex_form = False
        pxe_config_root_tag = '(( ROOT ))'
        pxe_config_disk_ident = '(( DISK_IDENTIFIER ))'
    else:
        # TODO(stendulker): We should use '(' ')' as the delimiters for all our
        # config files so that we do not need special handling for each of the
        # bootloaders. Should be removed once the Mitaka release starts.
        pxe_config_root_tag = '{{ ROOT }}'
        pxe_config_disk_ident = '{{ DISK_IDENTIFIER }}'

    pxe_config = _build_pxe_config(pxe_options, template, pxe_config_root_tag,
                                   pxe_config_disk_ident)
    utils.write_to_file(pxe_config_file_path, pxe_config)

    if is_uefi_boot_mode:
        _link_ip_address_pxe_configs(task, hex_form)
    else:
        _link_mac_pxe_configs(task)
Пример #12
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:
            utils.mkfs("vfat", output_file)
            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)
Пример #13
0
    def activate_bootloader(self, context, node, instance):
        """Configure PXE boot loader for an instance

        Kernel and ramdisk images are downloaded by cache_tftp_images,
        and stored in /tftpboot/{uuid}/

        This method writes the instances config file, and then creates
        symlinks for each MAC address in the instance.

        By default, the complete layout looks like this:

        /tftpboot/
            ./{uuid}/
                 kernel
                 ramdisk
                 deploy_kernel
                 deploy_ramdisk
                 config
            ./pxelinux.cfg/
                 {mac} -> ../{uuid}/config
        """
        instance_type = self.virtapi.instance_type_get(
            context, instance['instance_type_id'])
        image_info = get_tftp_image_info(instance, instance_type)
        (root_mb, swap_mb) = get_partition_sizes(instance)
        pxe_config_file_path = get_pxe_config_file_path(instance)
        image_file_path = get_image_file_path(instance)

        deployment_key = utils.random_alnum(32)
        deployment_iscsi_iqn = "iqn-%s" % instance['uuid']
        db.bm_node_update(
            context, node['id'], {
                'deploy_key': deployment_key,
                'image_path': image_file_path,
                'pxe_config_path': pxe_config_file_path,
                'root_mb': root_mb,
                'swap_mb': swap_mb
            })
        pxe_config = build_pxe_config(
            node['id'],
            deployment_key,
            deployment_iscsi_iqn,
            image_info['deploy_kernel'][1],
            image_info['deploy_ramdisk'][1],
            image_info['kernel'][1],
            image_info['ramdisk'][1],
        )
        utils.write_to_file(pxe_config_file_path, pxe_config)

        macs = self._collect_mac_addresses(context, node)
        for mac in macs:
            mac_path = get_pxe_mac_path(mac)
            utils.unlink_without_raise(mac_path)
            utils.create_link_without_raise(pxe_config_file_path, mac_path)
Пример #14
0
def _create_token_file(task):
    """Save PKI token to file."""
    token_file_path = _get_token_file_path(task.node.uuid)
    token = task.context.auth_token
    if token:
        timeout = CONF.conductor.deploy_callback_timeout
        if timeout and keystone.token_expires_soon(token, timeout):
            token = keystone.get_admin_auth_token()
        utils.write_to_file(token_file_path, token)
    else:
        utils.unlink_without_raise(token_file_path)
Пример #15
0
def _create_token_file(task):
    """Save PKI token to file."""
    token_file_path = _get_token_file_path(task.node.uuid)
    token = task.context.auth_token
    if token:
        timeout = CONF.conductor.deploy_callback_timeout
        if timeout and keystone.token_expires_soon(token, timeout):
            token = keystone.get_admin_auth_token()
        utils.write_to_file(token_file_path, token)
    else:
        utils.unlink_without_raise(token_file_path)
Пример #16
0
def _prepare_floppy_image(task, params):
    """Prepares the floppy image for passing the parameters.

    This method prepares a temporary vfat filesystem image. Then it adds
    two files into the image - one containing the authentication token and
    the other containing the parameters to be passed to the ramdisk. Then it
    uploads the file to Swift in 'swift_ilo_container', setting it to
    auto-expire after 'swift_object_expiry_timeout' seconds. Then it returns
    the temp url for the Swift object.

    :param task: a TaskManager instance containing the node to act on.
    :param params: a dictionary containing 'parameter name'->'value' mapping
        to be passed to the deploy ramdisk via the floppy image.
    :raises: ImageCreationFailed, if it failed while creating the floppy image.
    :raises: SwiftOperationError, if any operation with Swift fails.
    :returns: the Swift temp url for the floppy image.
    """
    with tempfile.NamedTemporaryFile() as vfat_image_tmpfile_obj:

        files_info = {}
        token_tmpfile_obj = None
        vfat_image_tmpfile = vfat_image_tmpfile_obj.name

        # If auth_strategy is noauth, then no need to write token into
        # the image file.
        if task.context.auth_token:
            token_tmpfile_obj = tempfile.NamedTemporaryFile()
            token_tmpfile = token_tmpfile_obj.name
            utils.write_to_file(token_tmpfile, task.context.auth_token)
            files_info[token_tmpfile] = 'token'

        try:
            images.create_vfat_image(vfat_image_tmpfile, files_info=files_info,
                                     parameters=params)
        finally:
            if token_tmpfile_obj:
                token_tmpfile_obj.close()

        container = CONF.ilo.swift_ilo_container
        object_name = _get_floppy_image_name(task.node)
        timeout = CONF.ilo.swift_object_expiry_timeout

        object_headers = {'X-Delete-After': timeout}
        swift_api = swift.SwiftAPI()
        swift_api.create_object(container, object_name,
                                vfat_image_tmpfile,
                                object_headers=object_headers)
        temp_url = swift_api.get_temp_url(container, object_name, timeout)

        LOG.debug("Uploaded floppy image %(object_name)s to %(container)s "
                  "for deployment.",
                  {'object_name': object_name, 'container': container})
        return temp_url
Пример #17
0
    def activate_bootloader(self, context, node, instance):
        """Configure PXE boot loader for an instance

        Kernel and ramdisk images are downloaded by cache_tftp_images,
        and stored in /tftpboot/{uuid}/

        This method writes the instances config file, and then creates
        symlinks for each MAC address in the instance.

        By default, the complete layout looks like this:

        /tftpboot/
            ./{uuid}/
                 kernel
                 ramdisk
                 deploy_kernel
                 deploy_ramdisk
                 config
            ./pxelinux.cfg/
                 {mac} -> ../{uuid}/config
        """
        instance_type = self.virtapi.instance_type_get(
            context, instance['instance_type_id'])
        image_info = get_tftp_image_info(instance, instance_type)
        (root_mb, swap_mb) = get_partition_sizes(instance)
        pxe_config_file_path = get_pxe_config_file_path(instance)
        image_file_path = get_image_file_path(instance)

        deployment_key = utils.random_alnum(32)
        deployment_iscsi_iqn = "iqn-%s" % instance['uuid']
        db.bm_node_update(context, node['id'],
                {'deploy_key': deployment_key,
                 'image_path': image_file_path,
                 'pxe_config_path': pxe_config_file_path,
                 'root_mb': root_mb,
                 'swap_mb': swap_mb})
        pxe_config = build_pxe_config(
                    node['id'],
                    deployment_key,
                    deployment_iscsi_iqn,
                    image_info['deploy_kernel'][1],
                    image_info['deploy_ramdisk'][1],
                    image_info['kernel'][1],
                    image_info['ramdisk'][1],
                )
        utils.write_to_file(pxe_config_file_path, pxe_config)

        macs = self._collect_mac_addresses(context, node)
        for mac in macs:
            mac_path = get_pxe_mac_path(mac)
            utils.unlink_without_raise(mac_path)
            utils.create_link_without_raise(pxe_config_file_path, mac_path)
Пример #18
0
def create_ipxe_boot_script():
    """Render the iPXE boot script into the HTTP root directory"""
    boot_script = utils.render_template(
        CONF.pxe.ipxe_boot_script,
        {'ipxe_for_mac_uri': PXE_CFG_DIR_NAME + '/'})
    bootfile_path = os.path.join(CONF.deploy.http_root,
                                 os.path.basename(CONF.pxe.ipxe_boot_script))
    # NOTE(pas-ha) to prevent unneeded writes,
    # only write to file if its content is different from required,
    # which should be rather rare
    if (not os.path.isfile(bootfile_path)
            or not utils.file_has_content(bootfile_path, boot_script)):
        utils.write_to_file(bootfile_path, boot_script)
Пример #19
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)
Пример #20
0
def _create_pxe_config(task, pxe_info):
    """Generate pxe configuration file and link mac ports to it for
    tftp booting.
    """
    fileutils.ensure_tree(os.path.join(CONF.pxe.tftp_root, task.node.uuid))
    fileutils.ensure_tree(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg'))

    pxe_config_file_path = _get_pxe_config_file_path(task.node.uuid)
    pxe_config = _build_pxe_config(task.node, pxe_info, task.context)
    utils.write_to_file(pxe_config_file_path, pxe_config)
    for port in driver_utils.get_node_mac_addresses(task):
        mac_path = _get_pxe_mac_path(port)
        utils.unlink_without_raise(mac_path)
        utils.create_link_without_raise(pxe_config_file_path, mac_path)
Пример #21
0
def create_ipxe_boot_script():
    """Render the iPXE boot script into the HTTP root directory"""
    boot_script = utils.render_template(
        CONF.pxe.ipxe_boot_script,
        {'ipxe_for_mac_uri': PXE_CFG_DIR_NAME + '/'})
    bootfile_path = os.path.join(
        CONF.deploy.http_root,
        os.path.basename(CONF.pxe.ipxe_boot_script))
    # NOTE(pas-ha) to prevent unneeded writes,
    # only write to file if its content is different from required,
    # which should be rather rare
    if (not os.path.isfile(bootfile_path)
            or not utils.file_has_content(bootfile_path, boot_script)):
        utils.write_to_file(bootfile_path, boot_script)
Пример #22
0
def _create_pxe_config(task, node, pxe_info):
    """Generate pxe configuration file and link mac ports to it for
    tftp booting.
    """
    fileutils.ensure_tree(os.path.join(CONF.pxe.tftp_root,
                                       node.uuid))
    fileutils.ensure_tree(os.path.join(CONF.pxe.tftp_root,
                                       'pxelinux.cfg'))

    pxe_config_file_path = _get_pxe_config_file_path(node.uuid)
    pxe_config = _build_pxe_config(node, pxe_info, task.context)
    utils.write_to_file(pxe_config_file_path, pxe_config)
    for port in driver_utils.get_node_mac_addresses(task, node):
        mac_path = _get_pxe_mac_path(port)
        utils.unlink_without_raise(mac_path)
        utils.create_link_without_raise(pxe_config_file_path, mac_path)
Пример #23
0
def create_isolinux_image(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'

    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_isolinux_cfg(kernel_params)

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

        try:
            utils.execute('mkisofs', '-r', '-V', "BOOT IMAGE",
                          '-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)
Пример #24
0
    def _create_pxe_config(self, task):
        pxe_options = self._build_pxe_options(task.node)

        pxe_config_template = CONF.pxe.pxe_config_template
        node_uuid = task.node.uuid
        root_dir = CONF.pxe.tftp_root
        fileutils.ensure_tree(os.path.join(root_dir, node_uuid))
        fileutils.ensure_tree(os.path.join(root_dir, PXE_CFG_DIR_NAME))

        pxe_config_file_path = pxe_utils.get_pxe_config_file_path(node_uuid)
        tmpl_path, tmpl_file = os.path.split(pxe_config_template)
        env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path))
        template = env.get_template(tmpl_file)
        pxe_config = template.render({
            'pxe_options': pxe_options,
            'server_ip': CONF.my_ip,
            'UUID': node_uuid,
        })
        utils.write_to_file(pxe_config_file_path, pxe_config)
        self._link_mac_pxe_configs(task)
Пример #25
0
def create_pxe_config(task, pxe_options, template=None, ipxe_enabled=False):
    """Generate PXE configuration file and MAC address links for it.

    This method will generate the PXE configuration file for the task's
    node under a directory named with the UUID of that node. For each
    MAC address or DHCP IP address (port) of that node, a symlink for
    the configuration file will be created under the PXE configuration
    directory, so regardless of which port boots first they'll get the
    same PXE configuration.
    If grub2 bootloader is in use, then its configuration will be created
    based on DHCP IP address in the form nn.nn.nn.nn.

    :param task: A TaskManager instance.
    :param pxe_options: A dictionary with the PXE configuration
        parameters.
    :param template: The PXE configuration template. If no template is
        given the node specific template will be used.

    """
    LOG.debug("Building PXE config for node %s", task.node.uuid)
    if template is None:
        template = deploy_utils.get_pxe_config_template(task.node)

    _ensure_config_dirs_exist(task, ipxe_enabled)

    pxe_config_file_path = get_pxe_config_file_path(task.node.uuid,
                                                    ipxe_enabled=ipxe_enabled)
    is_uefi_boot_mode = (boot_mode_utils.get_boot_mode(task.node) == 'uefi')
    uefi_with_grub = is_uefi_boot_mode and not ipxe_enabled

    # grub bootloader panics with '{}' around any of its tags in its
    # config file. To overcome that 'ROOT' and 'DISK_IDENTIFIER' are enclosed
    # with '(' and ')' in uefi boot mode.
    if uefi_with_grub:
        pxe_config_root_tag = '(( ROOT ))'
        pxe_config_disk_ident = '(( DISK_IDENTIFIER ))'
    else:
        # TODO(stendulker): We should use '(' ')' as the delimiters for all our
        # config files so that we do not need special handling for each of the
        # bootloaders. Should be removed once the Mitaka release starts.
        pxe_config_root_tag = '{{ ROOT }}'
        pxe_config_disk_ident = '{{ DISK_IDENTIFIER }}'

    params = {
        'pxe_options': pxe_options,
        'ROOT': pxe_config_root_tag,
        'DISK_IDENTIFIER': pxe_config_disk_ident
    }

    pxe_config = utils.render_template(template, params)
    utils.write_to_file(pxe_config_file_path, pxe_config)

    # Always write the mac addresses
    _link_mac_pxe_configs(task, ipxe_enabled=ipxe_enabled)
    if uefi_with_grub:
        try:
            _link_ip_address_pxe_configs(task, ipxe_enabled)
        # NOTE(TheJulia): The IP address support will fail if the
        # dhcp_provider interface is set to none. This will result
        # in the MAC addresses and DHCP files being written, and
        # we can remove IP address creation for the grub use.
        except exception.FailedToGetIPAddressOnPort as e:
            if CONF.dhcp.dhcp_provider != 'none':
                with excutils.save_and_reraise_exception():
                    LOG.error(
                        'Unable to create boot config, IP address '
                        'was unable to be retrieved. %(error)s', {'error': e})
Пример #26
0
    def prepare_ramdisk(self, task, ramdisk_params):
        """Prepares the boot of Ironic ramdisk using PXE.

        This method prepares the boot of the deploy kernel/ramdisk after
        reading relevant information from the node's driver_info and
        instance_info.

        :param task: a task from TaskManager.
        :param ramdisk_params: the parameters to be passed to the ramdisk.
            pxe driver passes these parameters as kernel command-line
            arguments.
        :returns: None
        :raises: MissingParameterValue, if some information is missing in
            node's driver_info or instance_info.
        :raises: InvalidParameterValue, if some information provided is
            invalid.
        :raises: IronicException, if some power or set boot boot device
            operation failed on the node.
        """
        node = task.node

        if CONF.pxe.ipxe_enabled:
            # Render the iPXE boot script template and save it
            # to HTTP root directory
            boot_script = utils.render_template(
                CONF.pxe.ipxe_boot_script,
                {'ipxe_for_mac_uri': pxe_utils.PXE_CFG_DIR_NAME + '/'})
            bootfile_path = os.path.join(
                CONF.deploy.http_root,
                os.path.basename(CONF.pxe.ipxe_boot_script))
            # NOTE(pas-ha) to prevent unneeded writes,
            # only write to file if its content is different from required,
            # which should be rather rare
            if (not os.path.isfile(bootfile_path) or
                not utils.file_has_content(bootfile_path, boot_script)):
                    utils.write_to_file(bootfile_path, boot_script)

        dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
        provider = dhcp_factory.DHCPFactory()
        provider.update_dhcp(task, dhcp_opts)

        pxe_info = _get_deploy_image_info(node)

        # NODE: Try to validate and fetch instance images only
        # if we are in DEPLOYING state.
        if node.provision_state == states.DEPLOYING:
            pxe_info.update(_get_instance_image_info(node, task.context))

        pxe_options = _build_pxe_config_options(task, pxe_info)
        pxe_options.update(ramdisk_params)

        pxe_config_template = deploy_utils.get_pxe_config_template(node)

        pxe_utils.create_pxe_config(task, pxe_options,
                                    pxe_config_template)
        deploy_utils.try_set_boot_device(task, boot_devices.PXE)

        if CONF.pxe.ipxe_enabled and CONF.pxe.ipxe_use_swift:
            pxe_info.pop('deploy_kernel', None)
            pxe_info.pop('deploy_ramdisk', None)
        if pxe_info:
            _cache_ramdisk_kernel(task.context, node, pxe_info)
Пример #27
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
                }

            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)
Пример #28
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'
    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,
        }

        # 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 (OSError, IOError) 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', "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("Creating ISO image failed.")
            raise exception.ImageCreationFailed(image_type='iso', error=e)
Пример #29
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)
Пример #30
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)
Пример #31
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)
Пример #32
0
def create_pxe_config(task, pxe_options, template=None, ipxe_enabled=False):
    """Generate PXE configuration file and MAC address links for it.

    This method will generate the PXE configuration file for the task's
    node under a directory named with the UUID of that node. For each
    MAC address or DHCP IP address (port) of that node, a symlink for
    the configuration file will be created under the PXE configuration
    directory, so regardless of which port boots first they'll get the
    same PXE configuration.
    If elilo is the bootloader in use, then its configuration file will
    be created based on hex form of DHCP IP address.
    If grub2 bootloader is in use, then its configuration will be created
    based on DHCP IP address in the form nn.nn.nn.nn.

    :param task: A TaskManager instance.
    :param pxe_options: A dictionary with the PXE configuration
        parameters.
    :param template: The PXE configuration template. If no template is
        given the node specific template will be used.

    """
    LOG.debug("Building PXE config for node %s", task.node.uuid)
    if template is None:
        template = deploy_utils.get_pxe_config_template(task.node)

    _ensure_config_dirs_exist(task, ipxe_enabled)

    pxe_config_file_path = get_pxe_config_file_path(
        task.node.uuid,
        ipxe_enabled=ipxe_enabled)
    is_uefi_boot_mode = (boot_mode_utils.get_boot_mode(task.node)
                         == 'uefi')

    # grub bootloader panics with '{}' around any of its tags in its
    # config file. To overcome that 'ROOT' and 'DISK_IDENTIFIER' are enclosed
    # with '(' and ')' in uefi boot mode.
    # These changes do not have any impact on elilo bootloader.
    hex_form = True
    if is_uefi_boot_mode and utils.is_regex_string_in_file(template,
                                                           '^menuentry'):
        hex_form = False
        pxe_config_root_tag = '(( ROOT ))'
        pxe_config_disk_ident = '(( DISK_IDENTIFIER ))'
        LOG.warning("The requested config appears to support elilo. "
                    "Support for elilo has been deprecated and will be "
                    "removed in the Queens release of OpenStack.")
    else:
        # TODO(stendulker): We should use '(' ')' as the delimiters for all our
        # config files so that we do not need special handling for each of the
        # bootloaders. Should be removed once the Mitaka release starts.
        pxe_config_root_tag = '{{ ROOT }}'
        pxe_config_disk_ident = '{{ DISK_IDENTIFIER }}'

    params = {'pxe_options': pxe_options,
              'ROOT': pxe_config_root_tag,
              'DISK_IDENTIFIER': pxe_config_disk_ident}

    pxe_config = utils.render_template(template, params)
    utils.write_to_file(pxe_config_file_path, pxe_config)

    # Always write the mac addresses
    _link_mac_pxe_configs(task, ipxe_enabled=ipxe_enabled)
    if is_uefi_boot_mode and not ipxe_enabled:
        try:
            _link_ip_address_pxe_configs(task, hex_form, ipxe_enabled)
        # NOTE(TheJulia): The IP address support will fail if the
        # dhcp_provider interface is set to none. This will result
        # in the MAC addresses and DHCP files being written, and
        # we can remove IP address creation for the grub use
        # case, considering that will ease removal of elilo support.
        except exception.FailedToGetIPaddressesOnPort as e:
            if CONF.dhcp.dhcp_provider != 'none':
                with excutils.save_and_reraise_exception():
                    LOG.error('Unable to create boot config, IP address '
                              'was unable to be retrieved. %(error)s',
                              {'error': e})
Пример #33
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(_LE("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(_LE("Creating ISO image failed."))
            raise exception.ImageCreationFailed(image_type='iso', error=e)