예제 #1
0
    def create_initrd(self,
                      mbrid: Optional[SystemIdentifier] = None,
                      basename: Optional[str] = None,
                      install_initrd: bool = False) -> None:
        """
        Create initrd from prepared boot system tree and compress the result

        :param SystemIdentifier mbrid: instance of ImageIdentifier
        :param str basename: base initrd file name
        :param bool install_initrd: installation media initrd

        """
        if self.is_prepared():
            log.info('Creating initrd cpio archive')
            # we can't simply exclude boot when building the archive
            # because the file boot/mbrid must be preserved. Because of
            # that we create a copy of the boot directory and remove
            # everything in boot/ except for boot/mbrid. The original
            # boot directory should not be changed because we rely
            # on other data in boot/ e.g the kernel to be available
            # for the entire image building process
            if basename:
                kiwi_initrd_basename = basename
            else:
                kiwi_initrd_basename = self.initrd_base_name
            temp_boot_root = Temporary(prefix='kiwi_boot_root_copy.').new_dir()
            temp_boot_root_directory = temp_boot_root.name
            os.chmod(temp_boot_root_directory, 0o755)
            data = DataSync(self.boot_root_directory + '/',
                            temp_boot_root_directory)
            data.sync_data(options=['-a'])
            boot_directory = temp_boot_root_directory + '/boot'
            Path.wipe(boot_directory)
            if mbrid:
                log.info('--> Importing mbrid: %s', mbrid.get_id())
                Path.create(boot_directory)
                image_identifier = boot_directory + '/mbrid'
                mbrid.write(image_identifier)

            cpio = ArchiveCpio(
                os.sep.join([self.target_dir, kiwi_initrd_basename]))
            # the following is a list of directories which were needed
            # during the process of creating an image but not when the
            # image is actually booting with this initrd
            exclude_from_archive = [
                '/' + Defaults.get_shared_cache_location(), '/image',
                '/usr/lib/grub*'
            ]
            # the following is a list of directories to exclude which
            # are not needed inside of the initrd
            exclude_from_archive += [
                '/usr/share/doc', '/usr/share/man', '/home', '/media', '/srv'
            ]
            cpio.create(source_dir=temp_boot_root_directory,
                        exclude=exclude_from_archive)
            log.info('--> xz compressing archive')
            compress = Compress(
                os.sep.join([self.target_dir, kiwi_initrd_basename]))
            compress.xz(['--check=crc32', '--lzma2=dict=1MiB', '--threads=0'])
            self.initrd_filename = compress.compressed_filename
예제 #2
0
class TestCompress(object):
    @patch('os.path.exists')
    def setup(self, mock_exists):
        mock_exists.return_value = True
        self.compress = Compress('some-file', True)

    @raises(KiwiFileNotFound)
    def test_source_file_not_found(self):
        Compress('some-file')

    @patch('kiwi.command.Command.run')
    def test_xz(self, mock_command):
        self.compress.xz()
        mock_command.assert_called_once_with([
            'xz', '-f', '--check=crc32', '--lzma2=dict=512KiB', '--keep',
            'some-file'
        ])
        assert self.compress.compressed_filename == 'some-file.xz'

    @patch('kiwi.command.Command.run')
    def test_gzip(self, mock_command):
        self.compress.gzip()
        mock_command.assert_called_once_with(
            ['gzip', '-f', '-9', '--keep', 'some-file'])
        assert self.compress.compressed_filename == 'some-file.gz'

    @patch('kiwi.command.Command.run')
    @patch('kiwi.utils.compress.NamedTemporaryFile')
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress(self, mock_format, mock_temp, mock_command):
        mock_format.return_value = 'xz'
        self.compress.uncompress()
        mock_command.assert_called_once_with(['xz', '-d', 'some-file'])
        assert self.compress.uncompressed_filename == 'some-file'

    @patch('kiwi.command.Command.run')
    @patch('kiwi.utils.compress.NamedTemporaryFile')
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress_temporary(self, mock_format, mock_temp, mock_command):
        tempfile = mock.Mock()
        tempfile.name = 'tempfile'
        mock_temp.return_value = tempfile
        mock_format.return_value = 'xz'
        self.compress.uncompress(temporary=True)
        mock_command.assert_called_once_with(
            ['bash', '-c', 'xz -c -d some-file > tempfile'])
        assert self.compress.uncompressed_filename == 'tempfile'

    @raises(KiwiCompressionFormatUnknown)
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress_unknown_format(self, mock_format):
        mock_format.return_value = None
        self.compress.uncompress()

    def test_get_format(self):
        xz = Compress('../data/xz_data.xz')
        assert xz.get_format() == 'xz'
        gzip = Compress('../data/gz_data.gz')
        assert gzip.get_format() == 'gzip'
예제 #3
0
파일: install.py 프로젝트: michal42/kiwi-1
    def create_install_pxe_archive(self):
        """
        Create an oem install tar archive suitable for installing a
        disk image via the network using the PXE boot protocol.
        The archive contains the raw disk image and its checksum
        as well as an install initrd and kernel plus the required
        kernel commandline information which needs to be added
        as append line in the pxelinux config file on the boot
        server

        Image types which triggers this builder are:

        * installpxe="true|false"
        """
        self.pxe_dir = mkdtemp(prefix='kiwi_pxe_install_media.',
                               dir=self.target_dir)
        # the system image is transfered as xz compressed variant
        log.info('xz compressing disk image')
        pxe_image_filename = ''.join(
            [self.pxe_dir, '/',
             self.xml_state.xml_data.get_name(), '.xz'])
        compress = Compress(source_filename=self.diskname,
                            keep_source_on_compress=True)
        compress.xz(self.xz_options)
        Command.run(['mv', compress.compressed_filename, pxe_image_filename])

        # the system image transfer is checked against a checksum
        log.info('Creating disk image checksum')
        pxe_md5_filename = ''.join(
            [self.pxe_dir, '/',
             self.xml_state.xml_data.get_name(), '.md5'])
        checksum = Checksum(self.diskname)
        checksum.md5(pxe_md5_filename)

        # the kiwi initrd code triggers the install by trigger files
        self._create_pxe_install_trigger_files()

        # create pxe config append information
        # this information helps to configure the boot server correctly
        append_filename = ''.join(
            [self.pxe_dir, '/',
             self.xml_state.xml_data.get_name(), '.append'])
        cmdline = 'pxe=1'
        custom_cmdline = self.xml_state.build_type.get_kernelcmdline()
        if custom_cmdline:
            cmdline += ' ' + custom_cmdline
        with open(append_filename, 'w') as append:
            append.write('%s\n' % cmdline)

        # create initrd for pxe install
        log.info('Creating pxe install boot image')
        self._create_pxe_install_kernel_and_initrd()

        # create pxe install tarball
        log.info('Creating pxe install archive')
        archive = ArchiveTar(self.pxename.replace('.xz', ''))
        archive.create_xz_compressed(self.pxe_dir, xz_options=self.xz_options)
