コード例 #1
0
    def post_init(self, custom_args):
        self.custom_args = custom_args
        arch = platform.machine()
        if 's390' in arch:
            self.arch = arch
        else:
            raise KiwiBootLoaderZiplPlatformError(
                'host architecture %s not supported for zipl setup' % arch)

        if not custom_args or 'targetbase' not in custom_args:
            raise KiwiBootLoaderZiplSetupError(
                'targetbase device name is required for zipl setup')

        self.bootpath = '.'
        self.timeout = self.get_boot_timeout_seconds()
        self.cmdline = self.get_boot_cmdline()
        self.cmdline_failsafe = ' '.join(
            [self.cmdline, self.get_failsafe_kernel_options()])
        self.target_blocksize = self.xml_state.build_type.get_target_blocksize(
        )
        self.target_type = self.xml_state.build_type.get_zipl_targettype()
        self.failsafe_boot = self.failsafe_boot_entry_requested()
        self.target_device = custom_args['targetbase']
        self.firmware = FirmWare(self.xml_state)
        self.target_table_type = self.firmware.get_partition_table_type()

        self.zipl = BootLoaderTemplateZipl()
        self.config = None
コード例 #2
0
    def __init__(self, xml_state, target_dir, root_dir):
        self.media_dir = None
        self.arch = platform.machine()
        self.root_dir = root_dir
        self.target_dir = target_dir
        self.xml_state = xml_state
        self.live_type = xml_state.build_type.get_flags()
        self.types = Defaults.get_live_iso_types()
        self.hybrid = xml_state.build_type.get_hybrid()
        self.volume_id = xml_state.build_type.get_volid()
        self.machine = xml_state.get_build_type_machine_section()
        self.mbrid = ImageIdentifier()
        self.mbrid.calculate_id()

        if not self.live_type:
            self.live_type = Defaults.get_default_live_iso_type()

        self.boot_image_task = BootImageTask('kiwi', xml_state, target_dir)
        self.firmware = FirmWare(xml_state)
        self.system_setup = SystemSetup(xml_state=xml_state,
                                        description_dir=None,
                                        root_dir=self.root_dir)
        self.isoname = ''.join([
            target_dir, '/',
            xml_state.xml_data.get_name(), '.' + platform.machine(),
            '-' + xml_state.get_image_version(), '.iso'
        ])
        self.live_image_file = ''.join([
            target_dir, '/',
            xml_state.xml_data.get_name(), '-read-only.', self.arch, '-',
            xml_state.get_image_version()
        ])
        self.result = Result()
コード例 #3
0
ファイル: bootloader_config_zipl.py プロジェクト: k0da/kiwi-1
    def post_init(self, custom_args):
        self.custom_args = custom_args
        arch = platform.machine()
        if 's390' in arch:
            self.arch = arch
        else:
            raise KiwiBootLoaderZiplPlatformError(
                'host architecture %s not supported for zipl setup' % arch
            )

        if not custom_args or 'targetbase' not in custom_args:
            raise KiwiBootLoaderZiplSetupError(
                'targetbase device name is required for zipl setup'
            )

        self.bootpath = '.'
        self.timeout = self.get_boot_timeout_seconds()
        self.cmdline = self.get_boot_cmdline()
        self.cmdline_failsafe = ' '.join(
            [self.cmdline, self.get_failsafe_kernel_options()]
        )
        self.target_blocksize = self.xml_state.build_type.get_target_blocksize()
        self.target_type = self.xml_state.build_type.get_zipl_targettype()
        self.failsafe_boot = self.failsafe_boot_entry_requested()
        self.target_device = custom_args['targetbase']
        self.firmware = FirmWare(self.xml_state)
        self.target_table_type = self.firmware.get_partition_table_type()

        self.zipl = BootLoaderTemplateZipl()
        self.config = None
コード例 #4
0
    def __init__(self, xml_state, root_dir):
        self.configured_size = xml_state.get_build_type_size()
        self.build_type_name = xml_state.get_build_type_name()
        self.filesystem = xml_state.build_type.get_filesystem()
        self.bootpart_requested = xml_state.build_type.get_bootpartition()
        self.bootpart_mbytes = xml_state.build_type.get_bootpartsize()
        self.mdraid = xml_state.build_type.get_mdraid()
        self.luks = xml_state.build_type.get_luks()
        self.volume_manager = xml_state.get_volume_management()
        self.bootloader = xml_state.build_type.get_bootloader()
        self.oemconfig = xml_state.get_build_type_oemconfig_section()
        self.volumes = xml_state.get_volumes()

        self.firmware = FirmWare(xml_state)
        self.rootsize = SystemSize(root_dir)

        self.root_dir = root_dir
        self.xml_state = xml_state
コード例 #5
0
    def post_init(self, custom_args):
        self.custom_args = custom_args
        arch = platform.machine()
        if arch == 'x86_64':
            self.arch = arch
        else:
            raise KiwiBootLoaderGrubPlatformError(
                'host architecture %s not supported for grub2 setup' % arch)

        self.terminal = 'gfxterm'
        self.bootpath = self.get_boot_path()
        self.gfxmode = self.__get_gfxmode()
        self.theme = self.get_boot_theme()
        self.timeout = self.get_boot_timeout_seconds()
        self.failsafe_boot = self.failsafe_boot_entry_requested()
        self.hypervisor_domain = self.get_hypervisor_domain()
        self.firmware = FirmWare(self.xml_state)

        self.hybrid_boot = True
        self.multiboot = False
        if self.hypervisor_domain:
            if self.hypervisor_domain == 'dom0':
                self.hybrid_boot = False
                self.multiboot = True
            elif self.hypervisor_domain == 'domU':
                self.hybrid_boot = False
                self.multiboot = False

        self.xen_guest = False
        if self.hypervisor_domain == 'domU' or self.firmware.ec2_mode():
            self.xen_guest = True

        self.grub2 = BootLoaderTemplateGrub2()
        self.config = None
        self.efi_boot_path = None
        self.boot_directory_name = 'grub2'
コード例 #6
0
ファイル: live_image_builder.py プロジェクト: k0da/kiwi-1
    def __init__(self, xml_state, target_dir, root_dir):
        self.media_dir = None
        self.arch = platform.machine()
        self.root_dir = root_dir
        self.target_dir = target_dir
        self.xml_state = xml_state
        self.live_type = xml_state.build_type.get_flags()
        self.types = Defaults.get_live_iso_types()
        self.hybrid = xml_state.build_type.get_hybrid()
        self.volume_id = xml_state.build_type.get_volid()
        self.machine = xml_state.get_build_type_machine_section()
        self.mbrid = ImageIdentifier()
        self.mbrid.calculate_id()

        if not self.live_type:
            self.live_type = Defaults.get_default_live_iso_type()

        self.boot_image_task = BootImageTask(
            'kiwi', xml_state, target_dir
        )
        self.firmware = FirmWare(
            xml_state
        )
        self.system_setup = SystemSetup(
            xml_state=xml_state, description_dir=None, root_dir=self.root_dir
        )
        self.isoname = ''.join(
            [
                target_dir, '/',
                xml_state.xml_data.get_name(),
                '.' + platform.machine(),
                '-' + xml_state.get_image_version(),
                '.iso'
            ]
        )
        self.live_image_file = ''.join(
            [
                target_dir, '/',
                xml_state.xml_data.get_name(),
                '-read-only.', self.arch, '-',
                xml_state.get_image_version()
            ]
        )
        self.result = Result()
コード例 #7
0
ファイル: disk_setup.py プロジェクト: k0da/kiwi-1
    def __init__(self, xml_state, root_dir):
        self.configured_size = xml_state.get_build_type_size()
        self.build_type_name = xml_state.get_build_type_name()
        self.filesystem = xml_state.build_type.get_filesystem()
        self.bootpart_requested = xml_state.build_type.get_bootpartition()
        self.bootpart_mbytes = xml_state.build_type.get_bootpartsize()
        self.mdraid = xml_state.build_type.get_mdraid()
        self.luks = xml_state.build_type.get_luks()
        self.volume_manager = xml_state.get_volume_management()
        self.bootloader = xml_state.build_type.get_bootloader()
        self.oemconfig = xml_state.get_build_type_oemconfig_section()
        self.volumes = xml_state.get_volumes()

        self.firmware = FirmWare(
            xml_state
        )
        self.rootsize = SystemSize(
            root_dir
        )

        self.root_dir = root_dir
        self.xml_state = xml_state
コード例 #8
0
    def post_init(self, custom_args):
        self.custom_args = custom_args
        arch = platform.machine()
        if arch == 'x86_64':
            self.arch = arch
        else:
            raise KiwiBootLoaderGrubPlatformError(
                'host architecture %s not supported for grub2 setup' % arch
            )

        self.terminal = 'gfxterm'
        self.bootpath = self.get_boot_path()
        self.gfxmode = self.__get_gfxmode()
        self.theme = self.get_boot_theme()
        self.timeout = self.get_boot_timeout_seconds()
        self.failsafe_boot = self.failsafe_boot_entry_requested()
        self.hypervisor_domain = self.get_hypervisor_domain()
        self.firmware = FirmWare(
            self.xml_state
        )

        self.hybrid_boot = True
        self.multiboot = False
        if self.hypervisor_domain:
            if self.hypervisor_domain == 'dom0':
                self.hybrid_boot = False
                self.multiboot = True
            elif self.hypervisor_domain == 'domU':
                self.hybrid_boot = False
                self.multiboot = False

        self.xen_guest = False
        if self.hypervisor_domain == 'domU' or self.firmware.ec2_mode():
            self.xen_guest = True

        self.grub2 = BootLoaderTemplateGrub2()
        self.config = None
        self.efi_boot_path = None
        self.boot_directory_name = 'grub2'
コード例 #9
0
ファイル: bootloader_config_zipl.py プロジェクト: k0da/kiwi-1
class BootLoaderConfigZipl(BootLoaderConfigBase):
    """
        zipl bootloader configuration.
    """
    def post_init(self, custom_args):
        self.custom_args = custom_args
        arch = platform.machine()
        if 's390' in arch:
            self.arch = arch
        else:
            raise KiwiBootLoaderZiplPlatformError(
                'host architecture %s not supported for zipl setup' % arch
            )

        if not custom_args or 'targetbase' not in custom_args:
            raise KiwiBootLoaderZiplSetupError(
                'targetbase device name is required for zipl setup'
            )

        self.bootpath = '.'
        self.timeout = self.get_boot_timeout_seconds()
        self.cmdline = self.get_boot_cmdline()
        self.cmdline_failsafe = ' '.join(
            [self.cmdline, self.get_failsafe_kernel_options()]
        )
        self.target_blocksize = self.xml_state.build_type.get_target_blocksize()
        self.target_type = self.xml_state.build_type.get_zipl_targettype()
        self.failsafe_boot = self.failsafe_boot_entry_requested()
        self.target_device = custom_args['targetbase']
        self.firmware = FirmWare(self.xml_state)
        self.target_table_type = self.firmware.get_partition_table_type()

        self.zipl = BootLoaderTemplateZipl()
        self.config = None

    def write(self):
        """
            Write zipl config file
        """
        log.info('Writing zipl config file')
        config_dir = self.__get_zipl_boot_path()
        config_file = config_dir + '/config'
        if self.config:
            Path.create(config_dir)
            with open(config_file, 'w') as config:
                config.write(self.config)

            log.info('Moving initrd/kernel to zipl boot directory')
            Command.run(
                [
                    'mv',
                    self.root_dir + '/boot/initrd.vmx',
                    self.root_dir + '/boot/linux.vmx',
                    self.__get_zipl_boot_path()
                ]
            )

    def setup_disk_image_config(
        self, uuid=None, hypervisor=None,
        kernel='linux.vmx', initrd='initrd.vmx'
    ):
        """
            Create the zipl config in memory from a template suitable to
            boot from a disk image
        """
        log.info('Creating zipl config file from template')
        parameters = {
            'device': self.target_device,
            'target_type': self.target_type,
            'blocksize': self.target_blocksize,
            'offset': self.__get_target_offset(),
            'geometry': self.__get_target_geometry(),
            'default_boot': '1',
            'bootpath': self.bootpath,
            'boot_timeout': self.timeout,
            'title': self.quote_title(self.get_menu_entry_title()),
            'kernel_file': kernel,
            'initrd_file': initrd,
            'boot_options': self.cmdline,
            'failsafe_boot_options': self.cmdline_failsafe
        }
        log.info('--> Using standard disk boot template')
        template = self.zipl.get_template(self.failsafe_boot)
        try:
            self.config = template.substitute(parameters)
        except Exception as e:
            raise KiwiTemplateError(
                '%s: %s' % (type(e).__name__, format(e))
            )

    def setup_disk_boot_images(self, boot_uuid, lookup_path=None):
        # on s390 no bootloader images needs to be created
        pass

    def __get_zipl_boot_path(self):
        return self.root_dir + '/boot/zipl'

    def __get_target_geometry(self):
        if self.target_table_type == 'dasd':
            return '%d,%d,%d' % (
                self.__read_dasd_disk_geometry('cylinders'),
                self.__read_dasd_disk_geometry('tracks per cylinder'),
                self.__read_dasd_disk_geometry('blocks per track')
            )
        else:
            return '%d,%d,%d' % (
                self.__read_msdos_disk_geometry('cylinders'),
                self.__read_msdos_disk_geometry('tracks per cylinder'),
                self.__read_msdos_disk_geometry('blocks per track')
            )

    def __get_target_offset(self):
        if self.target_table_type == 'dasd':
            blocks = self.__read_dasd_disk_geometry('blocks per track')
            bash_command = [
                'fdasd', '-f', '-s', '-p', self.target_device,
                '|', 'head', '-n', '1', '|', 'tr', '-s', '" "'
            ]
            fdasd_call = Command.run(
                ['bash', '-c', ' '.join(bash_command)]
            )
            fdasd_output = fdasd_call.output
            try:
                start_track = int(fdasd_output.split(' ')[2].lstrip())
            except Exception as e:
                raise KiwiDiskGeometryError(
                    'unknown partition format: %s' % fdasd_output
                )
            return start_track * blocks
        else:
            blocks = self.__read_msdos_disk_geometry('blocks per track')
            parted_call = Command.run(
                ['parted', '-m', self.target_device, 'unit', 's', 'print']
            )
            parted_output = parted_call.output.lstrip()
            first_partition_format = re.search('1:(.*?)s', parted_output)
            if not first_partition_format:
                raise KiwiDiskGeometryError(
                    'unknown partition format: %s' % parted_output
                )
            start_track = int(first_partition_format.group(1))
            return start_track * blocks

    def __read_msdos_disk_geometry(self, value):
        sfdisk_call = Command.run(
            ['sfdisk', '-g', self.target_device]
        )
        sfdisk_output = sfdisk_call.output.lstrip()
        geometry_format = re.search(
            '/dev.*: (.*) cylinders, (.*) heads, (.*) sectors/track',
            sfdisk_output
        )
        if not geometry_format:
            raise KiwiDiskGeometryError(
                'unknown format for geometry: %s' % sfdisk_output
            )
        result = {
            'cylinders': geometry_format.group(1),
            'tracks per cylinder': geometry_format.group(2),
            'blocks per track': geometry_format.group(3)
        }
        if value in result:
            return int(result[value])

    def __read_dasd_disk_geometry(self, value):
        fdasd = ['fdasd', '-f', '-p', self.target_device]
        bash_command = fdasd + ['|', 'grep', '"' + value + '"']
        fdasd_call = Command.run(
            ['bash', '-c', ' '.join(bash_command)]
        )
        fdasd_output = fdasd_call.output
        try:
            return int(fdasd_output.split(':')[1].lstrip())
        except Exception as e:
            raise KiwiDiskGeometryError(
                'unknown format for disk geometry: %s' % fdasd_output
            )
