Beispiel #1
0
    def test_fix_boot_catalog(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            'CD001' + '_' * (0x08c - 0x5) + '0x1d5f23a'
        eltorito_descriptor = \
            'EL TORITO SPECIFICATION' + '_' * (0x47 - 0x17) + '0x1d5f23a'
        boot_catalog = '_' * 64 + struct.pack('B', 0x88) + '_' * 32
        read_results = [boot_catalog, eltorito_descriptor, volume_descriptor]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect

        Iso.fix_boot_catalog('isofile')

        if sys.byteorder == 'big':
            assert self.file_mock.write.call_args_list == [
                call('_' * 44 +
                     '\x01Legacy (isolinux)\x00\x00\x91\xef\x00\x01' +
                     '\x00' * 28 + '\x88___________\x01UEFI (grub)' +
                     '\x00' * 8)
            ]
        else:
            assert self.file_mock.write.call_args_list == [
                call('_' * 44 + '\x01Legacy (isolinux)\x00\x00\x91\xef\x01' +
                     '\x00' * 29 + '\x88___________\x01UEFI (grub)' +
                     '\x00' * 8)
            ]
Beispiel #2
0
 def test_create_hybrid_with_error(self, mock_command):
     mbrid = mock.Mock()
     mbrid.get_id = mock.Mock(return_value='0x0815')
     command = mock.Mock()
     command.error = 'some error message'
     mock_command.return_value = command
     Iso.create_hybrid(42, mbrid, 'some-iso', 'efi')
Beispiel #3
0
    def test_relocate_boot_catalog(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
        eltorito_descriptor = \
            bytes(b'EL TORITO SPECIFICATION') + bytes(b'_') * (0x47 - 0x17) + bytes(b'0x1d5f23a')
        new_volume_descriptor = \
            bytes(b'bogus')
        next_new_volume_descriptor = \
            bytes(b'TEA01')
        new_boot_catalog = bytes(b'\x00') * 0x800
        read_results = [
            new_boot_catalog,
            next_new_volume_descriptor,
            new_volume_descriptor,
            bytes(b'catalog'),
            eltorito_descriptor,
            volume_descriptor
        ]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect

        Iso.relocate_boot_catalog('isofile')
        assert self.file_mock.write.call_args_list == [
            call(bytes(b'catalog')),
            call(
                bytes(b'EL TORITO SPECIFICATION') +
                bytes(b'_') * (0x47 - 0x17) + bytes(b'\x13\x00\x00\x005f23a')
            )
        ]
Beispiel #4
0
    def test_relocate_boot_catalog(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            'CD001' + '_' * (0x08c - 0x5) + '0x1d5f23a'
        eltorito_descriptor = \
            'EL TORITO SPECIFICATION' + '_' * (0x47 - 0x17) + '0x1d5f23a'
        new_volume_descriptor = \
            'bogus'
        next_new_volume_descriptor = \
            'TEA01'
        new_boot_catalog = format('\x00' * 0x800)
        read_results = [
            new_boot_catalog, next_new_volume_descriptor,
            new_volume_descriptor, 'catalog', eltorito_descriptor,
            volume_descriptor
        ]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect

        Iso.relocate_boot_catalog('isofile')
        assert self.file_mock.write.call_args_list == [
            call('catalog'),
            call('EL TORITO SPECIFICATION' + '_' * (0x47 - 0x17) +
                 '\x13\x00\x00\x005f23a')
        ]
Beispiel #5
0
    def test_relocate_boot_catalog(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            'CD001' + '_' * (0x08c - 0x5) + '0x1d5f23a'
        eltorito_descriptor = \
            'EL TORITO SPECIFICATION' + '_' * (0x47 - 0x17) + '0x1d5f23a'
        new_volume_descriptor = \
            'bogus'
        next_new_volume_descriptor = \
            'TEA01'
        new_boot_catalog = format('\x00' * 0x800)
        read_results = [
            new_boot_catalog,
            next_new_volume_descriptor,
            new_volume_descriptor,
            'catalog',
            eltorito_descriptor,
            volume_descriptor
        ]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect

        Iso.relocate_boot_catalog('isofile')
        assert self.file_mock.write.call_args_list == [
            call('catalog'),
            call(
                'EL TORITO SPECIFICATION' +
                '_' * (0x47 - 0x17) + '\x13\x00\x00\x005f23a'
            )
        ]
Beispiel #6
0
 def test_create_hybrid(self, mock_command):
     mbrid = mock.Mock()
     mbrid.get_id = mock.Mock(return_value='0x0815')
     Iso.create_hybrid(42, mbrid, 'some-iso')
     mock_command.assert_called_once_with([
         'isohybrid', '--offset', '42', '--id', '0x0815', '--type', '0x83',
         '--uefi', 'some-iso'
     ])
Beispiel #7
0
    def test_iso_metadata_path_table_sector_invalid(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        read_results = [bytes(b'EL TORITO SPECIFICATION'), bytes(b'CD001')]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect
        Iso.fix_boot_catalog('isofile')
Beispiel #8
0
 def test_create_hybrid_with_error(self, mock_command):
     mbrid = mock.Mock()
     mbrid.get_id = mock.Mock(
         return_value='0x0815'
     )
     command = mock.Mock()
     command.error = 'some error message'
     mock_command.return_value = command
     Iso.create_hybrid(42, mbrid, 'some-iso', 'efi')
Beispiel #9
0
 def test_create_hybrid_with_multiple_errors(self, mock_command):
     mbrid = mock.Mock()
     mbrid.get_id = mock.Mock(return_value='0x0815')
     command = mock.Mock()
     command.error = \
         'isohybrid: Warning: more than 1024 cylinders: 1817\n' + \
         'isohybrid: Not all BIOSes will be able to boot this device\n' + \
         'isohybrid: some other error we do not ignore'
     mock_command.return_value = command
     Iso.create_hybrid(42, mbrid, 'some-iso', 'efi')
Beispiel #10
0
    def test_iso_metadata_catalog_sector_invalid(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
        read_results = [bytes(b'EL TORITO SPECIFICATION'), volume_descriptor]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect
        Iso.fix_boot_catalog('isofile')
Beispiel #11
0
 def test_create_hybrid_with_multiple_errors(self, mock_command):
     mbrid = mock.Mock()
     mbrid.get_id = mock.Mock(
         return_value='0x0815'
     )
     command = mock.Mock()
     command.error = \
         'isohybrid: Warning: more than 1024 cylinders: 1817\n' + \
         'isohybrid: Not all BIOSes will be able to boot this device\n' + \
         'isohybrid: some other error we do not ignore'
     mock_command.return_value = command
     Iso.create_hybrid(42, mbrid, 'some-iso', 'efi')
Beispiel #12
0
 def test_create_hybrid_with_cylinders_warning(self, mock_command):
     mbrid = mock.Mock()
     mbrid.get_id = mock.Mock(return_value='0x0815')
     command = mock.Mock()
     command.error = \
         'isohybrid: Warning: more than 1024 cylinders: 1817\n' + \
         'isohybrid: Not all BIOSes will be able to boot this device\n'
     mock_command.return_value = command
     Iso.create_hybrid(42, mbrid, 'some-iso', 'efi')
     mock_command.assert_called_once_with([
         'isohybrid', '--offset', '42', '--id', '0x0815', '--type', '0x83',
         '--uefi', 'some-iso'
     ])
Beispiel #13
0
    def setup(self, mock_machine, mock_tempfile):
        temp_type = namedtuple('temp_type', ['name'])
        mock_machine.return_value = 'x86_64'
        mock_tempfile.return_value = temp_type(name='sortfile')
        self.context_manager_mock = mock.Mock()
        self.file_mock = mock.Mock()
        self.enter_mock = mock.Mock()
        self.exit_mock = mock.Mock()
        self.enter_mock.return_value = self.file_mock
        setattr(self.context_manager_mock, '__enter__', self.enter_mock)
        setattr(self.context_manager_mock, '__exit__', self.exit_mock)

        self.iso = Iso('source-dir')
Beispiel #14
0
    def test_iso_metadata_catalog_invalid(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            'CD001' + '_' * (0x08c - 0x5) + '0x1d5f23a'
        eltorito_descriptor = \
            'EL TORITO SPECIFICATION' + '_' * (0x47 - 0x17) + '0x1d5f23a'
        read_results = [eltorito_descriptor, volume_descriptor]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect
        Iso.fix_boot_catalog('isofile')
Beispiel #15
0
    def test_iso_metadata_catalog_invalid(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            'CD001' + '_' * (0x08c - 0x5) + '0x1d5f23a'
        eltorito_descriptor = \
            'EL TORITO SPECIFICATION' + '_' * (0x47 - 0x17) + '0x1d5f23a'
        read_results = [eltorito_descriptor, volume_descriptor]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect
        Iso.fix_boot_catalog('isofile')
Beispiel #16
0
 def test_create_hybrid(self, mock_command):
     mbrid = mock.Mock()
     mbrid.get_id = mock.Mock(
         return_value='0x0815'
     )
     Iso.create_hybrid(42, mbrid, 'some-iso')
     mock_command.assert_called_once_with(
         [
             'isohybrid', '--offset', '42',
             '--id', '0x0815', '--type', '0x83',
             '--uefi', 'some-iso'
         ]
     )
Beispiel #17
0
 def test_create_hybrid_with_cylinders_warning(self, mock_command):
     mbrid = mock.Mock()
     mbrid.get_id = mock.Mock(
         return_value='0x0815'
     )
     command = mock.Mock()
     command.error = \
         'isohybrid: Warning: more than 1024 cylinders: 1817\n' + \
         'isohybrid: Not all BIOSes will be able to boot this device\n'
     mock_command.return_value = command
     Iso.create_hybrid(42, mbrid, 'some-iso', 'efi')
     mock_command.assert_called_once_with(
         [
             'isohybrid', '--offset', '42',
             '--id', '0x0815', '--type', '0x83',
             '--uefi', 'some-iso'
         ]
     )
Beispiel #18
0
    def test_fix_boot_catalog(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
        eltorito_descriptor = \
            bytes(b'EL TORITO SPECIFICATION') + \
            bytes(b'_') * (0x47 - 0x17) + bytes(b'0x1d5f23a')
        boot_catalog = bytes(b'_') * 64 + struct.pack('B', 0x88) + \
            bytes(b'_') * 32
        read_results = [
            boot_catalog,
            eltorito_descriptor,
            volume_descriptor
        ]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect

        Iso.fix_boot_catalog('isofile')

        if sys.byteorder == 'big':
            assert self.file_mock.write.call_args_list == [
                call(
                    bytes(b'_') * 44 +
                    bytes(b'\x01Legacy (isolinux)\x00\x00\x91\xef\x00\x01') +
                    bytes(b'\x00') * 28 +
                    bytes(b'\x88___________\x01UEFI (grub)') +
                    bytes(b'\x00') * 8
                )
            ]
        else:
            assert self.file_mock.write.call_args_list == [
                call(
                    bytes(b'_') * 44 +
                    bytes(b'\x01Legacy (isolinux)\x00\x00\x91\xef\x01') +
                    bytes(b'\x00') * 29 +
                    bytes(b'\x88___________\x01UEFI (grub)') +
                    bytes(b'\x00') * 8
                )
            ]
Beispiel #19
0
    def setup(self, mock_machine, mock_tempfile):
        temp_type = namedtuple(
            'temp_type', ['name']
        )
        mock_machine.return_value = 'x86_64'
        mock_tempfile.return_value = temp_type(
            name='sortfile'
        )
        self.context_manager_mock = mock.Mock()
        self.file_mock = mock.Mock()
        self.enter_mock = mock.Mock()
        self.exit_mock = mock.Mock()
        self.enter_mock.return_value = self.file_mock
        setattr(self.context_manager_mock, '__enter__', self.enter_mock)
        setattr(self.context_manager_mock, '__exit__', self.exit_mock)

        self.iso = Iso('source-dir')
Beispiel #20
0
    def create(self):
        """
        Build a bootable hybrid live ISO image

        Image types which triggers this builder are:

        * image="iso"
        """
        # 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: {0}'.format(self.mbrid.get_id()))
        log.info('--> Publisher: {0}'.format(Defaults.get_publisher()))
        log.info('--> Volume id: {0}'.format(self.volume_id))
        custom_iso_args = {
            'create_options': [
                '-A', self.mbrid.get_id(),
                '-p', Defaults.get_preparer(),
                '-publisher', Defaults.get_publisher(),
                '-V', self.volume_id
            ]
        }

        # pack system into live boot structure as expected by dracut
        log.info(
            'Packing system into dracut live ISO type: {0}'.format(
                self.live_type
            )
        )
        root_filesystem = Defaults.get_default_live_iso_root_filesystem()
        filesystem_custom_parameters = {
            'mount_options': self.xml_state.get_fs_mount_option_list()
        }
        filesystem_setup = FileSystemSetup(
            self.xml_state, self.root_dir
        )
        root_image = NamedTemporaryFile()
        loop_provider = LoopDevice(
            root_image.name,
            filesystem_setup.get_size_mbytes(root_filesystem),
            self.xml_state.build_type.get_target_blocksize()
        )
        loop_provider.create()
        live_filesystem = FileSystem(
            name=root_filesystem,
            device_provider=loop_provider,
            root_dir=self.root_dir + os.sep,
            custom_args=filesystem_custom_parameters
        )
        live_filesystem.create_on_device()
        log.info(
            '--> Syncing data to {0} root image'.format(root_filesystem)
        )
        live_filesystem.sync_data(
            Defaults.get_exclude_list_for_root_data_sync()
        )
        log.info('--> Creating squashfs container for root image')
        self.live_container_dir = mkdtemp(
            prefix='live-container.', dir=self.target_dir
        )
        Path.create(self.live_container_dir + '/LiveOS')
        shutil.copy(
            root_image.name, self.live_container_dir + '/LiveOS/rootfs.img'
        )
        live_container_image = FileSystem(
            name='squashfs',
            device_provider=None,
            root_dir=self.live_container_dir
        )
        container_image = NamedTemporaryFile()
        live_container_image.create_on_file(
            container_image.name
        )
        Path.create(self.media_dir + '/LiveOS')
        shutil.copy(
            container_image.name, self.media_dir + '/LiveOS/squashfs.img'
        )

        # 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.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, {
                    'grub_directory_name':
                        Defaults.get_grub_boot_directory_name(self.root_dir)
                }
            )
            bootloader_config_grub.setup_live_boot_images(
                mbrid=self.mbrid, lookup_path=self.root_dir
            )
            bootloader_config_grub.setup_live_image_config(
                mbrid=self.mbrid
            )
            bootloader_config_grub.write()

        # call custom editbootconfig script if present
        self.system_setup.call_edit_boot_config_script(
            filesystem='iso:{0}'.format(self.media_dir), boot_part_id=1,
            working_directory=self.root_dir
        )

        # create dracut initrd for live image
        log.info('Creating live ISO boot image')
        self._create_dracut_live_iso_config()
        self.boot_image.create_initrd(self.mbrid)

        # setup kernel file(s) and initrd in ISO boot layout
        log.info('Setting up kernel file(s) and boot image in ISO boot layout')
        self._setup_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['create_options'].append('-iso-level')
            custom_iso_args['create_options'].append('3')
            custom_iso_args['create_options'].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.firmware.efi_mode()
            )

        # include metadata for checkmedia tool
        if self.xml_state.build_type.get_mediacheck() is True:
            Iso.set_media_tag(self.isoname)

        self.result.verify_image_size(
            self.runtime_config.get_max_size_constraint(),
            self.isoname
        )
        self.result.add(
            key='live_image',
            filename=self.isoname,
            use_for_bundle=True,
            compress=False,
            shasum=True
        )
        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
Beispiel #21
0
 def test_init_for_ix86_platform(self, mock_machine, mock_tempfile):
     mock_machine.return_value = 'i686'
     iso = Iso('source-dir')
     assert iso.arch == 'ix86'
Beispiel #22
0
 def test_set_media_tag(self, mock_command):
     Iso.set_media_tag('foo')
     mock_command.assert_called_once_with(
         ['tagmedia', '--md5', '--check', '--pad', '150', 'foo']
     )
Beispiel #23
0
 def test_iso_metadata_not_bootable(self, mock_open):
     mock_open.return_value = self.context_manager_mock
     self.file_mock.read.return_value = bytes(b'CD001')
     Iso.fix_boot_catalog('isofile')
Beispiel #24
0
 def test_iso_metadata_iso9660_invalid(self, mock_open):
     mock_open.return_value = self.context_manager_mock
     self.file_mock.read.return_value = bytes(b'bogus')
     Iso.fix_boot_catalog('isofile')
Beispiel #25
0
class TestIso(object):
    @patch('kiwi.iso.NamedTemporaryFile')
    @patch('platform.machine')
    def setup(self, mock_machine, mock_tempfile):
        temp_type = namedtuple(
            'temp_type', ['name']
        )
        mock_machine.return_value = 'x86_64'
        mock_tempfile.return_value = temp_type(
            name='sortfile'
        )
        self.context_manager_mock = mock.Mock()
        self.file_mock = mock.Mock()
        self.enter_mock = mock.Mock()
        self.exit_mock = mock.Mock()
        self.enter_mock.return_value = self.file_mock
        setattr(self.context_manager_mock, '__enter__', self.enter_mock)
        setattr(self.context_manager_mock, '__exit__', self.exit_mock)

        self.iso = Iso('source-dir')

    @patch_open
    @patch('os.path.exists')
    @raises(KiwiIsoLoaderError)
    def test_init_iso_creation_parameters_no_loader(
        self, mock_exists, mock_open
    ):
        mock_exists.return_value = False
        self.iso.init_iso_creation_parameters()

    @patch('kiwi.iso.NamedTemporaryFile')
    @patch('platform.machine')
    def test_init_for_ix86_platform(self, mock_machine, mock_tempfile):
        mock_machine.return_value = 'i686'
        iso = Iso('source-dir')
        assert iso.arch == 'ix86'

    @patch_open
    @patch('kiwi.iso.Command.run')
    @patch('os.path.exists')
    @patch('os.walk')
    def test_init_iso_creation_parameters(
        self, mock_walk, mock_exists, mock_command, mock_open
    ):
        mock_walk.return_value = [
            ('source-dir', ('bar', 'baz'), ('efi', 'eggs', 'header_end'))
        ]
        mock_exists.return_value = True
        mock_open.return_value = self.context_manager_mock

        self.iso.init_iso_creation_parameters(['custom_arg'])

        assert self.file_mock.write.call_args_list == [
            call('7984fc91-a43f-4e45-bf27-6d3aa08b24cf\n'),
            call('source-dir/boot/x86_64/boot.catalog 3\n'),
            call('source-dir/boot/x86_64/loader/isolinux.bin 2\n'),
            call('source-dir/efi 1000001\n'),
            call('source-dir/eggs 1\n'),
            call('source-dir/header_end 1000000\n'),
            call('source-dir/bar 1\n'),
            call('source-dir/baz 1\n')
        ]
        assert self.iso.iso_parameters == [
            'custom_arg', '-R', '-J', '-f', '-pad', '-joliet-long',
            '-sort', 'sortfile', '-no-emul-boot', '-boot-load-size', '4',
            '-boot-info-table',
            '-hide', 'boot/x86_64/boot.catalog',
            '-hide-joliet', 'boot/x86_64/boot.catalog',
        ]
        assert self.iso.iso_loaders == [
            '-b', 'boot/x86_64/loader/isolinux.bin',
            '-c', 'boot/x86_64/boot.catalog'
        ]
        mock_command.assert_called_once_with(
            [
                'isolinux-config', '--base', 'boot/x86_64/loader',
                'source-dir/boot/x86_64/loader/isolinux.bin'
            ]
        )

    @patch_open
    @patch('kiwi.iso.Command.run')
    @patch('kiwi.iso.Path.create')
    @patch('os.path.exists')
    @patch('os.walk')
    def test_init_iso_creation_parameters_failed_isolinux_config(
        self, mock_walk, mock_exists, mock_path, mock_command, mock_open
    ):
        mock_exists.return_value = True
        mock_open.return_value = self.context_manager_mock
        command_raises = [False, True]

        def side_effect(arg):
            if command_raises.pop():
                raise Exception

        mock_command.side_effect = side_effect

        self.iso.init_iso_creation_parameters(['custom_arg'])

        mock_path.assert_called_once_with('source-dir/isolinux')
        assert mock_command.call_args_list[1] == call(
            [
                'bash', '-c',
                'ln source-dir/boot/x86_64/loader/* source-dir/isolinux'
            ]
        )

    @patch('os.path.exists')
    def test_add_efi_loader_parameters(self, mock_exists):
        mock_exists.return_value = True
        self.iso.add_efi_loader_parameters()
        assert self.iso.iso_loaders == [
            '-eltorito-alt-boot', '-b', 'boot/x86_64/efi',
            '-no-emul-boot', '-joliet-long'
        ]

    def test_get_iso_creation_parameters(self):
        self.iso.iso_parameters = ['a']
        self.iso.iso_loaders = ['b']
        assert self.iso.get_iso_creation_parameters() == ['a', 'b']

    @raises(KiwiIsoToolError)
    @patch('os.path.exists')
    def test_isols_no_tool_found(self, mock_exists):
        mock_exists.return_value = False
        self.iso.isols('some-iso')

    @patch('os.path.exists')
    @patch('kiwi.iso.Command.run')
    @patch_open
    def test_isols_usr_bin_isoinfo_used(
        self, mock_open, mock_command, mock_exists
    ):
        exists_results = [False, True]

        def side_effect(self):
            return exists_results.pop()

        mock_exists.side_effect = side_effect
        self.iso.isols('some-iso')
        mock_command.assert_called_once_with(
            ['/usr/bin/isoinfo', '-R', '-l', '-i', 'some-iso']
        )

    @patch('os.path.exists')
    @patch('kiwi.iso.Command.run')
    @patch_open
    def test_isols_usr_lib_genisoimage_isoinfo_used(
        self, mock_open, mock_command, mock_exists
    ):
        exists_results = [True, False]

        def side_effect(self):
            return exists_results.pop()

        mock_exists.side_effect = side_effect
        self.iso.isols('some-iso')
        mock_command.assert_called_once_with(
            ['/usr/lib/genisoimage/isoinfo', '-R', '-l', '-i', 'some-iso']
        )

    @patch('kiwi.iso.Command.run')
    @patch('os.path.exists')
    def test_isols(self, mock_exists, mock_command):
        mock_exists.return_value = True
        output_type = namedtuple('output_type', ['output'])
        output_data = ''
        with open('../data/iso_listing.txt') as iso:
            output_data = iso.read()
        mock_command.return_value = output_type(output=output_data)
        result = self.iso.isols('some-iso')
        assert result[2158].name == 'header_end'

    def test_create_header_end_block(self):
        temp_file = NamedTemporaryFile()
        self.iso.header_end_file = temp_file.name
        assert self.iso.create_header_end_block(
            '../data/iso_with_marker.iso'
        ) == 96

    @raises(KiwiIsoLoaderError)
    def test_create_header_end_block_raises(self):
        temp_file = NamedTemporaryFile()
        self.iso.header_end_file = temp_file.name
        self.iso.create_header_end_block(
            '../data/iso_no_marker.iso'
        )

    @patch('kiwi.iso.Command.run')
    def test_create_hybrid(self, mock_command):
        mbrid = mock.Mock()
        mbrid.get_id = mock.Mock(
            return_value='0x0815'
        )
        Iso.create_hybrid(42, mbrid, 'some-iso')
        mock_command.assert_called_once_with(
            [
                'isohybrid', '--offset', '42',
                '--id', '0x0815', '--type', '0x83',
                '--uefi', 'some-iso'
            ]
        )

    @patch_open
    @raises(KiwiIsoMetaDataError)
    def test_iso_metadata_iso9660_invalid(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        self.file_mock.read.return_value = bytes(b'bogus')
        Iso.fix_boot_catalog('isofile')

    @patch_open
    @raises(KiwiIsoMetaDataError)
    def test_iso_metadata_not_bootable(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        self.file_mock.read.return_value = bytes(b'CD001')
        Iso.fix_boot_catalog('isofile')

    @patch_open
    @raises(KiwiIsoMetaDataError)
    def test_iso_metadata_path_table_sector_invalid(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        read_results = [bytes(b'EL TORITO SPECIFICATION'), bytes(b'CD001')]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect
        Iso.fix_boot_catalog('isofile')

    @patch_open
    @raises(KiwiIsoMetaDataError)
    def test_iso_metadata_catalog_sector_invalid(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
        read_results = [bytes(b'EL TORITO SPECIFICATION'), volume_descriptor]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect
        Iso.fix_boot_catalog('isofile')

    @patch_open
    @raises(KiwiIsoMetaDataError)
    def test_iso_metadata_catalog_invalid(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
        eltorito_descriptor = \
            bytes(b'EL TORITO SPECIFICATION') + bytes(b'_') * (0x47 - 0x17) + bytes(b'0x1d5f23a')
        read_results = [eltorito_descriptor, volume_descriptor]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect
        Iso.fix_boot_catalog('isofile')

    @patch_open
    def test_relocate_boot_catalog(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
        eltorito_descriptor = \
            bytes(b'EL TORITO SPECIFICATION') + bytes(b'_') * (0x47 - 0x17) + bytes(b'0x1d5f23a')
        new_volume_descriptor = \
            bytes(b'bogus')
        next_new_volume_descriptor = \
            bytes(b'TEA01')
        new_boot_catalog = bytes(b'\x00') * 0x800
        read_results = [
            new_boot_catalog,
            next_new_volume_descriptor,
            new_volume_descriptor,
            bytes(b'catalog'),
            eltorito_descriptor,
            volume_descriptor
        ]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect

        Iso.relocate_boot_catalog('isofile')
        assert self.file_mock.write.call_args_list == [
            call(bytes(b'catalog')),
            call(
                bytes(b'EL TORITO SPECIFICATION') +
                bytes(b'_') * (0x47 - 0x17) + bytes(b'\x13\x00\x00\x005f23a')
            )
        ]

    @patch_open
    def test_fix_boot_catalog(self, mock_open):
        mock_open.return_value = self.context_manager_mock
        volume_descriptor = \
            bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
        eltorito_descriptor = \
            bytes(b'EL TORITO SPECIFICATION') + bytes(b'_') * (0x47 - 0x17) + bytes(b'0x1d5f23a')
        boot_catalog = bytes(b'_') * 64 + struct.pack('B', 0x88) + bytes(b'_') * 32
        read_results = [
            boot_catalog,
            eltorito_descriptor,
            volume_descriptor
        ]

        def side_effect(arg):
            return read_results.pop()

        self.file_mock.read.side_effect = side_effect

        Iso.fix_boot_catalog('isofile')

        if sys.byteorder == 'big':
            assert self.file_mock.write.call_args_list == [
                call(
                    bytes(b'_') * 44 +
                    bytes(b'\x01Legacy (isolinux)\x00\x00\x91\xef\x00\x01') +
                    bytes(b'\x00') * 28 +
                    bytes(b'\x88___________\x01UEFI (grub)') +
                    bytes(b'\x00') * 8
                )
            ]
        else:
            assert self.file_mock.write.call_args_list == [
                call(
                    bytes(b'_') * 44 +
                    bytes(b'\x01Legacy (isolinux)\x00\x00\x91\xef\x01') +
                    bytes(b'\x00') * 29 +
                    bytes(b'\x88___________\x01UEFI (grub)') +
                    bytes(b'\x00') * 8
                )
            ]
Beispiel #26
0
    def create(self):
        """
        Build a bootable hybrid live ISO image

        Image types which triggers this builder are:

        * image="iso"
        """
        # 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 = {
            'create_options': [
                '-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['create_options'].append('-V')
            custom_iso_args['create_options'].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,
                custom_args=self.filesystem_custom_parameters)
            live_type_image.create_on_file(
                self.live_image_file,
                exclude=Defaults.get_exclude_list_for_root_data_sync())
            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()
        self.system_setup.call_edit_boot_config_script(
            filesystem=self.types[self.live_type],
            boot_part_id=1,
            working_directory=self.media_dir)

        # 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, {
                    'grub_directory_name':
                    Defaults.get_grub_boot_directory_name(self.root_dir)
                })
            bootloader_config_grub.setup_live_boot_images(
                mbrid=self.mbrid, lookup_path=self.root_dir)
            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['create_options'].append('-iso-level')
            custom_iso_args['create_options'].append('3')
            custom_iso_args['create_options'].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)

        # include metadata for checkmedia tool
        if self.xml_state.build_type.get_mediacheck() is True:
            Iso.set_media_tag(self.isoname)

        self.result.add(key='live_image',
                        filename=self.isoname,
                        use_for_bundle=True,
                        compress=False,
                        shasum=True)
        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
Beispiel #27
0
    def create_install_iso(self):
        """
        Create an install ISO from the disk_image as hybrid ISO
        bootable via legacy BIOS, EFI and as disk from Stick

        Image types which triggers this builder are:

        * installiso="true|false"
        * installstick="true|false"
        """
        self.media_dir = mkdtemp(
            prefix='kiwi_install_media.', dir=self.target_dir
        )
        # custom iso metadata
        self.custom_iso_args = {
            'create_options': [
                '-V', '"KIWI Installation System"',
                '-A', self.mbrid.get_id()
            ]
        }

        # the system image transfer is checked against a checksum
        log.info('Creating disk image checksum')
        self.squashed_contents = mkdtemp(
            prefix='kiwi_install_squashfs.', dir=self.target_dir
        )
        checksum = Checksum(self.diskname)
        checksum.md5(self.squashed_contents + '/' + self.md5name)

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

        # the system image is stored as squashfs embedded file
        log.info('Creating squashfs embedded disk image')
        Command.run(
            [
                'cp', '-l', self.diskname,
                self.squashed_contents + '/' + self.squashed_diskname
            ]
        )
        squashed_image_file = ''.join(
            [
                self.target_dir, '/', self.squashed_diskname, '.squashfs'
            ]
        )
        squashed_image = FileSystemSquashFs(
            device_provider=None, root_dir=self.squashed_contents
        )
        squashed_image.create_on_file(squashed_image_file)
        Command.run(
            ['mv', squashed_image_file, self.media_dir]
        )

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

        # setup bootloader config to boot the ISO via EFI
        bootloader_config_grub = BootLoaderConfig(
            'grub2', self.xml_state, self.media_dir, {
                'grub_directory_name':
                    Defaults.get_grub_boot_directory_name(self.root_dir)
            }
        )
        bootloader_config_grub.setup_install_boot_images(
            mbrid=self.mbrid,
            lookup_path=self.boot_image_task.boot_root_directory
        )
        bootloader_config_grub.setup_install_image_config(
            mbrid=self.mbrid
        )
        bootloader_config_grub.write()

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

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

        # make it hybrid
        Iso.create_hybrid(
            iso_header_offset, self.mbrid, self.isoname
        )
Beispiel #28
0
    def create_on_file(self, filename, label=None, exclude=None):
        """
        Create iso filesystem from data tree

        There is no label which could be set for iso filesystem
        thus this parameter is not used

        :param string filename: result file path name
        :param string label: unused
        :param string exclude: unused
        """
        iso = Iso(self.root_dir)
        iso.init_iso_creation_parameters(
            self.custom_args['create_options']
        )
        iso.add_efi_loader_parameters()
        Command.run(
            [
                self._find_iso_creation_tool()
            ] + iso.get_iso_creation_parameters() + [
                '-o', filename, self.root_dir
            ]
        )
        hybrid_offset = iso.create_header_end_block(filename)
        Command.run(
            [
                self._find_iso_creation_tool(),
                '-hide', iso.header_end_name,
                '-hide-joliet', iso.header_end_name
            ] + iso.get_iso_creation_parameters() + [
                '-o', filename, self.root_dir
            ]
        )
        iso.relocate_boot_catalog(filename)
        iso.fix_boot_catalog(filename)
        return hybrid_offset
Beispiel #29
0
 def test_set_media_tag(self, mock_command):
     Iso.set_media_tag('foo')
     mock_command.assert_called_once_with(
         ['tagmedia', '--md5', '--check', '--pad', '150', 'foo'])
Beispiel #30
0
    def create_install_iso(self):
        """
        Create an install ISO from the disk_image as hybrid ISO
        bootable via legacy BIOS, EFI and as disk from Stick

        Image types which triggers this builder are:

        * installiso="true|false"
        * installstick="true|false"
        """
        self.media_dir = mkdtemp(
            prefix='kiwi_install_media.', dir=self.target_dir
        )
        # custom iso metadata
        self.custom_iso_args = {
            'create_options': [
                '-V', Defaults.get_install_volume_id(),
                '-A', self.mbrid.get_id()
            ]
        }

        # the system image transfer is checked against a checksum
        log.info('Creating disk image checksum')
        self.squashed_contents = mkdtemp(
            prefix='kiwi_install_squashfs.', dir=self.target_dir
        )
        checksum = Checksum(self.diskname)
        checksum.md5(self.squashed_contents + '/' + self.md5name)

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

        # the system image is stored as squashfs embedded file
        log.info('Creating squashfs embedded disk image')
        Command.run(
            [
                'cp', '-l', self.diskname,
                self.squashed_contents + '/' + self.squashed_diskname
            ]
        )
        squashed_image_file = ''.join(
            [
                self.target_dir, '/', self.squashed_diskname, '.squashfs'
            ]
        )
        squashed_image = FileSystemSquashFs(
            device_provider=None, root_dir=self.squashed_contents
        )
        squashed_image.create_on_file(squashed_image_file)
        Command.run(
            ['mv', squashed_image_file, self.media_dir]
        )

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

        # setup bootloader config to boot the ISO via EFI
        bootloader_config_grub = BootLoaderConfig(
            'grub2', self.xml_state, self.media_dir, {
                'grub_directory_name':
                    Defaults.get_grub_boot_directory_name(self.root_dir)
            }
        )
        bootloader_config_grub.setup_install_boot_images(
            mbrid=self.mbrid, lookup_path=self.root_dir
        )
        bootloader_config_grub.setup_install_image_config(
            mbrid=self.mbrid
        )
        bootloader_config_grub.write()

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

        # the system image initrd is stored to allow kexec
        self._copy_system_image_initrd_to_iso_image()

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

        # make it hybrid
        Iso.create_hybrid(
            iso_header_offset, self.mbrid, self.isoname,
            self.firmware.efi_mode()
        )