예제 #4
0
    def create_initrd(self, mbrid=None):
        """
        Create initrd from prepared boot system tree and compress the result

        :param object mbrid: instance of ImageIdentifier
        """
        if self.is_prepared():
            log.info('Creating initrd cpio archive')
            # we can't simply exclude boot when building the archive
            # because the file boot/mbrid must be preserved. Because of
            # that we create a copy of the boot directory and remove
            # everything in boot/ except for boot/mbrid. The original
            # boot directory should not be changed because we rely
            # on other data in boot/ e.g the kernel to be available
            # for the entire image building process
            temp_boot_root_directory = mkdtemp(prefix='kiwi_boot_root_copy.')
            self.temp_directories.append(temp_boot_root_directory)
            data = DataSync(self.boot_root_directory + '/',
                            temp_boot_root_directory)
            data.sync_data(options=['-z', '-a'])
            boot_directory = temp_boot_root_directory + '/boot'
            Path.wipe(boot_directory)
            if mbrid:
                log.info('--> Importing mbrid: %s', mbrid.get_id())
                Path.create(boot_directory)
                image_identifier = boot_directory + '/mbrid'
                mbrid.write(image_identifier)

            cpio = ArchiveCpio(
                os.sep.join([self.target_dir, self.initrd_base_name]))
            # the following is a list of directories which were needed
            # during the process of creating an image but not when the
            # image is actually booting with this initrd
            exclude_from_archive = [
                '/' + Defaults.get_shared_cache_location(), '/image',
                '/usr/lib/grub*'
            ]
            # the following is a list of directories to exclude which
            # are not needed inside of the initrd
            exclude_from_archive += [
                '/usr/share/doc', '/usr/share/man', '/home', '/media', '/srv'
            ]
            cpio.create(source_dir=temp_boot_root_directory,
                        exclude=exclude_from_archive)
            log.info('--> xz compressing archive')
            compress = Compress(
                os.sep.join([self.target_dir, self.initrd_base_name]))
            compress.xz()
            self.initrd_filename = compress.compressed_filename
예제 #5
0
파일: docker.py 프로젝트: Conan-Kudo/kiwi
    def pack_image_to_file(self, filename):
        """
        Packs the given oci image into the given filename.

        :param string filename: file name of the resulting packed image
        """
        oci_image = os.sep.join([
            self.oci_dir, ':'.join(['umoci_layout', self.container_tag])
        ])

        additional_tags = []
        for tag in self.additional_tags:
            additional_tags.extend([
                '--additional-tag', '{0}:{1}'.format(self.container_name, tag)
            ])

        # make sure the target tar file does not exist
        # skopeo doesn't support force overwrite
        Path.wipe(filename)
        Command.run(
            [
                'skopeo', 'copy', 'oci:{0}'.format(
                    oci_image
                ),
                'docker-archive:{0}:{1}:{2}'.format(
                    filename, self.container_name, self.container_tag
                )
            ] + additional_tags
        )
        container_compressor = self.runtime_config.get_container_compression()
        if container_compressor:
            compressor = Compress(filename)
            return compressor.xz(self.runtime_config.get_xz_options())
        else:
            return filename
예제 #6
0
파일: docker.py 프로젝트: hwoarang/kiwi
    def pack_image_to_file(self, filename):
        """
        Packs the given oci image into the given filename.

        :param string filename: file name of the resulting packed image
        """
        additional_tags = []
        if 'additional_tags' in self.oci_config:
            for tag in self.oci_config['additional_tags']:
                additional_tags.extend([
                    '--additional-tag',
                    '{0}:{1}'.format(self.oci_config['container_name'], tag)
                ])

        # make sure the target tar file does not exist
        # skopeo doesn't support force overwrite
        Path.wipe(filename)
        Command.run([
            'skopeo', 'copy', 'oci:{0}'.format(self.oci.container_name),
            'docker-archive:{0}:{1}:{2}'.format(
                filename, self.oci_config['container_name'],
                self.oci_config['container_tag'])
        ] + additional_tags)
        container_compressor = self.runtime_config.get_container_compression()
        if container_compressor:
            compressor = Compress(filename)
            return compressor.xz(self.runtime_config.get_xz_options())
        else:
            return filename
예제 #7
0
    def create(self, filename, base_image):
        """
        Create compressed oci system container tar archive

        :param string filename: archive file name
        :param string base_image: archive used as a base image
        """
        exclude_list = Defaults.get_exclude_list_for_root_data_sync()
        exclude_list.append('boot')
        exclude_list.append('dev')
        exclude_list.append('sys')
        exclude_list.append('proc')

        oci = OCI()
        if base_image:
            oci.import_container_image(
                'oci-archive:{0}:{1}'.format(
                    base_image, Defaults.get_container_base_image_tag()
                )
            )
        else:
            oci.init_container()

        image_ref = '{0}:{1}'.format(
            self.oci_config['container_name'], self.oci_config['container_tag']
        )

        oci.unpack()
        oci.sync_rootfs(self.root_dir, exclude_list)
        oci.repack(self.oci_config)
        oci.set_config(self.oci_config)
        oci.post_process()

        if self.archive_transport == 'docker-archive':
            image_ref = '{0}:{1}'.format(
                self.oci_config['container_name'],
                self.oci_config['container_tag']
            )
            additional_refs = []
            if 'additional_tags' in self.oci_config:
                additional_refs = []
                for tag in self.oci_config['additional_tags']:
                    additional_refs.append('{0}:{1}'.format(
                        self.oci_config['container_name'], tag
                    ))
        else:
            image_ref = self.oci_config['container_tag']
            additional_refs = []

        oci.export_container_image(
            filename, self.archive_transport, image_ref, additional_refs
        )

        if self.runtime_config.get_container_compression():
            compressor = Compress(filename)
            return compressor.xz(self.runtime_config.get_xz_options())
        else:
            return filename