コード例 #10
0
class DiskSetup(object):
    """
        Implement disk setup methods providing information required
        before building a disk image
    """
    def __init__(self, xml_state, root_dir):
        self.configured_size = xml_state.get_build_type_size()
        self.build_type_name = xml_state.get_build_type_name()
        self.filesystem = xml_state.build_type.get_filesystem()
        self.bootpart_requested = xml_state.build_type.get_bootpartition()
        self.bootpart_mbytes = xml_state.build_type.get_bootpartsize()
        self.mdraid = xml_state.build_type.get_mdraid()
        self.luks = xml_state.build_type.get_luks()
        self.volume_manager = xml_state.get_volume_management()
        self.bootloader = xml_state.build_type.get_bootloader()
        self.oemconfig = xml_state.get_build_type_oemconfig_section()
        self.volumes = xml_state.get_volumes()

        self.firmware = FirmWare(xml_state)
        self.rootsize = SystemSize(root_dir)

        self.root_dir = root_dir
        self.xml_state = xml_state

    def get_disksize_mbytes(self):
        log.info('Precalculating required disk size')
        calculated_disk_mbytes = 0
        root_filesystem_mbytes = self.rootsize.customize(
            self.rootsize.accumulate_mbyte_file_sizes(), self.filesystem)
        calculated_disk_mbytes += root_filesystem_mbytes
        log.info('--> system data with filesystem overhead needs %s MB',
                 root_filesystem_mbytes)
        if self.volume_manager and self.volume_manager == 'lvm':
            if self.build_type_name == 'vmx':
                # only for vmx types we need to add the configured volume
                # sizes. oem disks are self expandable and will resize to
                # the configured sizes on first boot of the disk image
                volume_mbytes = self.__accumulate_volume_size(
                    root_filesystem_mbytes)
                if volume_mbytes:
                    calculated_disk_mbytes += volume_mbytes
                    log.info('--> volume(s) size setup adding %s MB',
                             volume_mbytes)

        legacy_bios_mbytes = self.firmware.get_legacy_bios_partition_size()
        if legacy_bios_mbytes:
            calculated_disk_mbytes += legacy_bios_mbytes
            log.info('--> legacy bios boot partition adding %s MB',
                     legacy_bios_mbytes)

        boot_mbytes = self.boot_partition_size()
        if boot_mbytes:
            calculated_disk_mbytes += boot_mbytes
            log.info('--> boot partition adding %s MB', boot_mbytes)

        efi_mbytes = self.firmware.get_efi_partition_size()
        if efi_mbytes:
            calculated_disk_mbytes += efi_mbytes
            log.info('--> EFI partition adding %s MB', efi_mbytes)

        recovery_mbytes = self.__inplace_recovery_partition_size()
        if recovery_mbytes:
            calculated_disk_mbytes += recovery_mbytes
            log.info('--> In-place recovery partition adding: %s MB',
                     recovery_mbytes)

        if self.configured_size and self.build_type_name == 'oem':
            log.warning(
                'Fixed disk size setup not used for expandable oem image')
            self.configured_size = None

        if not self.configured_size:
            log.info('Using calculated disk size: %d MB',
                     calculated_disk_mbytes)
            return calculated_disk_mbytes
        elif self.configured_size.additive:
            result_disk_mbytes = \
                self.configured_size.mbytes + calculated_disk_mbytes
            log.info(
                'Using configured disk size: %d MB + %d MB calculated = %d MB',
                self.configured_size.mbytes, calculated_disk_mbytes,
                result_disk_mbytes)
            return result_disk_mbytes
        else:
            log.info('Using configured disk size: %d MB',
                     self.configured_size.mbytes)
            if self.configured_size.mbytes < calculated_disk_mbytes:
                log.warning(
                    '--> Configured size smaller than calculated size: %d MB',
                    calculated_disk_mbytes)
            return self.configured_size.mbytes

    def need_boot_partition(self):
        """
            Decide if an extra boot partition is needed. This is done with
            the bootpartition attribute from the type, however if it is not
            set it depends on some other type configuration parameters if
            we need a boot partition or not
        """
        if self.bootpart_requested is True:
            return True
        if self.bootpart_requested is False:
            return False
        if self.mdraid:
            return True
        if self.volume_manager:
            return True
        if self.filesystem == 'btrfs':
            return True
        if self.filesystem == 'xfs':
            return True
        if self.bootloader == 'grub2_s390x_emu':
            return True
        if self.luks:
            return True

    def get_boot_label(self):
        label = 'BOOT'
        if self.bootloader == 'grub2_s390x_emu':
            label = 'ZIPL'
        return label

    def get_root_label(self):
        return 'ROOT'

    def get_efi_label(self):
        return 'EFI'

    def boot_partition_size(self):
        if self.need_boot_partition():
            if self.bootpart_mbytes:
                return self.bootpart_mbytes
            else:
                return Defaults.get_default_boot_mbytes()

    def __inplace_recovery_partition_size(self):
        """
            in inplace recovery mode the recovery archive is created at
            install time. This requires free space on the disk. The
            amount of free space is specified with the oem-recovery-part-size
            attribute. If specified we add the given size to the disk.
            If not specified an inplace setup at install time will be
            moved to the first boot of an oem image when the recovery
            partition has been created
        """
        if self.oemconfig and self.oemconfig.get_oem_inplace_recovery():
            recovery_mbytes = self.oemconfig.get_oem_recovery_part_size()
            if recovery_mbytes:
                return int(recovery_mbytes[0] * 1.7)

    def __accumulate_volume_size(self, root_mbytes):
        """
            calculate number of mbytes to add to the disk to allow
            the creaton of the volumes with their configured size
        """
        disk_volume_mbytes = 0

        data_volume_mbytes = self.__calculate_volume_mbytes()
        root_volume = self.__get_root_volume_configuration()

        for volume in self.volumes:
            if volume.realpath and not volume.realpath == '/' and volume.size:
                [size_type, req_size] = volume.size.split(':')
                disk_add_mbytes = 0
                if size_type == 'freespace':
                    disk_add_mbytes += int(req_size) + \
                        Defaults.get_min_volume_mbytes()
                else:
                    disk_add_mbytes += int(req_size) - \
                        data_volume_mbytes.volume[volume.realpath]
                if disk_add_mbytes > 0:
                    disk_volume_mbytes += disk_add_mbytes
                else:
                    log.warning(
                        'volume size of %s MB for %s is too small, skipped',
                        int(req_size), volume.realpath)

        if root_volume:
            if root_volume.size_type == 'freespace':
                disk_add_mbytes += root_volume.req_size + \
                    Defaults.get_min_volume_mbytes()
            else:
                disk_add_mbytes = root_volume.req_size - \
                    root_mbytes + data_volume_mbytes.total

            if disk_add_mbytes > 0:
                disk_volume_mbytes += disk_add_mbytes
            else:
                log.warning('root volume size of %s MB is too small, skipped',
                            root_volume.req_size)

        return disk_volume_mbytes

    def __get_root_volume_configuration(self):
        """
            provide LVRoot volume configuration if present and in
            use according to the selected volume management. So far
            this only affects the LVM volume manager
        """
        root_volume_type = namedtuple('root_volume_type',
                                      ['size_type', 'req_size'])
        for volume in self.volumes:
            if volume.name == 'LVRoot':
                if volume.size:
                    [size_type, req_size] = volume.size.split(':')
                    return root_volume_type(size_type=size_type,
                                            req_size=int(req_size))

    def __calculate_volume_mbytes(self):
        """
            calculate the number of mbytes each volume path currently
            consumes and also provide a total number of these values
        """
        volume_mbytes_type = namedtuple('volume_mbytes_type',
                                        ['volume', 'total'])
        volume_mbytes = {}
        volume_total = 0
        for volume in self.volumes:
            if volume.realpath and not volume.realpath == '/':
                path_to_volume = self.root_dir + '/' + volume.realpath
                if os.path.exists(path_to_volume):
                    volume_size = SystemSize(path_to_volume)
                    volume_mbytes[volume.realpath] = volume_size.customize(
                        volume_size.accumulate_mbyte_file_sizes(),
                        self.filesystem)
                    volume_total += volume_mbytes[volume.realpath]

        return volume_mbytes_type(volume=volume_mbytes, total=volume_total)
コード例 #11
0
ファイル: disk_builder.py プロジェクト: k0da/kiwi-1
class DiskBuilder(object):
    """
        Disk image builder
    """
    def __init__(self, xml_state, target_dir, root_dir):
        self.root_dir = root_dir
        self.target_dir = target_dir
        self.xml_state = xml_state
        self.custom_filesystem_args = None
        self.build_type_name = xml_state.get_build_type_name()
        self.image_format = xml_state.build_type.get_format()
        self.install_iso = xml_state.build_type.get_installiso()
        self.install_stick = xml_state.build_type.get_installstick()
        self.install_pxe = xml_state.build_type.get_installpxe()
        self.blocksize = xml_state.build_type.get_target_blocksize()
        self.volume_manager_name = xml_state.get_volume_management()
        self.volumes = xml_state.get_volumes()
        self.volume_group_name = xml_state.get_volume_group_name()
        self.mdraid = xml_state.build_type.get_mdraid()
        self.luks = xml_state.build_type.get_luks()
        self.luks_os = xml_state.build_type.get_luksOS()
        self.machine = xml_state.get_build_type_machine_section()
        self.requested_filesystem = xml_state.build_type.get_filesystem()
        self.requested_boot_filesystem = \
            xml_state.build_type.get_bootfilesystem()
        self.bootloader = xml_state.build_type.get_bootloader()
        self.disk_setup = DiskSetup(
            xml_state, root_dir
        )
        self.boot_image_task = BootImageTask(
            'kiwi', xml_state, target_dir
        )
        self.firmware = FirmWare(
            xml_state
        )
        self.system_setup = SystemSetup(
            xml_state=xml_state, description_dir=None, root_dir=self.root_dir
        )
        self.diskname = ''.join(
            [
                target_dir, '/',
                xml_state.xml_data.get_name(),
                '.' + platform.machine(),
                '-' + xml_state.get_image_version(),
                '.raw'
            ]
        )
        self.install_media = self.__install_image_requested()
        self.install_image = InstallImageBuilder(
            xml_state, target_dir, self.boot_image_task
        )
        # an instance of a class with the sync_data capability
        # representing the entire image system except for the boot/ area
        # which could live on another part of the disk
        self.system = None

        # an instance of a class with the sync_data capability
        # representing the boot/ area of the disk if not part of
        # self.system
        self.system_boot = None

        # an instance of a class with the sync_data capability
        # representing the boot/efi area of the disk
        self.system_efi = None

        # result store
        self.result = Result()

    def create(self):
        if self.install_media and self.build_type_name != 'oem':
            raise KiwiInstallMediaError(
                'Install media requires oem type setup, got %s' %
                self.build_type_name
            )

        # setup recovery archive, cleanup and create archive if requested
        self.system_setup.create_recovery_archive()

        # prepare boot(initrd) root system
        log.info('Preparing boot system')
        self.boot_image_task.prepare()

        # precalculate needed disk size
        disksize_mbytes = self.disk_setup.get_disksize_mbytes()

        # create the disk
        log.info('Creating raw disk image %s', self.diskname)
        loop_provider = LoopDevice(
            self.diskname, disksize_mbytes, self.blocksize
        )
        loop_provider.create()

        self.disk = Disk(
            self.firmware.get_partition_table_type(), loop_provider
        )

        # create the bootloader instance
        self.bootloader_config = BootLoaderConfig(
            self.bootloader, self.xml_state, self.root_dir,
            {'targetbase': loop_provider.get_device()}
        )

        # create disk partitions and instance device map
        device_map = self.__build_and_map_disk_partitions()

        # create raid on current root device if requested
        if self.mdraid:
            self.raid_root = RaidDevice(device_map['root'])
            self.raid_root.create_degraded_raid(raid_level=self.mdraid)
            device_map['root'] = self.raid_root.get_device()

        # create luks on current root device if requested
        if self.luks:
            self.luks_root = LuksDevice(device_map['root'])
            self.luks_root.create_crypto_luks(
                passphrase=self.luks, os=self.luks_os
            )
            device_map['root'] = self.luks_root.get_device()

        # create filesystems on boot partition(s) if any
        self.__build_boot_filesystems(device_map)

        # create volumes and filesystems for root system
        if self.volume_manager_name:
            volume_manager_custom_parameters = {
                'root_filesystem_args':
                    self.custom_filesystem_args,
                'root_label':
                    self.disk_setup.get_root_label(),
                'root_is_snapshot':
                    self.xml_state.build_type.get_btrfs_root_is_snapshot()
            }
            volume_manager = VolumeManager(
                self.volume_manager_name, device_map['root'],
                self.root_dir + '/',
                self.volumes, volume_manager_custom_parameters
            )
            volume_manager.setup(
                self.volume_group_name
            )
            volume_manager.create_volumes(
                self.requested_filesystem
            )
            volume_manager.mount_volumes()
            self.system = volume_manager
            device_map['root'] = volume_manager.get_device()['root']
        else:
            log.info(
                'Creating root(%s) filesystem on %s',
                self.requested_filesystem, device_map['root'].get_device()
            )
            filesystem = FileSystem(
                self.requested_filesystem, device_map['root'],
                self.root_dir + '/',
                self.custom_filesystem_args
            )
            filesystem.create_on_device(
                label=self.disk_setup.get_root_label()
            )
            self.system = filesystem

        # create a random image identifier
        self.mbrid = ImageIdentifier()
        self.mbrid.calculate_id()

        # create first stage metadata to boot image
        self.__write_partition_id_config_to_boot_image()

        self.__write_recovery_metadata_to_boot_image()

        self.__write_raid_config_to_boot_image()

        self.system_setup.export_modprobe_setup(
            self.boot_image_task.boot_root_directory
        )

        # create first stage metadata to system image
        self.__write_image_identifier_to_system_image()

        self.__write_crypttab_to_system_image()

        # create initrd cpio archive
        self.boot_image_task.create_initrd(self.mbrid)

        # create second stage metadata to boot
        self.__copy_first_boot_files_to_system_image()

        self.__write_bootloader_config_to_system_image(device_map)

        self.mbrid.write_to_disk(
            self.disk.storage_provider
        )

        # syncing system data to disk image
        log.info('Syncing system to image')
        if self.system_efi:
            log.info('--> Syncing EFI boot data to EFI partition')
            self.system_efi.sync_data()

        if self.system_boot:
            log.info('--> Syncing boot data at extra partition')
            self.system_boot.sync_data(
                self.__get_exclude_list_for_boot_data_sync()
            )

        log.info('--> Syncing root filesystem data')
        self.system.sync_data(
            self.__get_exclude_list_for_root_data_sync(device_map)
        )

        # install boot loader
        self.__install_bootloader(device_map)

        self.result.add(
            'disk_image', self.diskname
        )

        # create install media if requested
        if self.install_media:
            if self.image_format:
                log.warning('Install image requested, ignoring disk format')
            if self.install_iso or self.install_stick:
                log.info('Creating hybrid ISO installation image')
                self.install_image.create_install_iso()
                self.result.add(
                    'installation_image', self.install_image.isoname
                )

            if self.install_pxe:
                log.info('Creating PXE installation archive')
                self.install_image.create_install_pxe_archive()
                self.result.add(
                    'installation_pxe_archive', self.install_image.pxename
                )

        # create disk image format if requested
        elif self.image_format:
            log.info('Creating %s Disk Format', self.image_format)
            disk_format = DiskFormat(
                self.image_format, self.xml_state,
                self.root_dir, self.target_dir
            )
            disk_format.create_image_format()
            self.result.add(
                'disk_format_image',
                self.target_dir + '/' + disk_format.get_target_name_for_format(
                    self.image_format
                )
            )

        return self.result

    def __install_image_requested(self):
        if self.install_iso or self.install_stick or self.install_pxe:
            return True

    def __get_exclude_list_for_root_data_sync(self, device_map):
        exclude_list = [
            'image', '.profile', '.kconfig', 'var/cache/kiwi'
        ]
        if 'boot' in device_map and self.bootloader == 'grub2_s390x_emu':
            exclude_list.append('boot/zipl/*')
            exclude_list.append('boot/zipl/.*')
        elif 'boot' in device_map:
            exclude_list.append('boot/*')
            exclude_list.append('boot/.*')
        return exclude_list

    def __get_exclude_list_for_boot_data_sync(self):
        return ['efi/*']

    def __build_boot_filesystems(self, device_map):
        if 'efi' in device_map:
            log.info(
                'Creating EFI(fat16) filesystem on %s',
                device_map['efi'].get_device()
            )
            filesystem = FileSystem(
                'fat16', device_map['efi'], self.root_dir + '/boot/efi/'
            )
            filesystem.create_on_device(
                label=self.disk_setup.get_efi_label()
            )
            self.system_efi = filesystem

        if 'boot' in device_map:
            boot_filesystem = self.requested_boot_filesystem
            if not boot_filesystem:
                boot_filesystem = self.requested_filesystem
            boot_directory = self.root_dir + '/boot/'
            if self.bootloader == 'grub2_s390x_emu':
                boot_directory = self.root_dir + '/boot/zipl/'
                boot_filesystem = 'ext2'
            log.info(
                'Creating boot(%s) filesystem on %s',
                boot_filesystem, device_map['boot'].get_device()
            )
            filesystem = FileSystem(
                boot_filesystem, device_map['boot'], boot_directory
            )
            filesystem.create_on_device(
                label=self.disk_setup.get_boot_label()
            )
            self.system_boot = filesystem

    def __build_and_map_disk_partitions(self):
        self.disk.wipe()
        if self.firmware.legacy_bios_mode():
            log.info('--> creating EFI CSM(legacy bios) partition')
            self.disk.create_efi_csm_partition(
                self.firmware.get_legacy_bios_partition_size()
            )

        if self.firmware.efi_mode():
            log.info('--> creating EFI partition')
            self.disk.create_efi_partition(
                self.firmware.get_efi_partition_size()
            )

        if self.disk_setup.need_boot_partition():
            log.info('--> creating boot partition')
            self.disk.create_boot_partition(
                self.disk_setup.boot_partition_size()
            )

        if self.volume_manager_name and self.volume_manager_name == 'lvm':
            log.info('--> creating LVM root partition')
            self.disk.create_root_lvm_partition('all_free')

        elif self.mdraid:
            log.info('--> creating mdraid root partition')
            self.disk.create_root_raid_partition('all_free')

        else:
            log.info('--> creating root partition')
            self.disk.create_root_partition('all_free')

        if self.firmware.bios_mode():
            log.info('--> setting active flag to primary boot partition')
            self.disk.activate_boot_partition()

        self.disk.map_partitions()
        return self.disk.get_device()

    def __write_partition_id_config_to_boot_image(self):
        log.info('Creating config.partids in boot system')
        filename = self.boot_image_task.boot_root_directory + '/config.partids'
        partition_id_map = self.disk.get_partition_id_map()
        with open(filename, 'w') as partids:
            for id_name, id_value in partition_id_map.iteritems():
                partids.write('%s="%s"\n' % (id_name, id_value))

    def __write_raid_config_to_boot_image(self):
        if self.mdraid:
            log.info('Creating etc/mdadm.conf in boot system')
            self.raid_root.create_raid_config(
                self.boot_image_task.boot_root_directory + '/etc/mdadm.conf'
            )

    def __write_crypttab_to_system_image(self):
        if self.luks:
            log.info('Creating etc/crypttab')
            self.luks_root.create_crypttab(
                self.root_dir + '/etc/crypttab'
            )

    def __write_image_identifier_to_system_image(self):
        log.info('Creating image identifier: %s', self.mbrid.get_id())
        self.mbrid.write(
            self.root_dir + '/boot/mbrid'
        )

    def __write_recovery_metadata_to_boot_image(self):
        if os.path.exists(self.root_dir + '/recovery.partition.size'):
            log.info('Copying recovery metadata to boot image')
            Command.run(
                [
                    'cp', self.root_dir + '/recovery.partition.size',
                    self.boot_image_task.boot_root_directory
                ]
            )

    def __write_bootloader_config_to_system_image(self, device_map):
        log.info('Creating %s bootloader configuration', self.bootloader)
        boot_device = device_map['root']
        if 'boot' in device_map:
            boot_device = device_map['boot']

        partition_id_map = self.disk.get_partition_id_map()
        boot_partition_id = partition_id_map['kiwi_RootPart']
        if 'kiwi_BootPart' in partition_id_map:
            boot_partition_id = partition_id_map['kiwi_BootPart']

        boot_uuid = self.disk.get_uuid(
            boot_device.get_device()
        )
        self.bootloader_config.setup_disk_boot_images(boot_uuid)
        self.bootloader_config.setup_disk_image_config(boot_uuid)
        self.bootloader_config.write()

        self.system_setup.call_edit_boot_config_script(
            self.requested_filesystem, boot_partition_id
        )

    def __install_bootloader(self, device_map):
        boot_device = device_map['root']
        custom_install_arguments = {}
        if 'boot' in device_map:
            boot_device = device_map['boot']
            custom_install_arguments['boot_device'] = boot_device.get_device()

        bootloader = BootLoaderInstall(
            self.bootloader, self.root_dir, self.disk.storage_provider,
            custom_install_arguments
        )
        bootloader.install()

        self.system_setup.call_edit_boot_install_script(
            self.diskname, boot_device.get_device()
        )

    def __copy_first_boot_files_to_system_image(self):
        log.info('Copy boot files to system image')
        kernel = Kernel(self.boot_image_task.boot_root_directory)
        if kernel.get_kernel():
            log.info('--> boot image kernel as first boot linux.vmx')
            kernel.copy_kernel(
                self.root_dir, '/boot/linux.vmx'
            )
        else:
            raise KiwiDiskBootImageError(
                'No kernel in boot image tree %s found' %
                self.boot_image_task.boot_root_directory
            )
        if self.machine and self.machine.get_domain() == 'dom0':
            if kernel.get_xen_hypervisor():
                log.info('--> boot image Xen hypervisor as xen.gz')
                kernel.copy_xen_hypervisor(
                    self.root_dir, '/boot/xen.gz'
                )
            else:
                raise KiwiDiskBootImageError(
                    'No hypervisor in boot image tree %s found' %
                    self.boot_image_task.boot_root_directory
                )
        log.info('--> initrd archive as first boot initrd.vmx')
        Command.run(
            [
                'mv', self.boot_image_task.initrd_filename,
                self.root_dir + '/boot/initrd.vmx'
            ]
        )