예제 #8
0
파일: docker.py 프로젝트: michal42/kiwi-1
    def pack_image_to_file(self, filename):
        """
        Packs the given oci image into the given filename.

        :param string filename: file name of the resulting packed image
        """
        docker_tarfile = filename.replace('.xz', '')
        oci_image = os.sep.join(
            [self.oci_dir, ':'.join(['umoci_layout', self.container_tag])])

        # make sure the target tar file does not exist
        # skopeo doesn't support force overwrite
        Path.wipe(docker_tarfile)
        Command.run([
            'skopeo', 'copy', 'oci:{0}'.format(oci_image),
            'docker-archive:{0}:{1}:{2}'.format(docker_tarfile,
                                                self.container_name,
                                                self.container_tag)
        ])
        compressor = Compress(docker_tarfile)
        compressor.xz(self.xz_options)
예제 #9
0
    def create(self):
        """
        Build a pxe image set consisting out of a boot image(initrd)
        plus its appropriate kernel files and the root filesystem
        image with a checksum. The result can be used within the kiwi
        PXE boot infrastructure

        Image types which triggers this builder are:

        * image="pxe"

        :raises KiwiPxeBootImageError: if no kernel or hipervisor is found
            in boot image tree
        :return: result

        :rtype: instance of :class:`Result`
        """
        log.info('Creating PXE root filesystem image')
        self.filesystem.create()
        os.rename(self.filesystem.filename, self.image_name)
        self.image = self.image_name
        if self.compressed:
            log.info('xz compressing root filesystem image')
            compress = Compress(self.image)
            compress.xz(self.xz_options)
            self.image = compress.compressed_filename

        log.info('Creating PXE root filesystem MD5 checksum')
        checksum = Checksum(self.image)
        checksum.md5(self.checksum_name)

        # prepare boot(initrd) root system
        log.info('Creating PXE boot image')
        self.boot_image_task.prepare()

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

        # extract kernel from boot(initrd) root system
        kernel = Kernel(self.boot_image_task.boot_root_directory)
        kernel_data = kernel.get_kernel()
        if kernel_data:
            self.kernel_filename = ''.join([
                os.path.basename(self.image_name), '-', kernel_data.version,
                '.kernel'
            ])
            kernel.copy_kernel(self.target_dir, self.kernel_filename)
        else:
            raise KiwiPxeBootImageError(
                'No kernel in boot image tree %s found' %
                self.boot_image_task.boot_root_directory)

        # extract hypervisor from boot(initrd) root system
        if self.xen_server:
            kernel_data = kernel.get_xen_hypervisor()
            if kernel_data:
                self.hypervisor_filename = ''.join(
                    [os.path.basename(self.image_name), '-', kernel_data.name])
                kernel.copy_xen_hypervisor(self.target_dir,
                                           self.hypervisor_filename)
                self.result.add(key='xen_hypervisor',
                                filename=self.target_dir + '/' +
                                self.hypervisor_filename,
                                use_for_bundle=True,
                                compress=False,
                                shasum=True)
            else:
                raise KiwiPxeBootImageError(
                    'No hypervisor in boot image tree %s found' %
                    self.boot_image_task.boot_root_directory)

        # create initrd for pxe boot
        self.boot_image_task.create_initrd()

        # put results into a tarball
        if not self.xz_options:
            self.xz_options = Defaults.get_xz_compression_options()
        bash_command = ['tar', '-C', self.target_dir, '-c', '--to-stdout'] + [
            self.kernel_filename,
            os.path.basename(self.boot_image_task.initrd_filename),
            os.path.basename(self.image),
            os.path.basename(self.checksum_name)
        ] + ['|', 'xz', '-f'] + self.xz_options + ['>', self.archive_name]
        Command.run(['bash', '-c', ' '.join(bash_command)])

        self.result.verify_image_size(
            self.runtime_config.get_max_size_constraint(), self.archive_name)
        # store results
        self.result.add(
            key='pxe_archive',
            filename=self.archive_name,
            use_for_bundle=True,
            compress=self.runtime_config.get_bundle_compression(default=False),
            shasum=True)

        # create image root metadata
        self.result.add(key='image_packages',
                        filename=self.system_setup.export_package_list(
                            self.target_dir),
                        use_for_bundle=True,
                        compress=False,
                        shasum=False)
        self.result.add(key='image_verified',
                        filename=self.system_setup.export_package_verification(
                            self.target_dir),
                        use_for_bundle=True,
                        compress=False,
                        shasum=False)
        return self.result
예제 #10
0
    def process(self):
        """
        Create result bundle from the image build results in the
        specified target directory. Each result image will contain
        the specified bundle identifier as part of its filename.
        Uncompressed image files will also become xz compressed
        and a sha sum will be created from every result image
        """
        self.manual = Help()
        if self._help():
            return

        # load serialized result object from target directory
        result_directory = os.path.abspath(self.command_args['--target-dir'])
        bundle_directory = os.path.abspath(self.command_args['--bundle-dir'])
        if result_directory == bundle_directory:
            raise KiwiBundleError(
                'Bundle directory must be different from target directory'
            )

        log.info(
            'Bundle build results from %s', result_directory
        )
        result = Result.load(
            result_directory + '/kiwi.result'
        )
        image_version = result.xml_state.get_image_version()
        ordered_results = OrderedDict(sorted(result.get_results().items()))

        # hard link bundle files, compress and build checksum
        if not os.path.exists(bundle_directory):
            Path.create(bundle_directory)
        for result_file in list(ordered_results.values()):
            if result_file.use_for_bundle:
                bundle_file_basename = os.path.basename(result_file.filename)
                # The bundle id is only taken into account for image results
                # which contains the image version in its nane
                bundle_file_basename = bundle_file_basename.replace(
                    image_version,
                    image_version + '-' + self.command_args['--id']
                )
                log.info('Creating %s', bundle_file_basename)
                bundle_file = ''.join(
                    [bundle_directory, '/', bundle_file_basename]
                )
                checksum_file = ''.join(
                    [bundle_directory, '/', bundle_file_basename, '.sha256']
                )
                Command.run(
                    [
                        'cp', result_file.filename, bundle_file
                    ]
                )
                if result_file.compress:
                    log.info('--> XZ compressing')
                    compress = Compress(bundle_file)
                    compress.xz(self.runtime_config.get_xz_options())
                    bundle_file = compress.compressed_filename
                    checksum_file = compress.compressed_filename + '.sha256'
                    if self.command_args['--zsync-source']:
                        zsyncmake = Path.which('zsyncmake', access_mode=os.X_OK)
                        if zsyncmake:
                            log.info('--> Creating zsync control file')
                            Command.run(
                                [
                                    zsyncmake, '-e',
                                    '-u', os.sep.join(
                                        [
                                            self.command_args['--zsync-source'],
                                            os.path.basename(bundle_file)
                                        ]
                                    ),
                                    '-o', bundle_file + '.zsync',
                                    bundle_file
                                ]
                            )
                        else:
                            log.warning(
                                '--> zsyncmake missing, zsync setup skipped'
                            )
                if result_file.shasum:
                    log.info('--> Creating SHA 256 sum')
                    checksum = Checksum(bundle_file)
                    with open(checksum_file, 'w') as shasum:
                        shasum.write(checksum.sha256())