コード例 #12
0
class LiveImageBuilder(object):
    """
        Live image builder
    """
    def __init__(self, xml_state, target_dir, root_dir):
        self.media_dir = None
        self.arch = platform.machine()
        self.root_dir = root_dir
        self.target_dir = target_dir
        self.xml_state = xml_state
        self.live_type = xml_state.build_type.get_flags()
        self.types = Defaults.get_live_iso_types()
        self.hybrid = xml_state.build_type.get_hybrid()
        self.volume_id = xml_state.build_type.get_volid()
        self.machine = xml_state.get_build_type_machine_section()
        self.mbrid = ImageIdentifier()
        self.mbrid.calculate_id()

        if not self.live_type:
            self.live_type = Defaults.get_default_live_iso_type()

        self.boot_image_task = BootImageTask('kiwi', xml_state, target_dir)
        self.firmware = FirmWare(xml_state)
        self.system_setup = SystemSetup(xml_state=xml_state,
                                        description_dir=None,
                                        root_dir=self.root_dir)
        self.isoname = ''.join([
            target_dir, '/',
            xml_state.xml_data.get_name(), '.' + platform.machine(),
            '-' + xml_state.get_image_version(), '.iso'
        ])
        self.live_image_file = ''.join([
            target_dir, '/',
            xml_state.xml_data.get_name(), '-read-only.', self.arch, '-',
            xml_state.get_image_version()
        ])
        self.result = Result()

    def create(self):
        # media dir to store CD contents
        self.media_dir = mkdtemp(prefix='live-media.', dir=self.target_dir)
        rootsize = SystemSize(self.media_dir)

        # custom iso metadata
        log.info('Using following live ISO metadata:')
        log.info('--> Application id: %s', self.mbrid.get_id())
        log.info('--> Publisher: %s', Defaults.get_publisher())
        custom_iso_args = [
            '-A',
            self.mbrid.get_id(),
            '-p',
            '"' + Defaults.get_preparer() + '"',
            '-publisher',
            '"' + Defaults.get_publisher() + '"',
        ]
        if self.volume_id:
            log.info('--> Volume id: %s', self.volume_id)
            custom_iso_args.append('-V')
            custom_iso_args.append('"' + self.volume_id + '"')

        # prepare boot(initrd) root system
        log.info('Preparing live ISO boot system')
        self.boot_image_task.prepare()

        # export modprobe configuration to boot image
        self.system_setup.export_modprobe_setup(
            self.boot_image_task.boot_root_directory)

        # pack system into live boot structure
        log.info('Packing system into live ISO type: %s', self.live_type)
        if self.live_type in self.types:
            live_type_image = FileSystem(name=self.types[self.live_type],
                                         device_provider=None,
                                         root_dir=self.root_dir)
            live_type_image.create_on_file(self.live_image_file)
            Command.run(['mv', self.live_image_file, self.media_dir])
            self.__create_live_iso_client_config(self.live_type)
        else:
            raise KiwiLiveBootImageError('live ISO type "%s" not supported' %
                                         self.live_type)

        # setup bootloader config to boot the ISO via isolinux
        log.info('Setting up isolinux bootloader configuration')
        bootloader_config_isolinux = BootLoaderConfig('isolinux',
                                                      self.xml_state,
                                                      self.media_dir)
        bootloader_config_isolinux.setup_live_boot_images(
            mbrid=None, lookup_path=self.boot_image_task.boot_root_directory)
        bootloader_config_isolinux.setup_live_image_config(mbrid=None)
        bootloader_config_isolinux.write()

        # setup bootloader config to boot the ISO via EFI
        if self.firmware.efi_mode():
            log.info('Setting up EFI grub bootloader configuration')
            bootloader_config_grub = BootLoaderConfig('grub2', self.xml_state,
                                                      self.media_dir)
            bootloader_config_grub.setup_live_boot_images(
                mbrid=self.mbrid,
                lookup_path=self.boot_image_task.boot_root_directory)
            bootloader_config_grub.setup_live_image_config(mbrid=self.mbrid)
            bootloader_config_grub.write()

        # create initrd for live image
        log.info('Creating live ISO boot image')
        self.__create_live_iso_kernel_and_initrd()

        # calculate size and decide if we need UDF
        if rootsize.accumulate_mbyte_file_sizes() > 4096:
            log.info('ISO exceeds 4G size, using UDF filesystem')
            custom_iso_args.append('-allow-limited-size')
            custom_iso_args.append('-udf')

        # create iso filesystem from media_dir
        log.info('Creating live ISO image')
        iso_image = FileSystemIsoFs(device_provider=None,
                                    root_dir=self.media_dir,
                                    custom_args=custom_iso_args)
        iso_header_offset = iso_image.create_on_file(self.isoname)

        # make it hybrid
        if self.hybrid:
            Iso.create_hybrid(iso_header_offset, self.mbrid, self.isoname)

        self.result.add('live_image', self.isoname)
        return self.result

    def __create_live_iso_kernel_and_initrd(self):
        boot_path = self.media_dir + '/boot/x86_64/loader'
        Path.create(boot_path)
        kernel = Kernel(self.boot_image_task.boot_root_directory)
        if kernel.get_kernel():
            kernel.copy_kernel(boot_path, '/linux')
        else:
            raise KiwiLiveBootImageError(
                'No kernel in boot image tree %s found' %
                self.boot_image_task.boot_root_directory)
        if self.machine and self.machine.get_domain() == 'dom0':
            if kernel.get_xen_hypervisor():
                kernel.copy_xen_hypervisor(boot_path, '/xen.gz')
            else:
                raise KiwiLiveBootImageError(
                    'No hypervisor in boot image tree %s found' %
                    self.boot_image_task.boot_root_directory)
        self.boot_image_task.create_initrd(self.mbrid)
        Command.run([
            'mv', self.boot_image_task.initrd_filename, boot_path + '/initrd'
        ])

    def __create_live_iso_client_config(self, iso_type):
        """
            Setup IMAGE and UNIONFS_CONFIG variables as they are used in
            the kiwi isoboot code. Variable contents:

            + IMAGE=target_device;live_iso_name_definition
            + UNIONFS_CONFIG=rw_device,ro_device,union_type

            If no real block device is used or can be predefined the
            word 'loop' is set as a placeholder or indicator to use a loop
            device. For more details please refer to the kiwi shell boot
            code
        """
        iso_client_config_file = self.media_dir + '/config.isoclient'
        iso_client_params = Defaults.get_live_iso_client_parameters()
        (system_device, union_device, union_type) = iso_client_params[iso_type]

        with open(iso_client_config_file, 'w') as config:
            config.write('IMAGE="%s;%s.%s;%s"\n' %
                         (system_device, self.xml_state.xml_data.get_name(),
                          self.arch, self.xml_state.get_image_version()))
            config.write('UNIONFS_CONFIG="%s,loop,%s"\n' %
                         (union_device, union_type))

    def __del__(self):
        if self.media_dir:
            log.info('Cleaning up %s instance', type(self).__name__)
            Path.wipe(self.media_dir)
コード例 #13
0
ファイル: disk_builder.py プロジェクト: k0da/kiwi-1
    def __init__(self, xml_state, target_dir, root_dir):
        self.root_dir = root_dir
        self.target_dir = target_dir
        self.xml_state = xml_state
        self.custom_filesystem_args = None
        self.build_type_name = xml_state.get_build_type_name()
        self.image_format = xml_state.build_type.get_format()
        self.install_iso = xml_state.build_type.get_installiso()
        self.install_stick = xml_state.build_type.get_installstick()
        self.install_pxe = xml_state.build_type.get_installpxe()
        self.blocksize = xml_state.build_type.get_target_blocksize()
        self.volume_manager_name = xml_state.get_volume_management()
        self.volumes = xml_state.get_volumes()
        self.volume_group_name = xml_state.get_volume_group_name()
        self.mdraid = xml_state.build_type.get_mdraid()
        self.luks = xml_state.build_type.get_luks()
        self.luks_os = xml_state.build_type.get_luksOS()
        self.machine = xml_state.get_build_type_machine_section()
        self.requested_filesystem = xml_state.build_type.get_filesystem()
        self.requested_boot_filesystem = \
            xml_state.build_type.get_bootfilesystem()
        self.bootloader = xml_state.build_type.get_bootloader()
        self.disk_setup = DiskSetup(
            xml_state, root_dir
        )
        self.boot_image_task = BootImageTask(
            'kiwi', xml_state, target_dir
        )
        self.firmware = FirmWare(
            xml_state
        )
        self.system_setup = SystemSetup(
            xml_state=xml_state, description_dir=None, root_dir=self.root_dir
        )
        self.diskname = ''.join(
            [
                target_dir, '/',
                xml_state.xml_data.get_name(),
                '.' + platform.machine(),
                '-' + xml_state.get_image_version(),
                '.raw'
            ]
        )
        self.install_media = self.__install_image_requested()
        self.install_image = InstallImageBuilder(
            xml_state, target_dir, self.boot_image_task
        )
        # an instance of a class with the sync_data capability
        # representing the entire image system except for the boot/ area
        # which could live on another part of the disk
        self.system = None

        # an instance of a class with the sync_data capability
        # representing the boot/ area of the disk if not part of
        # self.system
        self.system_boot = None

        # an instance of a class with the sync_data capability
        # representing the boot/efi area of the disk
        self.system_efi = None

        # result store
        self.result = Result()
コード例 #14
0
class BootLoaderConfigZipl(BootLoaderConfigBase):
    """
        zipl bootloader configuration.
    """
    def post_init(self, custom_args):
        self.custom_args = custom_args
        arch = platform.machine()
        if 's390' in arch:
            self.arch = arch
        else:
            raise KiwiBootLoaderZiplPlatformError(
                'host architecture %s not supported for zipl setup' % arch)

        if not custom_args or 'targetbase' not in custom_args:
            raise KiwiBootLoaderZiplSetupError(
                'targetbase device name is required for zipl setup')

        self.bootpath = '.'
        self.timeout = self.get_boot_timeout_seconds()
        self.cmdline = self.get_boot_cmdline()
        self.cmdline_failsafe = ' '.join(
            [self.cmdline, self.get_failsafe_kernel_options()])
        self.target_blocksize = self.xml_state.build_type.get_target_blocksize(
        )
        self.target_type = self.xml_state.build_type.get_zipl_targettype()
        self.failsafe_boot = self.failsafe_boot_entry_requested()
        self.target_device = custom_args['targetbase']
        self.firmware = FirmWare(self.xml_state)
        self.target_table_type = self.firmware.get_partition_table_type()

        self.zipl = BootLoaderTemplateZipl()
        self.config = None

    def write(self):
        """
            Write zipl config file
        """
        log.info('Writing zipl config file')
        config_dir = self.__get_zipl_boot_path()
        config_file = config_dir + '/config'
        if self.config:
            Path.create(config_dir)
            with open(config_file, 'w') as config:
                config.write(self.config)

            log.info('Moving initrd/kernel to zipl boot directory')
            Command.run([
                'mv', self.root_dir + '/boot/initrd.vmx',
                self.root_dir + '/boot/linux.vmx',
                self.__get_zipl_boot_path()
            ])

    def setup_disk_image_config(self,
                                uuid=None,
                                hypervisor=None,
                                kernel='linux.vmx',
                                initrd='initrd.vmx'):
        """
            Create the zipl config in memory from a template suitable to
            boot from a disk image
        """
        log.info('Creating zipl config file from template')
        parameters = {
            'device': self.target_device,
            'target_type': self.target_type,
            'blocksize': self.target_blocksize,
            'offset': self.__get_target_offset(),
            'geometry': self.__get_target_geometry(),
            'default_boot': '1',
            'bootpath': self.bootpath,
            'boot_timeout': self.timeout,
            'title': self.quote_title(self.get_menu_entry_title()),
            'kernel_file': kernel,
            'initrd_file': initrd,
            'boot_options': self.cmdline,
            'failsafe_boot_options': self.cmdline_failsafe
        }
        log.info('--> Using standard disk boot template')
        template = self.zipl.get_template(self.failsafe_boot)
        try:
            self.config = template.substitute(parameters)
        except Exception as e:
            raise KiwiTemplateError('%s: %s' % (type(e).__name__, format(e)))

    def setup_disk_boot_images(self, boot_uuid, lookup_path=None):
        # on s390 no bootloader images needs to be created
        pass

    def __get_zipl_boot_path(self):
        return self.root_dir + '/boot/zipl'

    def __get_target_geometry(self):
        if self.target_table_type == 'dasd':
            return '%d,%d,%d' % (
                self.__read_dasd_disk_geometry('cylinders'),
                self.__read_dasd_disk_geometry('tracks per cylinder'),
                self.__read_dasd_disk_geometry('blocks per track'))
        else:
            return '%d,%d,%d' % (
                self.__read_msdos_disk_geometry('cylinders'),
                self.__read_msdos_disk_geometry('tracks per cylinder'),
                self.__read_msdos_disk_geometry('blocks per track'))

    def __get_target_offset(self):
        if self.target_table_type == 'dasd':
            blocks = self.__read_dasd_disk_geometry('blocks per track')
            bash_command = [
                'fdasd', '-f', '-s', '-p', self.target_device, '|', 'head',
                '-n', '1', '|', 'tr', '-s', '" "'
            ]
            fdasd_call = Command.run(['bash', '-c', ' '.join(bash_command)])
            fdasd_output = fdasd_call.output
            try:
                start_track = int(fdasd_output.split(' ')[2].lstrip())
            except Exception as e:
                raise KiwiDiskGeometryError('unknown partition format: %s' %
                                            fdasd_output)
            return start_track * blocks
        else:
            blocks = self.__read_msdos_disk_geometry('blocks per track')
            parted_call = Command.run(
                ['parted', '-m', self.target_device, 'unit', 's', 'print'])
            parted_output = parted_call.output.lstrip()
            first_partition_format = re.search('1:(.*?)s', parted_output)
            if not first_partition_format:
                raise KiwiDiskGeometryError('unknown partition format: %s' %
                                            parted_output)
            start_track = int(first_partition_format.group(1))
            return start_track * blocks

    def __read_msdos_disk_geometry(self, value):
        sfdisk_call = Command.run(['sfdisk', '-g', self.target_device])
        sfdisk_output = sfdisk_call.output.lstrip()
        geometry_format = re.search(
            '/dev.*: (.*) cylinders, (.*) heads, (.*) sectors/track',
            sfdisk_output)
        if not geometry_format:
            raise KiwiDiskGeometryError('unknown format for geometry: %s' %
                                        sfdisk_output)
        result = {
            'cylinders': geometry_format.group(1),
            'tracks per cylinder': geometry_format.group(2),
            'blocks per track': geometry_format.group(3)
        }
        if value in result:
            return int(result[value])

    def __read_dasd_disk_geometry(self, value):
        fdasd = ['fdasd', '-f', '-p', self.target_device]
        bash_command = fdasd + ['|', 'grep', '"' + value + '"']
        fdasd_call = Command.run(['bash', '-c', ' '.join(bash_command)])
        fdasd_output = fdasd_call.output
        try:
            return int(fdasd_output.split(':')[1].lstrip())
        except Exception as e:
            raise KiwiDiskGeometryError(
                'unknown format for disk geometry: %s' % fdasd_output)
コード例 #15
0
ファイル: disk_setup.py プロジェクト: k0da/kiwi-1
class DiskSetup(object):
    """
        Implement disk setup methods providing information required
        before building a disk image
    """
    def __init__(self, xml_state, root_dir):
        self.configured_size = xml_state.get_build_type_size()
        self.build_type_name = xml_state.get_build_type_name()
        self.filesystem = xml_state.build_type.get_filesystem()
        self.bootpart_requested = xml_state.build_type.get_bootpartition()
        self.bootpart_mbytes = xml_state.build_type.get_bootpartsize()
        self.mdraid = xml_state.build_type.get_mdraid()
        self.luks = xml_state.build_type.get_luks()
        self.volume_manager = xml_state.get_volume_management()
        self.bootloader = xml_state.build_type.get_bootloader()
        self.oemconfig = xml_state.get_build_type_oemconfig_section()
        self.volumes = xml_state.get_volumes()

        self.firmware = FirmWare(
            xml_state
        )
        self.rootsize = SystemSize(
            root_dir
        )

        self.root_dir = root_dir
        self.xml_state = xml_state

    def get_disksize_mbytes(self):
        log.info('Precalculating required disk size')
        calculated_disk_mbytes = 0
        root_filesystem_mbytes = self.rootsize.customize(
            self.rootsize.accumulate_mbyte_file_sizes(), self.filesystem
        )
        calculated_disk_mbytes += root_filesystem_mbytes
        log.info(
            '--> system data with filesystem overhead needs %s MB',
            root_filesystem_mbytes
        )
        if self.volume_manager and self.volume_manager == 'lvm':
            if self.build_type_name == 'vmx':
                # only for vmx types we need to add the configured volume
                # sizes. oem disks are self expandable and will resize to
                # the configured sizes on first boot of the disk image
                volume_mbytes = self.__accumulate_volume_size(
                    root_filesystem_mbytes
                )
                if volume_mbytes:
                    calculated_disk_mbytes += volume_mbytes
                    log.info(
                        '--> volume(s) size setup adding %s MB', volume_mbytes
                    )

        legacy_bios_mbytes = self.firmware.get_legacy_bios_partition_size()
        if legacy_bios_mbytes:
            calculated_disk_mbytes += legacy_bios_mbytes
            log.info(
                '--> legacy bios boot partition adding %s MB',
                legacy_bios_mbytes
            )

        boot_mbytes = self.boot_partition_size()
        if boot_mbytes:
            calculated_disk_mbytes += boot_mbytes
            log.info(
                '--> boot partition adding %s MB', boot_mbytes
            )

        efi_mbytes = self.firmware.get_efi_partition_size()
        if efi_mbytes:
            calculated_disk_mbytes += efi_mbytes
            log.info(
                '--> EFI partition adding %s MB', efi_mbytes
            )

        recovery_mbytes = self.__inplace_recovery_partition_size()
        if recovery_mbytes:
            calculated_disk_mbytes += recovery_mbytes
            log.info(
                '--> In-place recovery partition adding: %s MB',
                recovery_mbytes
            )

        if self.configured_size and self.build_type_name == 'oem':
            log.warning(
                'Fixed disk size setup not used for expandable oem image'
            )
            self.configured_size = None

        if not self.configured_size:
            log.info(
                'Using calculated disk size: %d MB',
                calculated_disk_mbytes
            )
            return calculated_disk_mbytes
        elif self.configured_size.additive:
            result_disk_mbytes = \
                self.configured_size.mbytes + calculated_disk_mbytes
            log.info(
                'Using configured disk size: %d MB + %d MB calculated = %d MB',
                self.configured_size.mbytes,
                calculated_disk_mbytes,
                result_disk_mbytes
            )
            return result_disk_mbytes
        else:
            log.info(
                'Using configured disk size: %d MB',
                self.configured_size.mbytes
            )
            if self.configured_size.mbytes < calculated_disk_mbytes:
                log.warning(
                    '--> Configured size smaller than calculated size: %d MB',
                    calculated_disk_mbytes
                )
            return self.configured_size.mbytes

    def need_boot_partition(self):
        """
            Decide if an extra boot partition is needed. This is done with
            the bootpartition attribute from the type, however if it is not
            set it depends on some other type configuration parameters if
            we need a boot partition or not
        """
        if self.bootpart_requested is True:
            return True
        if self.bootpart_requested is False:
            return False
        if self.mdraid:
            return True
        if self.volume_manager:
            return True
        if self.filesystem == 'btrfs':
            return True
        if self.filesystem == 'xfs':
            return True
        if self.bootloader == 'grub2_s390x_emu':
            return True
        if self.luks:
            return True

    def get_boot_label(self):
        label = 'BOOT'
        if self.bootloader == 'grub2_s390x_emu':
            label = 'ZIPL'
        return label

    def get_root_label(self):
        return 'ROOT'

    def get_efi_label(self):
        return 'EFI'

    def boot_partition_size(self):
        if self.need_boot_partition():
            if self.bootpart_mbytes:
                return self.bootpart_mbytes
            else:
                return Defaults.get_default_boot_mbytes()

    def __inplace_recovery_partition_size(self):
        """
            in inplace recovery mode the recovery archive is created at
            install time. This requires free space on the disk. The
            amount of free space is specified with the oem-recovery-part-size
            attribute. If specified we add the given size to the disk.
            If not specified an inplace setup at install time will be
            moved to the first boot of an oem image when the recovery
            partition has been created
        """
        if self.oemconfig and self.oemconfig.get_oem_inplace_recovery():
            recovery_mbytes = self.oemconfig.get_oem_recovery_part_size()
            if recovery_mbytes:
                return int(recovery_mbytes[0] * 1.7)

    def __accumulate_volume_size(self, root_mbytes):
        """
            calculate number of mbytes to add to the disk to allow
            the creaton of the volumes with their configured size
        """
        disk_volume_mbytes = 0

        data_volume_mbytes = self.__calculate_volume_mbytes()
        root_volume = self.__get_root_volume_configuration()

        for volume in self.volumes:
            if volume.realpath and not volume.realpath == '/' and volume.size:
                [size_type, req_size] = volume.size.split(':')
                disk_add_mbytes = 0
                if size_type == 'freespace':
                    disk_add_mbytes += int(req_size) + \
                        Defaults.get_min_volume_mbytes()
                else:
                    disk_add_mbytes += int(req_size) - \
                        data_volume_mbytes.volume[volume.realpath]
                if disk_add_mbytes > 0:
                    disk_volume_mbytes += disk_add_mbytes
                else:
                    log.warning(
                        'volume size of %s MB for %s is too small, skipped',
                        int(req_size), volume.realpath
                    )

        if root_volume:
            if root_volume.size_type == 'freespace':
                disk_add_mbytes += root_volume.req_size + \
                    Defaults.get_min_volume_mbytes()
            else:
                disk_add_mbytes = root_volume.req_size - \
                    root_mbytes + data_volume_mbytes.total

            if disk_add_mbytes > 0:
                disk_volume_mbytes += disk_add_mbytes
            else:
                log.warning(
                    'root volume size of %s MB is too small, skipped',
                    root_volume.req_size
                )

        return disk_volume_mbytes

    def __get_root_volume_configuration(self):
        """
            provide LVRoot volume configuration if present and in
            use according to the selected volume management. So far
            this only affects the LVM volume manager
        """
        root_volume_type = namedtuple(
            'root_volume_type', ['size_type', 'req_size']
        )
        for volume in self.volumes:
            if volume.name == 'LVRoot':
                if volume.size:
                    [size_type, req_size] = volume.size.split(':')
                    return root_volume_type(
                        size_type=size_type,
                        req_size=int(req_size)
                    )

    def __calculate_volume_mbytes(self):
        """
            calculate the number of mbytes each volume path currently
            consumes and also provide a total number of these values
        """
        volume_mbytes_type = namedtuple(
            'volume_mbytes_type', ['volume', 'total']
        )
        volume_mbytes = {}
        volume_total = 0
        for volume in self.volumes:
            if volume.realpath and not volume.realpath == '/':
                path_to_volume = self.root_dir + '/' + volume.realpath
                if os.path.exists(path_to_volume):
                    volume_size = SystemSize(path_to_volume)
                    volume_mbytes[volume.realpath] = volume_size.customize(
                        volume_size.accumulate_mbyte_file_sizes(),
                        self.filesystem
                    )
                    volume_total += volume_mbytes[volume.realpath]

        return volume_mbytes_type(
            volume=volume_mbytes,
            total=volume_total
        )