예제 #11
0
class TestCompress(object):
    @patch('os.path.exists')
    def setup(self, mock_exists):
        mock_exists.return_value = True
        self.compress = Compress('some-file', True)

    @raises(KiwiFileNotFound)
    def test_source_file_not_found(self):
        Compress('some-file')

    @patch('kiwi.command.Command.run')
    def test_xz(self, mock_command):
        assert self.compress.xz() == 'some-file.xz'
        mock_command.assert_called_once_with(
            ['xz', '-f', '--threads=0', '--keep', 'some-file'])
        assert self.compress.compressed_filename == 'some-file.xz'

    @patch('kiwi.command.Command.run')
    def test_xz_with_custom_options(self, mock_command):
        assert self.compress.xz(options=['foo', 'bar']) == 'some-file.xz'
        mock_command.assert_called_once_with(
            ['xz', '-f', 'foo', 'bar', '--keep', 'some-file'])
        assert self.compress.compressed_filename == 'some-file.xz'

    @patch('kiwi.command.Command.run')
    def test_gzip(self, mock_command):
        assert self.compress.gzip() == 'some-file.gz'
        mock_command.assert_called_once_with(
            ['gzip', '-f', '-9', '--keep', 'some-file'])
        assert self.compress.compressed_filename == 'some-file.gz'

    @patch('kiwi.command.Command.run')
    @patch('kiwi.utils.compress.NamedTemporaryFile')
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress(self, mock_format, mock_temp, mock_command):
        mock_format.return_value = 'xz'
        self.compress.uncompress()
        mock_command.assert_called_once_with(['xz', '-d', 'some-file'])
        assert self.compress.uncompressed_filename == 'some-file'

    @patch('kiwi.command.Command.run')
    @patch('kiwi.utils.compress.NamedTemporaryFile')
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress_temporary(self, mock_format, mock_temp, mock_command):
        tempfile = mock.Mock()
        tempfile.name = 'tempfile'
        mock_temp.return_value = tempfile
        mock_format.return_value = 'xz'
        self.compress.uncompress(temporary=True)
        mock_command.assert_called_once_with(
            ['bash', '-c', 'xz -c -d some-file > tempfile'])
        assert self.compress.uncompressed_filename == 'tempfile'

    @raises(KiwiCompressionFormatUnknown)
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress_unknown_format(self, mock_format):
        mock_format.return_value = None
        self.compress.uncompress()

    @patch('kiwi.path.Path.which')
    def test_get_format(self, mock_which):
        mock_which.return_value = 'ziptool'
        xz = Compress('../data/xz_data.xz')
        assert xz.get_format() == 'xz'
        gzip = Compress('../data/gz_data.gz')
        assert gzip.get_format() == 'gzip'

    @patch('kiwi.logger.log.debug')
    @patch('kiwi.command.Command.run')
    def test_get_format_invalid_format(self, mock_run, mock_log):
        mock_run.side_effect = ValueError("nothing")
        invalid = Compress("../data/gz_data.gz")
        invalid.supported_zipper = ["mock_zip"]

        assert invalid.get_format() is None

        mock_run.assert_called_once_with(
            ['mock_zip', '-l', '../data/gz_data.gz'])
        mock_log.assert_called_once_with(
            'Error running "mock_zip -l ../data/gz_data.gz", got a'
            ' ValueError: nothing')
예제 #12
0
    def create(self):
        """
        Build a pxe image set consisting out of a boot image(initrd)
        plus its appropriate kernel files and the root filesystem
        image with a checksum. The result can be used within the kiwi
        PXE boot infrastructure

        Image types which triggers this builder are:

        * image="pxe"
        """
        log.info('Creating PXE root filesystem image')
        self.filesystem.create()
        os.rename(
            self.filesystem.filename, self.image_name
        )
        self.image = self.image_name
        if self.compressed:
            log.info('xz compressing root filesystem image')
            compress = Compress(self.image)
            compress.xz(self.xz_options)
            self.image = compress.compressed_filename

        log.info('Creating PXE root filesystem MD5 checksum')
        self.filesystem_checksum = ''.join([self.image, '.md5'])
        checksum = Checksum(self.image)
        checksum.md5(self.filesystem_checksum)

        # prepare boot(initrd) root system
        log.info('Creating PXE boot image')
        self.boot_image_task.prepare()

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

        # extract kernel from boot(initrd) root system
        kernel = Kernel(self.boot_image_task.boot_root_directory)
        kernel_data = kernel.get_kernel()
        if kernel_data:
            self.kernel_filename = ''.join(
                [
                    os.path.basename(self.image_name), '-',
                    kernel_data.version, '.kernel'
                ]
            )
            kernel.copy_kernel(
                self.target_dir, self.kernel_filename
            )
        else:
            raise KiwiPxeBootImageError(
                'No kernel in boot image tree %s found' %
                self.boot_image_task.boot_root_directory
            )

        # extract hypervisor from boot(initrd) root system
        if self.xen_server:
            kernel_data = kernel.get_xen_hypervisor()
            if kernel_data:
                self.hypervisor_filename = ''.join(
                    [os.path.basename(self.image_name), '-', kernel_data.name]
                )
                kernel.copy_xen_hypervisor(
                    self.target_dir, self.hypervisor_filename
                )
                self.result.add(
                    key='xen_hypervisor',
                    filename=self.target_dir + '/' + self.hypervisor_filename,
                    use_for_bundle=True,
                    compress=False,
                    shasum=True
                )
            else:
                raise KiwiPxeBootImageError(
                    'No hypervisor in boot image tree %s found' %
                    self.boot_image_task.boot_root_directory
                )

        # create initrd for pxe boot
        self.boot_image_task.create_initrd()

        # put results into a tarball
        Command.run(
            [
                'tar', '-C', self.target_dir, '-cJf', self.archive_name,
                self.kernel_filename,
                os.path.basename(self.boot_image_task.initrd_filename),
                os.path.basename(self.image),
                os.path.basename(self.filesystem_checksum)
            ]
        )

        # store results
        self.result.add(
            key='pxe_archive',
            filename=self.archive_name,
            use_for_bundle=True,
            compress=False,
            shasum=True
        )

        # create image root metadata
        self.result.add(
            key='image_packages',
            filename=self.system_setup.export_package_list(
                self.target_dir
            ),
            use_for_bundle=True,
            compress=False,
            shasum=False
        )
        self.result.add(
            key='image_verified',
            filename=self.system_setup.export_package_verification(
                self.target_dir
            ),
            use_for_bundle=True,
            compress=False,
            shasum=False
        )

        if self.pxedeploy:
            log.warning(
                'Creation of client config file from pxedeploy not implemented'
            )

        return self.result