コード例 #16
0
class BootLoaderConfigGrub2(BootLoaderConfigBase):
    """
        grub2 bootloader configuration.
    """
    def post_init(self, custom_args):
        self.custom_args = custom_args
        arch = platform.machine()
        if arch == 'x86_64':
            self.arch = arch
        else:
            raise KiwiBootLoaderGrubPlatformError(
                'host architecture %s not supported for grub2 setup' % arch
            )

        self.terminal = 'gfxterm'
        self.bootpath = self.get_boot_path()
        self.gfxmode = self.__get_gfxmode()
        self.theme = self.get_boot_theme()
        self.timeout = self.get_boot_timeout_seconds()
        self.failsafe_boot = self.failsafe_boot_entry_requested()
        self.hypervisor_domain = self.get_hypervisor_domain()
        self.firmware = FirmWare(
            self.xml_state
        )

        self.hybrid_boot = True
        self.multiboot = False
        if self.hypervisor_domain:
            if self.hypervisor_domain == 'dom0':
                self.hybrid_boot = False
                self.multiboot = True
            elif self.hypervisor_domain == 'domU':
                self.hybrid_boot = False
                self.multiboot = False

        self.xen_guest = False
        if self.hypervisor_domain == 'domU' or self.firmware.ec2_mode():
            self.xen_guest = True

        self.grub2 = BootLoaderTemplateGrub2()
        self.config = None
        self.efi_boot_path = None
        self.boot_directory_name = 'grub2'

    def write(self):
        """
            Write grub.cfg file to all required places
        """
        log.info('Writing grub.cfg file')
        config_dir = self.__get_grub_boot_path()
        config_file = config_dir + '/grub.cfg'
        if self.config:
            Path.create(config_dir)
            with open(config_file, 'w') as config:
                config.write(self.config)

            if self.efi_boot_path:
                config_file = self.efi_boot_path + '/grub.cfg'
                with open(config_file, 'w') as config:
                    config.write(self.config)

    def setup_disk_image_config(
        self, uuid, hypervisor='xen.gz', kernel='linux.vmx', initrd='initrd.vmx'
    ):
        """
            Create the grub.cfg in memory from a template suitable to boot
            from a disk image
        """
        log.info('Creating grub config file from template')
        cmdline = self.get_boot_cmdline(uuid)
        cmdline_failsafe = ' '.join(
            [cmdline, self.get_failsafe_kernel_options()]
        )
        parameters = {
            'search_params': '--fs-uuid --set=root ' + uuid,
            'default_boot': '0',
            'kernel_file': kernel,
            'initrd_file': initrd,
            'boot_options': cmdline,
            'failsafe_boot_options': cmdline_failsafe,
            'gfxmode': self.gfxmode,
            'theme': self.theme,
            'boot_timeout': self.timeout,
            'title': self.get_menu_entry_title(),
            'bootpath': self.bootpath,
        }
        if self.multiboot:
            log.info('--> Using multiboot disk template')
            parameters['hypervisor'] = hypervisor
            template = self.grub2.get_multiboot_disk_template(
                self.failsafe_boot, self.terminal
            )
        else:
            log.info('--> Using EFI/BIOS hybrid boot disk template')
            template = self.grub2.get_disk_template(
                self.failsafe_boot, self.hybrid_boot, self.terminal
            )
        try:
            self.config = template.substitute(parameters)
        except Exception as e:
            raise KiwiTemplateError(
                '%s: %s' % (type(e).__name__, format(e))
            )

    def setup_install_image_config(
        self, mbrid, hypervisor='xen.gz', kernel='linux', initrd='initrd'
    ):
        """
            Create the grub.cfg in memory from a template suitable to boot
            from an ISO image in EFI boot mode
        """
        log.info('Creating grub install config file from template')
        cmdline = self.get_boot_cmdline()
        cmdline_failsafe = ' '.join(
            [cmdline, self.get_failsafe_kernel_options()]
        )
        parameters = {
            'search_params': '--file --set=root /boot/' + mbrid.get_id(),
            'default_boot': '0',
            'kernel_file': kernel,
            'initrd_file': initrd,
            'boot_options': cmdline,
            'failsafe_boot_options': cmdline_failsafe,
            'gfxmode': self.gfxmode,
            'theme': self.theme,
            'boot_timeout': self.timeout,
            'title': self.get_menu_entry_install_title(),
            'bootpath': '/boot/x86_64/loader',
        }
        if self.multiboot:
            log.info('--> Using EFI multiboot install template')
            parameters['hypervisor'] = hypervisor
            template = self.grub2.get_multiboot_install_template(
                self.failsafe_boot, self.terminal
            )
        else:
            log.info('--> Using EFI boot install template')
            hybrid_boot = True
            template = self.grub2.get_install_template(
                self.failsafe_boot, hybrid_boot, self.terminal
            )
        try:
            self.config = template.substitute(parameters)
        except Exception as e:
            raise KiwiTemplateError(
                '%s: %s' % (type(e).__name__, format(e))
            )

    def setup_live_image_config(
        self, mbrid, hypervisor='xen.gz', kernel='linux', initrd='initrd'
    ):
        """
            Create the grub.cfg in memory from a template suitable to boot
            a live system from an ISO image in EFI boot mode
        """
        log.info('Creating grub live ISO config file from template')
        cmdline = self.get_boot_cmdline()
        cmdline_failsafe = ' '.join(
            [cmdline, self.get_failsafe_kernel_options()]
        )
        parameters = {
            'search_params': '--file --set=root /boot/' + mbrid.get_id(),
            'default_boot': '0',
            'kernel_file': kernel,
            'initrd_file': initrd,
            'boot_options': cmdline,
            'failsafe_boot_options': cmdline_failsafe,
            'gfxmode': self.gfxmode,
            'theme': self.theme,
            'boot_timeout': self.timeout,
            'title': self.get_menu_entry_title(plain=True),
            'bootpath': '/boot/x86_64/loader',
        }
        if self.multiboot:
            log.info('--> Using EFI multiboot template')
            parameters['hypervisor'] = hypervisor
            template = self.grub2.get_multiboot_iso_template(
                self.failsafe_boot, self.terminal
            )
        else:
            log.info('--> Using EFI boot template')
            hybrid_boot = True
            template = self.grub2.get_iso_template(
                self.failsafe_boot, hybrid_boot, self.terminal
            )
        try:
            self.config = template.substitute(parameters)
        except Exception as e:
            raise KiwiTemplateError(
                '%s: %s' % (type(e).__name__, format(e))
            )

    def setup_install_boot_images(self, mbrid, lookup_path=None):
        """
            Using grub2 to boot an install media means to support EFI
            boot of the install media. Therefore an EFI image needs to
            be build or used and transfered into an embedded vfat image.
            The non EFI boot of the install media is handled in the
            isolinux boot loader configuration
        """
        log.info('Creating grub bootloader images')
        self.efi_boot_path = self.create_efi_path(in_sub_dir='')

        log.info('--> Creating identifier file %s', mbrid.get_id())
        Path.create(
            self.__get_grub_boot_path()
        )
        mbrid.write(
            self.root_dir + '/boot/' + mbrid.get_id()
        )
        mbrid.write(
            self.root_dir + '/boot/mbrid'
        )

        self.__copy_theme_data_to_boot_directory(lookup_path)

        if self.firmware.efi_mode() == 'uefi':
            log.info('--> Using signed secure boot efi image')
            self.__setup_secure_boot_efi_image(lookup_path)
        else:
            log.info('--> Creating unsigned efi image')
            self.__copy_efi_modules_to_boot_directory(lookup_path)
            self.__create_efi_image(mbrid=mbrid)

        self.__create_embedded_fat_efi_image()

    def setup_live_boot_images(self, mbrid, lookup_path=None):
        # same action as for install media
        self.setup_install_boot_images(mbrid, lookup_path)

    def setup_disk_boot_images(self, boot_uuid, lookup_path=None):
        """
            EFI and bios images needs to be build or used if provided
            by the distribution
        """
        log.info('Creating grub bootloader images')

        if self.firmware.efi_mode():
            self.efi_boot_path = self.create_efi_path()

        self.__copy_theme_data_to_boot_directory(lookup_path)

        if self.firmware.efi_mode() == 'efi':
            log.info('--> Creating unsigned efi image')
            self.__copy_efi_modules_to_boot_directory(lookup_path)
            self.__create_efi_image(uuid=boot_uuid)
        elif self.firmware.efi_mode() == 'uefi':
            log.info('--> Using signed secure boot efi image')
            self.__setup_secure_boot_efi_image(lookup_path)

        log.info('--> Creating bios core image')
        self.__copy_bios_modules_to_boot_directory(lookup_path)
        self.__create_bios_boot_image(boot_uuid)

    def __setup_secure_boot_efi_image(self, lookup_path):
        """
            use prebuilt and signed efi images provided by the distribution
        """
        secure_efi_lookup_path = self.root_dir + '/usr/lib64/efi/'
        if lookup_path:
            secure_efi_lookup_path = lookup_path
        shim_image = secure_efi_lookup_path + Defaults.get_shim_name()
        if not os.path.exists(shim_image):
            raise KiwiBootLoaderGrubSecureBootError(
                'Microsoft signed shim loader %s not found' % shim_image
            )
        grub_image = secure_efi_lookup_path + Defaults.get_signed_grub_name()
        if not os.path.exists(grub_image):
            raise KiwiBootLoaderGrubSecureBootError(
                'Signed grub2 efi loader %s not found' % grub_image
            )
        Command.run(
            ['cp', shim_image, self.__get_efi_image_name()]
        )
        Command.run(
            ['cp', grub_image, self.efi_boot_path]
        )

    def __create_embedded_fat_efi_image(self):
        Path.create(self.root_dir + '/boot/' + self.arch)
        efi_fat_image = ''.join(
            [self.root_dir + '/boot/', self.arch, '/efi']
        )
        Command.run(
            ['qemu-img', 'create', efi_fat_image, '4M']
        )
        Command.run(
            ['mkdosfs', '-n', 'BOOT', efi_fat_image]
        )
        Command.run(
            [
                'mcopy', '-Do', '-s', '-i', efi_fat_image,
                self.root_dir + '/EFI', '::'
            ]
        )

    def __create_efi_image(self, uuid=None, mbrid=None):
        """
            create efi image
        """
        early_boot_script = self.efi_boot_path + '/earlyboot.cfg'
        if uuid:
            self.__create_early_boot_script_for_uuid_search(
                early_boot_script, uuid
            )
        else:
            self.__create_early_boot_script_for_mbrid_search(
                early_boot_script, mbrid
            )
        Command.run(
            [
                'grub2-mkimage',
                '-O', self.__get_efi_format(),
                '-o', self.__get_efi_image_name(),
                '-c', early_boot_script,
                '-p', self.get_boot_path() + '/' + self.boot_directory_name,
                '-d',
                self.__get_grub_boot_path() + '/' + self.__get_efi_format()
            ] + self.__get_efi_modules()
        )

    def __create_bios_boot_image(self, uuid):
        """
            create bios image
        """
        early_boot_script = self.__get_grub_boot_path() + '/earlyboot.cfg'
        self.__create_early_boot_script_for_uuid_search(
            early_boot_script, uuid
        )
        Command.run(
            [
                'grub2-mkimage', '-O', self.__get_bios_format(),
                '-o', self.__get_bios_image_name(),
                '-c', early_boot_script,
                '-p', self.get_boot_path() + '/' + self.boot_directory_name,
                '-d',
                self.__get_grub_boot_path() + '/' + self.__get_bios_format()
            ] + self.__get_bios_modules()
        )

    def __create_early_boot_script_for_uuid_search(self, filename, uuid):
        with open(filename, 'w') as early_boot:
            early_boot.write(
                'search --fs-uuid --set=root %s\n' % uuid
            )
            early_boot.write(
                'set prefix=($root)%s/%s\n' % (
                    self.get_boot_path(), self.boot_directory_name
                )
            )

    def __create_early_boot_script_for_mbrid_search(self, filename, mbrid):
        with open(filename, 'w') as early_boot:
            early_boot.write(
                'search --file --set=root /boot/%s\n' % mbrid.get_id()
            )
            early_boot.write(
                'set prefix=($root)/boot/%s\n' % self.boot_directory_name
            )

    def __get_grub_boot_path(self):
        return self.root_dir + '/boot/' + self.boot_directory_name

    def __get_basic_modules(self):
        modules = [
            'ext2',
            'iso9660',
            'linux',
            'echo',
            'configfile',
            'search_label',
            'search_fs_file',
            'search',
            'search_fs_uuid',
            'ls',
            'normal',
            'gzio',
            'png',
            'fat',
            'gettext',
            'font',
            'minicmd',
            'gfxterm',
            'gfxmenu',
            'video',
            'video_fb',
            'xfs',
            'btrfs',
            'lvm',
            'multiboot'
        ]
        return modules

    def __get_efi_modules(self):
        modules = self.__get_basic_modules() + [
            'part_gpt',
            'efi_gop',
            'efi_uga',
            'linuxefi'
        ]
        return modules

    def __get_bios_modules(self):
        modules = self.__get_basic_modules() + [
            'part_gpt',
            'part_msdos',
            'biosdisk',
            'vga',
            'vbe',
            'chain',
            'boot'
        ]
        return modules

    def __get_efi_image_name(self):
        efi_image_name = None
        if self.arch == 'x86_64':
            efi_image_name = 'bootx64.efi'
        if efi_image_name:
            return ''.join(
                [self.efi_boot_path, '/', efi_image_name]
            )

    def __get_bios_image_name(self):
        return ''.join(
            [
                self.__get_grub_boot_path(), '/',
                self.__get_bios_format(), '/core.img'
            ]
        )

    def __get_efi_format(self):
        if self.arch == 'x86_64':
            return 'x86_64-efi'

    def __get_bios_format(self):
        return 'i386-pc'

    def __get_xen_format(self):
        return 'x86_64-xen'

    def __get_efi_modules_path(self, lookup_path=None):
        return self.__get_module_path(self.__get_efi_format(), lookup_path)

    def __get_bios_modules_path(self, lookup_path=None):
        return self.__get_module_path(self.__get_bios_format(), lookup_path)

    def __get_xen_modules_path(self, lookup_path=None):
        return self.__get_module_path(self.__get_xen_format(), lookup_path)

    def __get_module_path(self, format_name, lookup_path=None):
        if not lookup_path:
            lookup_path = self.root_dir
        return ''.join(
            [
                self.__find_grub_data(lookup_path + '/usr/lib'),
                '/', format_name
            ]
        )

    def __get_gfxmode(self):
        selected_gfxmode = '800x600'
        gfxmode = {
            '0x301': '640x480',
            '0x310': '640x480',
            '0x311': '640x480',
            '0x312': '640x480',
            '0x303': '800x600',
            '0x313': '800x600',
            '0x314': '800x600',
            '0x315': '800x600',
            '0x305': '1024x768',
            '0x316': '1024x768',
            '0x317': '1024x768',
            '0x318': '1024x768',
            '0x307': '1280x1024',
            '0x319': '1280x1024',
            '0x31a': '1280x1024',
            '0x31b': '1280x1024',
        }
        requested_gfxmode = self.xml_state.build_type.get_vga()
        if requested_gfxmode in gfxmode:
            selected_gfxmode = gfxmode[requested_gfxmode]
        return selected_gfxmode

    def __copy_theme_data_to_boot_directory(self, lookup_path):
        if not lookup_path:
            lookup_path = self.root_dir
        boot_unicode_font = self.root_dir + '/boot/unicode.pf2'
        if not os.path.exists(boot_unicode_font):
            unicode_font = self.__find_grub_data(lookup_path + '/usr/share') + \
                '/unicode.pf2'
            try:
                Command.run(
                    ['cp', unicode_font, boot_unicode_font]
                )
            except Exception:
                raise KiwiBootLoaderGrubFontError(
                    'Unicode font %s not found' % unicode_font
                )

        boot_theme_dir = self.root_dir + '/boot/' + \
            self.boot_directory_name + '/themes'
        if self.theme and not os.path.exists(boot_theme_dir):
            Path.create(boot_theme_dir)
            theme_dir = self.__find_grub_data(lookup_path + '/usr/share') + \
                '/themes/' + self.theme
            if os.path.exists(theme_dir):
                Command.run(
                    ['rsync', '-zav', theme_dir, boot_theme_dir],
                )
            else:
                log.warning('Theme %s not found', theme_dir)

    def __copy_efi_modules_to_boot_directory(self, lookup_path):
        self.__copy_modules_to_boot_directory_from(
            self.__get_efi_modules_path(lookup_path)
        )

    def __copy_bios_modules_to_boot_directory(self, lookup_path):
        self.__copy_modules_to_boot_directory_from(
            self.__get_bios_modules_path(lookup_path)
        )
        if self.xen_guest:
            self.__copy_modules_to_boot_directory_from(
                self.__get_xen_modules_path(lookup_path)
            )

    def __copy_modules_to_boot_directory_from(self, module_path):
        boot_module_path = \
            self.__get_grub_boot_path() + '/' + os.path.basename(module_path)
        if not os.path.exists(boot_module_path):
            try:
                Command.run(
                    ['cp', '-a', module_path, boot_module_path]
                )
            except Exception:
                raise KiwiBootLoaderGrubModulesError(
                    'grub2 modules %s not found' % module_path
                )

    def __find_grub_data(self, lookup_path):
        """
            depending on the distribution grub could be installed below
            a grub2 or grub directory. Therefore this information needs
            to be dynamically looked up
        """
        for grub_name in ['grub2', 'grub']:
            grub_path = lookup_path + '/' + grub_name
            if os.path.exists(grub_path):
                return grub_path

        raise KiwiBootLoaderGrubDataError(
            'No grub2 installation found in %s' % lookup_path
        )
コード例 #17
0
class BootLoaderConfigGrub2(BootLoaderConfigBase):
    """
        grub2 bootloader configuration.
    """
    def post_init(self, custom_args):
        self.custom_args = custom_args
        arch = platform.machine()
        if arch == 'x86_64':
            self.arch = arch
        else:
            raise KiwiBootLoaderGrubPlatformError(
                'host architecture %s not supported for grub2 setup' % arch)

        self.terminal = 'gfxterm'
        self.bootpath = self.get_boot_path()
        self.gfxmode = self.__get_gfxmode()
        self.theme = self.get_boot_theme()
        self.timeout = self.get_boot_timeout_seconds()
        self.failsafe_boot = self.failsafe_boot_entry_requested()
        self.hypervisor_domain = self.get_hypervisor_domain()
        self.firmware = FirmWare(self.xml_state)

        self.hybrid_boot = True
        self.multiboot = False
        if self.hypervisor_domain:
            if self.hypervisor_domain == 'dom0':
                self.hybrid_boot = False
                self.multiboot = True
            elif self.hypervisor_domain == 'domU':
                self.hybrid_boot = False
                self.multiboot = False

        self.xen_guest = False
        if self.hypervisor_domain == 'domU' or self.firmware.ec2_mode():
            self.xen_guest = True

        self.grub2 = BootLoaderTemplateGrub2()
        self.config = None
        self.efi_boot_path = None
        self.boot_directory_name = 'grub2'

    def write(self):
        """
            Write grub.cfg file to all required places
        """
        log.info('Writing grub.cfg file')
        config_dir = self.__get_grub_boot_path()
        config_file = config_dir + '/grub.cfg'
        if self.config:
            Path.create(config_dir)
            with open(config_file, 'w') as config:
                config.write(self.config)

            if self.efi_boot_path:
                config_file = self.efi_boot_path + '/grub.cfg'
                with open(config_file, 'w') as config:
                    config.write(self.config)

    def setup_disk_image_config(self,
                                uuid,
                                hypervisor='xen.gz',
                                kernel='linux.vmx',
                                initrd='initrd.vmx'):
        """
            Create the grub.cfg in memory from a template suitable to boot
            from a disk image
        """
        log.info('Creating grub config file from template')
        cmdline = self.get_boot_cmdline(uuid)
        cmdline_failsafe = ' '.join(
            [cmdline, self.get_failsafe_kernel_options()])
        parameters = {
            'search_params': '--fs-uuid --set=root ' + uuid,
            'default_boot': '0',
            'kernel_file': kernel,
            'initrd_file': initrd,
            'boot_options': cmdline,
            'failsafe_boot_options': cmdline_failsafe,
            'gfxmode': self.gfxmode,
            'theme': self.theme,
            'boot_timeout': self.timeout,
            'title': self.get_menu_entry_title(),
            'bootpath': self.bootpath,
        }
        if self.multiboot:
            log.info('--> Using multiboot disk template')
            parameters['hypervisor'] = hypervisor
            template = self.grub2.get_multiboot_disk_template(
                self.failsafe_boot, self.terminal)
        else:
            log.info('--> Using EFI/BIOS hybrid boot disk template')
            template = self.grub2.get_disk_template(self.failsafe_boot,
                                                    self.hybrid_boot,
                                                    self.terminal)
        try:
            self.config = template.substitute(parameters)
        except Exception as e:
            raise KiwiTemplateError('%s: %s' % (type(e).__name__, format(e)))

    def setup_install_image_config(self,
                                   mbrid,
                                   hypervisor='xen.gz',
                                   kernel='linux',
                                   initrd='initrd'):
        """
            Create the grub.cfg in memory from a template suitable to boot
            from an ISO image in EFI boot mode
        """
        log.info('Creating grub install config file from template')
        cmdline = self.get_boot_cmdline()
        cmdline_failsafe = ' '.join(
            [cmdline, self.get_failsafe_kernel_options()])
        parameters = {
            'search_params': '--file --set=root /boot/' + mbrid.get_id(),
            'default_boot': '0',
            'kernel_file': kernel,
            'initrd_file': initrd,
            'boot_options': cmdline,
            'failsafe_boot_options': cmdline_failsafe,
            'gfxmode': self.gfxmode,
            'theme': self.theme,
            'boot_timeout': self.timeout,
            'title': self.get_menu_entry_install_title(),
            'bootpath': '/boot/x86_64/loader',
        }
        if self.multiboot:
            log.info('--> Using EFI multiboot install template')
            parameters['hypervisor'] = hypervisor
            template = self.grub2.get_multiboot_install_template(
                self.failsafe_boot, self.terminal)
        else:
            log.info('--> Using EFI boot install template')
            hybrid_boot = True
            template = self.grub2.get_install_template(self.failsafe_boot,
                                                       hybrid_boot,
                                                       self.terminal)
        try:
            self.config = template.substitute(parameters)
        except Exception as e:
            raise KiwiTemplateError('%s: %s' % (type(e).__name__, format(e)))

    def setup_live_image_config(self,
                                mbrid,
                                hypervisor='xen.gz',
                                kernel='linux',
                                initrd='initrd'):
        """
            Create the grub.cfg in memory from a template suitable to boot
            a live system from an ISO image in EFI boot mode
        """
        log.info('Creating grub live ISO config file from template')
        cmdline = self.get_boot_cmdline()
        cmdline_failsafe = ' '.join(
            [cmdline, self.get_failsafe_kernel_options()])
        parameters = {
            'search_params': '--file --set=root /boot/' + mbrid.get_id(),
            'default_boot': '0',
            'kernel_file': kernel,
            'initrd_file': initrd,
            'boot_options': cmdline,
            'failsafe_boot_options': cmdline_failsafe,
            'gfxmode': self.gfxmode,
            'theme': self.theme,
            'boot_timeout': self.timeout,
            'title': self.get_menu_entry_title(plain=True),
            'bootpath': '/boot/x86_64/loader',
        }
        if self.multiboot:
            log.info('--> Using EFI multiboot template')
            parameters['hypervisor'] = hypervisor
            template = self.grub2.get_multiboot_iso_template(
                self.failsafe_boot, self.terminal)
        else:
            log.info('--> Using EFI boot template')
            hybrid_boot = True
            template = self.grub2.get_iso_template(self.failsafe_boot,
                                                   hybrid_boot, self.terminal)
        try:
            self.config = template.substitute(parameters)
        except Exception as e:
            raise KiwiTemplateError('%s: %s' % (type(e).__name__, format(e)))

    def setup_install_boot_images(self, mbrid, lookup_path=None):
        """
            Using grub2 to boot an install media means to support EFI
            boot of the install media. Therefore an EFI image needs to
            be build or used and transfered into an embedded vfat image.
            The non EFI boot of the install media is handled in the
            isolinux boot loader configuration
        """
        log.info('Creating grub bootloader images')
        self.efi_boot_path = self.create_efi_path(in_sub_dir='')

        log.info('--> Creating identifier file %s', mbrid.get_id())
        Path.create(self.__get_grub_boot_path())
        mbrid.write(self.root_dir + '/boot/' + mbrid.get_id())
        mbrid.write(self.root_dir + '/boot/mbrid')

        self.__copy_theme_data_to_boot_directory(lookup_path)

        if self.firmware.efi_mode() == 'uefi':
            log.info('--> Using signed secure boot efi image')
            self.__setup_secure_boot_efi_image(lookup_path)
        else:
            log.info('--> Creating unsigned efi image')
            self.__copy_efi_modules_to_boot_directory(lookup_path)
            self.__create_efi_image(mbrid=mbrid)

        self.__create_embedded_fat_efi_image()

    def setup_live_boot_images(self, mbrid, lookup_path=None):
        # same action as for install media
        self.setup_install_boot_images(mbrid, lookup_path)

    def setup_disk_boot_images(self, boot_uuid, lookup_path=None):
        """
            EFI and bios images needs to be build or used if provided
            by the distribution
        """
        log.info('Creating grub bootloader images')

        if self.firmware.efi_mode():
            self.efi_boot_path = self.create_efi_path()

        self.__copy_theme_data_to_boot_directory(lookup_path)

        if self.firmware.efi_mode() == 'efi':
            log.info('--> Creating unsigned efi image')
            self.__copy_efi_modules_to_boot_directory(lookup_path)
            self.__create_efi_image(uuid=boot_uuid)
        elif self.firmware.efi_mode() == 'uefi':
            log.info('--> Using signed secure boot efi image')
            self.__setup_secure_boot_efi_image(lookup_path)

        log.info('--> Creating bios core image')
        self.__copy_bios_modules_to_boot_directory(lookup_path)
        self.__create_bios_boot_image(boot_uuid)

    def __setup_secure_boot_efi_image(self, lookup_path):
        """
            use prebuilt and signed efi images provided by the distribution
        """
        secure_efi_lookup_path = self.root_dir + '/usr/lib64/efi/'
        if lookup_path:
            secure_efi_lookup_path = lookup_path
        shim_image = secure_efi_lookup_path + Defaults.get_shim_name()
        if not os.path.exists(shim_image):
            raise KiwiBootLoaderGrubSecureBootError(
                'Microsoft signed shim loader %s not found' % shim_image)
        grub_image = secure_efi_lookup_path + Defaults.get_signed_grub_name()
        if not os.path.exists(grub_image):
            raise KiwiBootLoaderGrubSecureBootError(
                'Signed grub2 efi loader %s not found' % grub_image)
        Command.run(['cp', shim_image, self.__get_efi_image_name()])
        Command.run(['cp', grub_image, self.efi_boot_path])

    def __create_embedded_fat_efi_image(self):
        Path.create(self.root_dir + '/boot/' + self.arch)
        efi_fat_image = ''.join([self.root_dir + '/boot/', self.arch, '/efi'])
        Command.run(['qemu-img', 'create', efi_fat_image, '4M'])
        Command.run(['mkdosfs', '-n', 'BOOT', efi_fat_image])
        Command.run([
            'mcopy', '-Do', '-s', '-i', efi_fat_image, self.root_dir + '/EFI',
            '::'
        ])

    def __create_efi_image(self, uuid=None, mbrid=None):
        """
            create efi image
        """
        early_boot_script = self.efi_boot_path + '/earlyboot.cfg'
        if uuid:
            self.__create_early_boot_script_for_uuid_search(
                early_boot_script, uuid)
        else:
            self.__create_early_boot_script_for_mbrid_search(
                early_boot_script, mbrid)
        Command.run([
            'grub2-mkimage', '-O',
            self.__get_efi_format(), '-o',
            self.__get_efi_image_name(), '-c', early_boot_script, '-p',
            self.get_boot_path() + '/' + self.boot_directory_name, '-d',
            self.__get_grub_boot_path() + '/' + self.__get_efi_format()
        ] + self.__get_efi_modules())

    def __create_bios_boot_image(self, uuid):
        """
            create bios image
        """
        early_boot_script = self.__get_grub_boot_path() + '/earlyboot.cfg'
        self.__create_early_boot_script_for_uuid_search(
            early_boot_script, uuid)
        Command.run([
            'grub2-mkimage', '-O',
            self.__get_bios_format(), '-o',
            self.__get_bios_image_name(), '-c', early_boot_script, '-p',
            self.get_boot_path() + '/' + self.boot_directory_name, '-d',
            self.__get_grub_boot_path() + '/' + self.__get_bios_format()
        ] + self.__get_bios_modules())

    def __create_early_boot_script_for_uuid_search(self, filename, uuid):
        with open(filename, 'w') as early_boot:
            early_boot.write('search --fs-uuid --set=root %s\n' % uuid)
            early_boot.write('set prefix=($root)%s/%s\n' %
                             (self.get_boot_path(), self.boot_directory_name))

    def __create_early_boot_script_for_mbrid_search(self, filename, mbrid):
        with open(filename, 'w') as early_boot:
            early_boot.write('search --file --set=root /boot/%s\n' %
                             mbrid.get_id())
            early_boot.write('set prefix=($root)/boot/%s\n' %
                             self.boot_directory_name)

    def __get_grub_boot_path(self):
        return self.root_dir + '/boot/' + self.boot_directory_name

    def __get_basic_modules(self):
        modules = [
            'ext2', 'iso9660', 'linux', 'echo', 'configfile', 'search_label',
            'search_fs_file', 'search', 'search_fs_uuid', 'ls', 'normal',
            'gzio', 'png', 'fat', 'gettext', 'font', 'minicmd', 'gfxterm',
            'gfxmenu', 'video', 'video_fb', 'xfs', 'btrfs', 'lvm', 'multiboot'
        ]
        return modules

    def __get_efi_modules(self):
        modules = self.__get_basic_modules() + [
            'part_gpt', 'efi_gop', 'efi_uga', 'linuxefi'
        ]
        return modules

    def __get_bios_modules(self):
        modules = self.__get_basic_modules() + [
            'part_gpt', 'part_msdos', 'biosdisk', 'vga', 'vbe', 'chain', 'boot'
        ]
        return modules

    def __get_efi_image_name(self):
        efi_image_name = None
        if self.arch == 'x86_64':
            efi_image_name = 'bootx64.efi'
        if efi_image_name:
            return ''.join([self.efi_boot_path, '/', efi_image_name])

    def __get_bios_image_name(self):
        return ''.join([
            self.__get_grub_boot_path(), '/',
            self.__get_bios_format(), '/core.img'
        ])

    def __get_efi_format(self):
        if self.arch == 'x86_64':
            return 'x86_64-efi'

    def __get_bios_format(self):
        return 'i386-pc'

    def __get_xen_format(self):
        return 'x86_64-xen'

    def __get_efi_modules_path(self, lookup_path=None):
        return self.__get_module_path(self.__get_efi_format(), lookup_path)

    def __get_bios_modules_path(self, lookup_path=None):
        return self.__get_module_path(self.__get_bios_format(), lookup_path)

    def __get_xen_modules_path(self, lookup_path=None):
        return self.__get_module_path(self.__get_xen_format(), lookup_path)

    def __get_module_path(self, format_name, lookup_path=None):
        if not lookup_path:
            lookup_path = self.root_dir
        return ''.join([
            self.__find_grub_data(lookup_path + '/usr/lib'), '/', format_name
        ])

    def __get_gfxmode(self):
        selected_gfxmode = '800x600'
        gfxmode = {
            '0x301': '640x480',
            '0x310': '640x480',
            '0x311': '640x480',
            '0x312': '640x480',
            '0x303': '800x600',
            '0x313': '800x600',
            '0x314': '800x600',
            '0x315': '800x600',
            '0x305': '1024x768',
            '0x316': '1024x768',
            '0x317': '1024x768',
            '0x318': '1024x768',
            '0x307': '1280x1024',
            '0x319': '1280x1024',
            '0x31a': '1280x1024',
            '0x31b': '1280x1024',
        }
        requested_gfxmode = self.xml_state.build_type.get_vga()
        if requested_gfxmode in gfxmode:
            selected_gfxmode = gfxmode[requested_gfxmode]
        return selected_gfxmode

    def __copy_theme_data_to_boot_directory(self, lookup_path):
        if not lookup_path:
            lookup_path = self.root_dir
        boot_unicode_font = self.root_dir + '/boot/unicode.pf2'
        if not os.path.exists(boot_unicode_font):
            unicode_font = self.__find_grub_data(lookup_path + '/usr/share') + \
                '/unicode.pf2'
            try:
                Command.run(['cp', unicode_font, boot_unicode_font])
            except Exception:
                raise KiwiBootLoaderGrubFontError('Unicode font %s not found' %
                                                  unicode_font)

        boot_theme_dir = self.root_dir + '/boot/' + \
            self.boot_directory_name + '/themes'
        if self.theme and not os.path.exists(boot_theme_dir):
            Path.create(boot_theme_dir)
            theme_dir = self.__find_grub_data(lookup_path + '/usr/share') + \
                '/themes/' + self.theme
            if os.path.exists(theme_dir):
                Command.run(['rsync', '-zav', theme_dir, boot_theme_dir], )
            else:
                log.warning('Theme %s not found', theme_dir)

    def __copy_efi_modules_to_boot_directory(self, lookup_path):
        self.__copy_modules_to_boot_directory_from(
            self.__get_efi_modules_path(lookup_path))

    def __copy_bios_modules_to_boot_directory(self, lookup_path):
        self.__copy_modules_to_boot_directory_from(
            self.__get_bios_modules_path(lookup_path))
        if self.xen_guest:
            self.__copy_modules_to_boot_directory_from(
                self.__get_xen_modules_path(lookup_path))

    def __copy_modules_to_boot_directory_from(self, module_path):
        boot_module_path = \
            self.__get_grub_boot_path() + '/' + os.path.basename(module_path)
        if not os.path.exists(boot_module_path):
            try:
                Command.run(['cp', '-a', module_path, boot_module_path])
            except Exception:
                raise KiwiBootLoaderGrubModulesError(
                    'grub2 modules %s not found' % module_path)

    def __find_grub_data(self, lookup_path):
        """
            depending on the distribution grub could be installed below
            a grub2 or grub directory. Therefore this information needs
            to be dynamically looked up
        """
        for grub_name in ['grub2', 'grub']:
            grub_path = lookup_path + '/' + grub_name
            if os.path.exists(grub_path):
                return grub_path

        raise KiwiBootLoaderGrubDataError('No grub2 installation found in %s' %
                                          lookup_path)