예제 #13
0
class TestCompress(object):
    @patch('os.path.exists')
    def setup(self, mock_exists):
        mock_exists.return_value = True
        self.compress = Compress('some-file', True)

    @raises(KiwiFileNotFound)
    def test_source_file_not_found(self):
        Compress('some-file')

    @patch('kiwi.command.Command.run')
    def test_xz(self, mock_command):
        assert self.compress.xz() == 'some-file.xz'
        mock_command.assert_called_once_with(
            [
                'xz', '-f', '--threads=0', '--keep',
                'some-file'
            ]
        )
        assert self.compress.compressed_filename == 'some-file.xz'

    @patch('kiwi.command.Command.run')
    def test_xz_with_custom_options(self, mock_command):
        assert self.compress.xz(options=['foo', 'bar']) == 'some-file.xz'
        mock_command.assert_called_once_with(
            [
                'xz', '-f', 'foo', 'bar', '--keep',
                'some-file'
            ]
        )
        assert self.compress.compressed_filename == 'some-file.xz'

    @patch('kiwi.command.Command.run')
    def test_gzip(self, mock_command):
        assert self.compress.gzip() == 'some-file.gz'
        mock_command.assert_called_once_with(
            ['gzip', '-f', '-9', '--keep', 'some-file']
        )
        assert self.compress.compressed_filename == 'some-file.gz'

    @patch('kiwi.command.Command.run')
    @patch('kiwi.utils.compress.NamedTemporaryFile')
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress(self, mock_format, mock_temp, mock_command):
        mock_format.return_value = 'xz'
        self.compress.uncompress()
        mock_command.assert_called_once_with(
            ['xz', '-d', 'some-file']
        )
        assert self.compress.uncompressed_filename == 'some-file'

    @patch('kiwi.command.Command.run')
    @patch('kiwi.utils.compress.NamedTemporaryFile')
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress_temporary(self, mock_format, mock_temp, mock_command):
        tempfile = mock.Mock()
        tempfile.name = 'tempfile'
        mock_temp.return_value = tempfile
        mock_format.return_value = 'xz'
        self.compress.uncompress(temporary=True)
        mock_command.assert_called_once_with(
            ['bash', '-c', 'xz -c -d some-file > tempfile']
        )
        assert self.compress.uncompressed_filename == 'tempfile'

    @raises(KiwiCompressionFormatUnknown)
    @patch('kiwi.utils.compress.Compress.get_format')
    def test_uncompress_unknown_format(self, mock_format):
        mock_format.return_value = None
        self.compress.uncompress()

    @patch('kiwi.path.Path.which')
    def test_get_format(self, mock_which):
        mock_which.return_value = 'ziptool'
        xz = Compress('../data/xz_data.xz')
        assert xz.get_format() == 'xz'
        gzip = Compress('../data/gz_data.gz')
        assert gzip.get_format() == 'gzip'
예제 #14
0
    def process(self):
        """
        Create result bundle from the image build results in the
        specified target directory. Each result image will contain
        the specified bundle identifier as part of its filename.
        Uncompressed image files will also become xz compressed
        and a sha sum will be created from every result image
        """
        self.manual = Help()
        if self._help():
            return

        # load serialized result object from target directory
        result_directory = os.path.abspath(self.command_args['--target-dir'])
        bundle_directory = os.path.abspath(self.command_args['--bundle-dir'])
        if result_directory == bundle_directory:
            raise KiwiBundleError(
                'Bundle directory must be different from target directory')

        log.info('Bundle build results from %s', result_directory)
        result = Result.load(result_directory + '/kiwi.result')
        image_version = result.xml_state.get_image_version()
        image_name = result.xml_state.xml_data.get_name()
        ordered_results = OrderedDict(sorted(result.get_results().items()))

        # hard link bundle files, compress and build checksum
        if not os.path.exists(bundle_directory):
            Path.create(bundle_directory)
        for result_file in list(ordered_results.values()):
            if result_file.use_for_bundle:
                bundle_file_basename = os.path.basename(result_file.filename)
                # The bundle id is only taken into account for image results
                # which contains the image version appended in its file name
                part_name = list(bundle_file_basename.partition(image_name))
                bundle_file_basename = ''.join([
                    part_name[0], part_name[1], part_name[2].replace(
                        image_version,
                        image_version + '-' + self.command_args['--id'])
                ])
                log.info('Creating %s', bundle_file_basename)
                bundle_file = ''.join(
                    [bundle_directory, '/', bundle_file_basename])
                Command.run(['cp', result_file.filename, bundle_file])
                if result_file.compress:
                    log.info('--> XZ compressing')
                    compress = Compress(bundle_file)
                    compress.xz(self.runtime_config.get_xz_options())
                    bundle_file = compress.compressed_filename

                if self.command_args['--zsync-source'] and result_file.shasum:
                    # Files with a checksum are considered to be image files
                    # and are therefore eligible to be provided via the
                    # requested Partial/differential file download based on
                    # zsync
                    zsyncmake = Path.which('zsyncmake', access_mode=os.X_OK)
                    if zsyncmake:
                        log.info('--> Creating zsync control file')
                        Command.run([
                            zsyncmake, '-e', '-u',
                            os.sep.join([
                                self.command_args['--zsync-source'],
                                os.path.basename(bundle_file)
                            ]), '-o', bundle_file + '.zsync', bundle_file
                        ])
                    else:
                        log.warning(
                            '--> zsyncmake missing, zsync setup skipped')

                if result_file.shasum:
                    log.info('--> Creating SHA 256 sum')
                    checksum = Checksum(bundle_file)
                    with open(bundle_file + '.sha256', 'w') as shasum:
                        shasum.write('{0}  {1}'.format(
                            checksum.sha256(), os.path.basename(bundle_file)))
예제 #15
0
파일: pxe.py 프로젝트: Conan-Kudo/kiwi
    def create(self):
        """
        Build a pxe image set consisting out of a boot image(initrd)
        plus its appropriate kernel files and the root filesystem
        image with a checksum. The result can be used within the kiwi
        PXE boot infrastructure

        Image types which triggers this builder are:

        * image="pxe"

        :raises KiwiPxeBootImageError: if no kernel or hipervisor is found
            in boot image tree
        :return: result

        :rtype: instance of :class:`Result`
        """
        log.info('Creating PXE root filesystem image')
        self.filesystem.create()
        os.rename(
            self.filesystem.filename, self.image_name
        )
        self.image = self.image_name
        if self.compressed:
            log.info('xz compressing root filesystem image')
            compress = Compress(self.image)
            compress.xz(self.xz_options)
            self.image = compress.compressed_filename

        log.info('Creating PXE root filesystem MD5 checksum')
        self.filesystem_checksum = ''.join([self.image, '.md5'])
        checksum = Checksum(self.image)
        checksum.md5(self.filesystem_checksum)

        # prepare boot(initrd) root system
        log.info('Creating PXE boot image')
        self.boot_image_task.prepare()

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

        # extract kernel from boot(initrd) root system
        kernel = Kernel(self.boot_image_task.boot_root_directory)
        kernel_data = kernel.get_kernel()
        if kernel_data:
            self.kernel_filename = ''.join(
                [
                    os.path.basename(self.image_name), '-',
                    kernel_data.version, '.kernel'
                ]
            )
            kernel.copy_kernel(
                self.target_dir, self.kernel_filename
            )
        else:
            raise KiwiPxeBootImageError(
                'No kernel in boot image tree %s found' %
                self.boot_image_task.boot_root_directory
            )

        # extract hypervisor from boot(initrd) root system
        if self.xen_server:
            kernel_data = kernel.get_xen_hypervisor()
            if kernel_data:
                self.hypervisor_filename = ''.join(
                    [os.path.basename(self.image_name), '-', kernel_data.name]
                )
                kernel.copy_xen_hypervisor(
                    self.target_dir, self.hypervisor_filename
                )
                self.result.add(
                    key='xen_hypervisor',
                    filename=self.target_dir + '/' + self.hypervisor_filename,
                    use_for_bundle=True,
                    compress=False,
                    shasum=True
                )
            else:
                raise KiwiPxeBootImageError(
                    'No hypervisor in boot image tree %s found' %
                    self.boot_image_task.boot_root_directory
                )

        # create initrd for pxe boot
        self.boot_image_task.create_initrd()

        # put results into a tarball
        if not self.xz_options:
            self.xz_options = Defaults.get_xz_compression_options()
        bash_command = [
            'tar', '-C', self.target_dir, '-c', '--to-stdout'
        ] + [
            self.kernel_filename,
            os.path.basename(self.boot_image_task.initrd_filename),
            os.path.basename(self.image),
            os.path.basename(self.filesystem_checksum)
        ] + [
            '|', 'xz', '-f'
        ] + self.xz_options + [
            '>', self.archive_name
        ]
        Command.run(['bash', '-c', ' '.join(bash_command)])

        self.result.verify_image_size(
            self.runtime_config.get_max_size_constraint(),
            self.archive_name
        )
        # store results
        self.result.add(
            key='pxe_archive',
            filename=self.archive_name,
            use_for_bundle=True,
            compress=False,
            shasum=True
        )

        # create image root metadata
        self.result.add(
            key='image_packages',
            filename=self.system_setup.export_package_list(
                self.target_dir
            ),
            use_for_bundle=True,
            compress=False,
            shasum=False
        )
        self.result.add(
            key='image_verified',
            filename=self.system_setup.export_package_verification(
                self.target_dir
            ),
            use_for_bundle=True,
            compress=False,
            shasum=False
        )

        if self.pxedeploy:
            log.warning(
                'Creation of client config file from pxedeploy not implemented'
            )

        return self.result
예제 #16
0
    def create_install_pxe_archive(self):
        """
        Create an oem install tar archive suitable for installing a
        disk image via the network using the PXE boot protocol.
        The archive contains:

        * The raw system image xz compressed
        * The raw system image checksum metadata file
        * The append file template for the boot server
        * The system image initrd for kexec
        * The install initrd
        * The kernel

        Image types which triggers this builder are:

        * installpxe="true|false"
        """
        self.pxe_dir = mkdtemp(
            prefix='kiwi_pxe_install_media.', dir=self.target_dir
        )
        # the system image is transfered as xz compressed variant
        log.info('xz compressing disk image')
        pxe_image_filename = ''.join(
            [
                self.pxe_dir, '/',
                self.xml_state.xml_data.get_name(), '.xz'
            ]
        )
        compress = Compress(
            source_filename=self.diskname,
            keep_source_on_compress=True
        )
        compress.xz(self.xz_options)
        Command.run(
            ['mv', compress.compressed_filename, pxe_image_filename]
        )

        # the system image transfer is checked against a checksum
        log.info('Creating disk image checksum')
        pxe_md5_filename = ''.join(
            [
                self.pxe_dir, '/',
                self.xml_state.xml_data.get_name(), '.md5'
            ]
        )
        checksum = Checksum(self.diskname)
        checksum.md5(pxe_md5_filename)

        # the install image name is stored in a config file
        if self.initrd_system == 'kiwi':
            self._write_install_image_info_to_boot_image()

        # the kexec required system image initrd is stored for dracut kiwi-dump
        if self.initrd_system == 'dracut':
            boot_names = self.boot_image_task.get_boot_names()
            system_image_initrd = os.sep.join(
                [self.root_dir, 'boot', boot_names.initrd_name]
            )
            target_initrd_name = '{0}/{1}.initrd'.format(
                self.pxe_dir, self.xml_state.xml_data.get_name()
            )
            shutil.copy(
                system_image_initrd, target_initrd_name
            )
            os.chmod(target_initrd_name, 420)

        # create pxe config append information
        # this information helps to configure the boot server correctly
        append_filename = ''.join(
            [
                self.pxe_dir, '/',
                self.xml_state.xml_data.get_name(), '.append'
            ]
        )
        if self.initrd_system == 'kiwi':
            cmdline = 'pxe=1'
        else:
            cmdline = ' '.join(
                [
                    'rd.kiwi.install.pxe',
                    'rd.kiwi.install.image=http://example.com/image.xz'
                ]
            )
        custom_cmdline = self.xml_state.build_type.get_kernelcmdline()
        if custom_cmdline:
            cmdline += ' ' + custom_cmdline
        with open(append_filename, 'w') as append:
            append.write('%s\n' % cmdline)

        # create initrd for pxe install
        log.info('Creating pxe install boot image')
        self._create_pxe_install_kernel_and_initrd()

        # create pxe install tarball
        log.info('Creating pxe install archive')
        archive = ArchiveTar(
            self.pxename.replace('.xz', '')
        )
        archive.create_xz_compressed(
            self.pxe_dir, xz_options=self.xz_options
        )