コード例 #18
0
ファイル: live_image_builder.py プロジェクト: k0da/kiwi-1
class LiveImageBuilder(object):
    """
        Live image builder
    """
    def __init__(self, xml_state, target_dir, root_dir):
        self.media_dir = None
        self.arch = platform.machine()
        self.root_dir = root_dir
        self.target_dir = target_dir
        self.xml_state = xml_state
        self.live_type = xml_state.build_type.get_flags()
        self.types = Defaults.get_live_iso_types()
        self.hybrid = xml_state.build_type.get_hybrid()
        self.volume_id = xml_state.build_type.get_volid()
        self.machine = xml_state.get_build_type_machine_section()
        self.mbrid = ImageIdentifier()
        self.mbrid.calculate_id()

        if not self.live_type:
            self.live_type = Defaults.get_default_live_iso_type()

        self.boot_image_task = BootImageTask(
            'kiwi', xml_state, target_dir
        )
        self.firmware = FirmWare(
            xml_state
        )
        self.system_setup = SystemSetup(
            xml_state=xml_state, description_dir=None, root_dir=self.root_dir
        )
        self.isoname = ''.join(
            [
                target_dir, '/',
                xml_state.xml_data.get_name(),
                '.' + platform.machine(),
                '-' + xml_state.get_image_version(),
                '.iso'
            ]
        )
        self.live_image_file = ''.join(
            [
                target_dir, '/',
                xml_state.xml_data.get_name(),
                '-read-only.', self.arch, '-',
                xml_state.get_image_version()
            ]
        )
        self.result = Result()

    def create(self):
        # media dir to store CD contents
        self.media_dir = mkdtemp(
            prefix='live-media.', dir=self.target_dir
        )
        rootsize = SystemSize(self.media_dir)

        # custom iso metadata
        log.info('Using following live ISO metadata:')
        log.info('--> Application id: %s', self.mbrid.get_id())
        log.info('--> Publisher: %s', Defaults.get_publisher())
        custom_iso_args = [
            '-A', self.mbrid.get_id(),
            '-p', '"' + Defaults.get_preparer() + '"',
            '-publisher', '"' + Defaults.get_publisher() + '"',
        ]
        if self.volume_id:
            log.info('--> Volume id: %s', self.volume_id)
            custom_iso_args.append('-V')
            custom_iso_args.append('"' + self.volume_id + '"')

        # prepare boot(initrd) root system
        log.info('Preparing live ISO boot system')
        self.boot_image_task.prepare()

        # export modprobe configuration to boot image
        self.system_setup.export_modprobe_setup(
            self.boot_image_task.boot_root_directory
        )

        # pack system into live boot structure
        log.info('Packing system into live ISO type: %s', self.live_type)
        if self.live_type in self.types:
            live_type_image = FileSystem(
                name=self.types[self.live_type],
                device_provider=None,
                root_dir=self.root_dir
            )
            live_type_image.create_on_file(self.live_image_file)
            Command.run(
                ['mv', self.live_image_file, self.media_dir]
            )
            self.__create_live_iso_client_config(self.live_type)
        else:
            raise KiwiLiveBootImageError(
                'live ISO type "%s" not supported' % self.live_type
            )

        # setup bootloader config to boot the ISO via isolinux
        log.info('Setting up isolinux bootloader configuration')
        bootloader_config_isolinux = BootLoaderConfig(
            'isolinux', self.xml_state, self.media_dir
        )
        bootloader_config_isolinux.setup_live_boot_images(
            mbrid=None,
            lookup_path=self.boot_image_task.boot_root_directory
        )
        bootloader_config_isolinux.setup_live_image_config(
            mbrid=None
        )
        bootloader_config_isolinux.write()

        # setup bootloader config to boot the ISO via EFI
        if self.firmware.efi_mode():
            log.info('Setting up EFI grub bootloader configuration')
            bootloader_config_grub = BootLoaderConfig(
                'grub2', self.xml_state, self.media_dir
            )
            bootloader_config_grub.setup_live_boot_images(
                mbrid=self.mbrid,
                lookup_path=self.boot_image_task.boot_root_directory
            )
            bootloader_config_grub.setup_live_image_config(
                mbrid=self.mbrid
            )
            bootloader_config_grub.write()

        # create initrd for live image
        log.info('Creating live ISO boot image')
        self.__create_live_iso_kernel_and_initrd()

        # calculate size and decide if we need UDF
        if rootsize.accumulate_mbyte_file_sizes() > 4096:
            log.info('ISO exceeds 4G size, using UDF filesystem')
            custom_iso_args.append('-allow-limited-size')
            custom_iso_args.append('-udf')

        # create iso filesystem from media_dir
        log.info('Creating live ISO image')
        iso_image = FileSystemIsoFs(
            device_provider=None,
            root_dir=self.media_dir,
            custom_args=custom_iso_args
        )
        iso_header_offset = iso_image.create_on_file(self.isoname)

        # make it hybrid
        if self.hybrid:
            Iso.create_hybrid(
                iso_header_offset, self.mbrid, self.isoname
            )

        self.result.add(
            'live_image', self.isoname
        )
        return self.result

    def __create_live_iso_kernel_and_initrd(self):
        boot_path = self.media_dir + '/boot/x86_64/loader'
        Path.create(boot_path)
        kernel = Kernel(self.boot_image_task.boot_root_directory)
        if kernel.get_kernel():
            kernel.copy_kernel(boot_path, '/linux')
        else:
            raise KiwiLiveBootImageError(
                'No kernel in boot image tree %s found' %
                self.boot_image_task.boot_root_directory
            )
        if self.machine and self.machine.get_domain() == 'dom0':
            if kernel.get_xen_hypervisor():
                kernel.copy_xen_hypervisor(boot_path, '/xen.gz')
            else:
                raise KiwiLiveBootImageError(
                    'No hypervisor in boot image tree %s found' %
                    self.boot_image_task.boot_root_directory
                )
        self.boot_image_task.create_initrd(self.mbrid)
        Command.run(
            [
                'mv', self.boot_image_task.initrd_filename,
                boot_path + '/initrd'
            ]
        )

    def __create_live_iso_client_config(self, iso_type):
        """
            Setup IMAGE and UNIONFS_CONFIG variables as they are used in
            the kiwi isoboot code. Variable contents:

            + IMAGE=target_device;live_iso_name_definition
            + UNIONFS_CONFIG=rw_device,ro_device,union_type

            If no real block device is used or can be predefined the
            word 'loop' is set as a placeholder or indicator to use a loop
            device. For more details please refer to the kiwi shell boot
            code
        """
        iso_client_config_file = self.media_dir + '/config.isoclient'
        iso_client_params = Defaults.get_live_iso_client_parameters()
        (system_device, union_device, union_type) = iso_client_params[iso_type]

        with open(iso_client_config_file, 'w') as config:
            config.write(
                'IMAGE="%s;%s.%s;%s"\n' % (
                    system_device,
                    self.xml_state.xml_data.get_name(), self.arch,
                    self.xml_state.get_image_version()
                )
            )
            config.write(
                'UNIONFS_CONFIG="%s,loop,%s"\n' %
                (union_device, union_type)
            )

    def __del__(self):
        if self.media_dir:
            log.info('Cleaning up %s instance', type(self).__name__)
            Path.wipe(self.media_dir)