예제 #17
0
    def process(self):
        """
        Create result bundle from the image build results in the
        specified target directory. Each result image will contain
        the specified bundle identifier as part of its filename.
        Uncompressed image files will also become xz compressed
        and a sha sum will be created from every result image
        """
        self.manual = Help()
        if self._help():
            return

        if self.command_args['--package-as-rpm']:
            Privileges.check_for_root_permissions()

        # load serialized result object from target directory
        result_directory = os.path.abspath(self.command_args['--target-dir'])
        bundle_directory = os.path.abspath(self.command_args['--bundle-dir'])
        if result_directory == bundle_directory:
            raise KiwiBundleError(
                'Bundle directory must be different from target directory')

        log.info('Bundle build results from %s', result_directory)
        result = Result.load(result_directory + '/kiwi.result')
        image_version = result.xml_state.get_image_version()
        image_name = result.xml_state.xml_data.get_name()
        image_description = result.xml_state.get_description_section()
        ordered_results = OrderedDict(sorted(result.get_results().items()))

        # hard link bundle files, compress and build checksum
        if self.command_args['--package-as-rpm']:
            Path.wipe(bundle_directory)
        if not os.path.exists(bundle_directory):
            Path.create(bundle_directory)

        bundle_file_format_name = ''
        if 'bundle_format' in ordered_results:
            bundle_format = ordered_results['bundle_format']
            tags = bundle_format['tags']
            bundle_file_format_name = bundle_format['pattern']
            # Insert image name
            bundle_file_format_name = bundle_file_format_name.replace(
                '%N', tags.N)
            # Insert Concatenated profile name (_)
            bundle_file_format_name = bundle_file_format_name.replace(
                '%P', tags.P)
            # Insert Architecture name
            bundle_file_format_name = bundle_file_format_name.replace(
                '%A', tags.A)
            # Insert Image build type name
            bundle_file_format_name = bundle_file_format_name.replace(
                '%T', tags.T)
            # Insert Image Major version number
            bundle_file_format_name = bundle_file_format_name.replace(
                '%M', format(tags.M))
            # Insert Image Minor version number
            bundle_file_format_name = bundle_file_format_name.replace(
                '%m', format(tags.m))
            # Insert Image Patch version number
            bundle_file_format_name = bundle_file_format_name.replace(
                '%p', format(tags.p))
            # Insert Bundle ID
            bundle_file_format_name = bundle_file_format_name.replace(
                '%I', self.command_args['--id'])
            del (ordered_results['bundle_format'])

        for result_file in list(ordered_results.values()):
            if result_file.use_for_bundle:
                extension = result_file.filename.split('.').pop()
                if bundle_file_format_name:
                    bundle_file_basename = '.'.join(
                        [bundle_file_format_name, extension])
                else:
                    bundle_file_basename = os.path.basename(
                        result_file.filename)
                    # The bundle id is only taken into account for image results
                    # which contains the image version appended in its file name
                    part_name = list(
                        bundle_file_basename.partition(image_name))
                    bundle_file_basename = ''.join([
                        part_name[0], part_name[1], part_name[2].replace(
                            image_version,
                            image_version + '-' + self.command_args['--id'])
                    ])
                log.info('Creating %s', bundle_file_basename)
                bundle_file = ''.join(
                    [bundle_directory, '/', bundle_file_basename])
                Command.run(['cp', result_file.filename, bundle_file])
                if result_file.compress:
                    log.info('--> XZ compressing')
                    compress = Compress(bundle_file)
                    compress.xz(self.runtime_config.get_xz_options())
                    bundle_file = compress.compressed_filename

                if self.command_args['--zsync-source'] and result_file.shasum:
                    # Files with a checksum are considered to be image files
                    # and are therefore eligible to be provided via the
                    # requested Partial/differential file download based on
                    # zsync
                    zsyncmake = Path.which('zsyncmake', access_mode=os.X_OK)
                    if zsyncmake:
                        log.info('--> Creating zsync control file')
                        Command.run([
                            zsyncmake, '-e', '-u',
                            os.sep.join([
                                self.command_args['--zsync-source'],
                                os.path.basename(bundle_file)
                            ]), '-o', bundle_file + '.zsync', bundle_file
                        ])
                    else:
                        log.warning(
                            '--> zsyncmake missing, zsync setup skipped')

                if result_file.shasum:
                    log.info('--> Creating SHA 256 sum')
                    checksum = Checksum(bundle_file)
                    with open(bundle_file + '.sha256', 'w') as shasum:
                        shasum.write('{0}  {1}{2}'.format(
                            checksum.sha256(), os.path.basename(bundle_file),
                            os.linesep))
        if self.command_args['--package-as-rpm']:
            ResultBundleTask._build_rpm_package(
                bundle_directory, bundle_file_format_name or image_name,
                image_version, image_description.specification,
                list(glob.iglob(f'{bundle_directory}/*')))
예제 #18
0
    def create_install_pxe_archive(self):
        """
        Create an oem install tar archive suitable for installing a
        disk image via the network using the PXE boot protocol.
        The archive contains:

        * The raw system image xz compressed
        * The raw system image checksum metadata file
        * The append file template for the boot server
        * The system image initrd for kexec
        * The install initrd
        * The kernel

        Image types which triggers this builder are:

        * installpxe="true|false"
        """
        self.pxe_dir = mkdtemp(prefix='kiwi_pxe_install_media.',
                               dir=self.target_dir)
        # the system image is transfered as xz compressed variant
        log.info('xz compressing disk image')
        pxe_image_filename = ''.join(
            [self.pxe_dir, '/',
             self.xml_state.xml_data.get_name(), '.xz'])
        compress = Compress(source_filename=self.diskname,
                            keep_source_on_compress=True)
        compress.xz(self.xz_options)
        Command.run(['mv', compress.compressed_filename, pxe_image_filename])

        # the system image transfer is checked against a checksum
        log.info('Creating disk image checksum')
        pxe_md5_filename = ''.join(
            [self.pxe_dir, '/',
             self.xml_state.xml_data.get_name(), '.md5'])
        checksum = Checksum(self.diskname)
        checksum.md5(pxe_md5_filename)

        # the install image name is stored in a config file
        if self.initrd_system == 'kiwi':
            self._write_install_image_info_to_boot_image()

        # the kexec required system image initrd is stored for dracut kiwi-dump
        if self.initrd_system == 'dracut':
            boot_names = self.boot_image_task.get_boot_names()
            system_image_initrd = os.sep.join(
                [self.root_dir, 'boot', boot_names.initrd_name])
            target_initrd_name = '{0}/{1}.initrd'.format(
                self.pxe_dir, self.xml_state.xml_data.get_name())
            shutil.copy(system_image_initrd, target_initrd_name)
            os.chmod(target_initrd_name, 420)

        # create pxe config append information
        # this information helps to configure the boot server correctly
        append_filename = ''.join(
            [self.pxe_dir, '/',
             self.xml_state.xml_data.get_name(), '.append'])
        if self.initrd_system == 'kiwi':
            cmdline = 'pxe=1'
        else:
            cmdline = ' '.join([
                'rd.kiwi.install.pxe',
                'rd.kiwi.install.image=http://example.com/image.xz'
            ])
        custom_cmdline = self.xml_state.build_type.get_kernelcmdline()
        if custom_cmdline:
            cmdline += ' ' + custom_cmdline
        with open(append_filename, 'w') as append:
            append.write('%s\n' % cmdline)

        # create initrd for pxe install
        log.info('Creating pxe install boot image')
        self._create_pxe_install_kernel_and_initrd()

        # create pxe install tarball
        log.info('Creating pxe install archive')
        archive = ArchiveTar(self.pxename.replace('.xz', ''))
        archive.create_xz_compressed(self.pxe_dir, xz_options=self.xz_options)
예제 #19
0
파일: kis.py 프로젝트: jfkw/kiwi
    def create(self) -> Result:
        """
        Build a component image consisting out of a boot image(initrd)
        plus its appropriate kernel files and the root filesystem
        image with a checksum.

        Image types which triggers this builder are:

        * image="kis"
        * image="pxe"

        :raises KiwiKisBootImageError: if no kernel or hipervisor is found
            in boot image tree
        :return: result

        :rtype: instance of :class:`Result`
        """
        if self.filesystem:
            log.info('Creating root filesystem image')
            self.filesystem.create()
            os.rename(
                self.filesystem.filename, self.image_name
            )
            self.image = self.image_name
            if self.compressed:
                log.info('xz compressing root filesystem image')
                compress = Compress(self.image)
                compress.xz(self.xz_options)
                self.image = compress.compressed_filename

            log.info('Creating root filesystem MD5 checksum')
            checksum = Checksum(self.image)
            checksum.md5(self.checksum_name)

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

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

        # extract kernel from boot(initrd) root system
        kernel = Kernel(self.boot_image_task.boot_root_directory)
        kernel_data = kernel.get_kernel()
        if kernel_data:
            self.kernel_filename = ''.join(
                [
                    os.path.basename(self.image_name), '-',
                    kernel_data.version, '.kernel'
                ]
            )
            kernel.copy_kernel(
                self.target_dir, self.kernel_filename
            )
        else:
            raise KiwiKisBootImageError(
                'No kernel in boot image tree %s found' %
                self.boot_image_task.boot_root_directory
            )

        # extract hypervisor from boot(initrd) root system
        if self.xen_server:
            hypervisor_data = kernel.get_xen_hypervisor()
            if hypervisor_data:
                self.hypervisor_filename = ''.join(
                    [
                        os.path.basename(self.image_name),
                        '-', hypervisor_data.name
                    ]
                )
                kernel.copy_xen_hypervisor(
                    self.target_dir, self.hypervisor_filename
                )
                self.result.add(
                    key='xen_hypervisor',
                    filename=self.target_dir + '/' + self.hypervisor_filename,
                    use_for_bundle=True,
                    compress=False,
                    shasum=True
                )
            else:
                raise KiwiKisBootImageError(
                    'No hypervisor in boot image tree %s found' %
                    self.boot_image_task.boot_root_directory
                )

        # create initrd
        self.boot_image_task.create_initrd()

        # create append information
        # this information helps to configure the deployment infrastructure
        if self.filesystem and self.filesystem.root_uuid \
           and self.initrd_system == 'dracut':
            cmdline = 'root=UUID={}'.format(self.filesystem.root_uuid)
            if self.custom_cmdline:
                cmdline += ' {}'.format(self.custom_cmdline)
            with open(self.append_file, 'w') as append:
                append.write(cmdline)

        # put results into a tarball
        if not self.xz_options:
            self.xz_options = Defaults.get_xz_compression_options()

        kis_tarball_files = [
            self.kernel_filename,
            os.path.basename(self.boot_image_task.initrd_filename),
            os.path.basename(self.checksum_name),
        ]

        if self.image:
            kis_tarball_files.append(os.path.basename(self.image))

        if self.filesystem and self.filesystem.root_uuid \
           and self.initrd_system == 'dracut':
            kis_tarball_files.append(os.path.basename(self.append_file))

        kis_tarball = ArchiveTar(
            self.archive_name,
            create_from_file_list=True,
            file_list=kis_tarball_files
        )

        if self.compressed:
            self.archive_name = kis_tarball.create(self.target_dir)
        else:
            self.archive_name = kis_tarball.create_xz_compressed(
                self.target_dir, xz_options=self.xz_options
            )

        Result.verify_image_size(
            self.runtime_config.get_max_size_constraint(),
            self.archive_name
        )
        # store results
        self.result.add(
            key='kis_archive',
            filename=self.archive_name,
            use_for_bundle=True,
            compress=self.runtime_config.get_bundle_compression(
                default=False
            ),
            shasum=True
        )

        # create image root metadata
        self.result.add(
            key='image_packages',
            filename=self.system_setup.export_package_list(
                self.target_dir
            ),
            use_for_bundle=True,
            compress=False,
            shasum=False
        )
        self.result.add(
            key='image_changes',
            filename=self.system_setup.export_package_changes(
                self.target_dir
            ),
            use_for_bundle=True,
            compress=True,
            shasum=False
        )
        self.result.add(
            key='image_verified',
            filename=self.system_setup.export_package_verification(
                self.target_dir
            ),
            use_for_bundle=True,
            compress=False,
            shasum=False
        )
        return self.result