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) ]
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')
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') ) ]
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') ]
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' ) ]
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' ])
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')
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')
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')
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')
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')
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' ])
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')
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')
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' ] )
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' ] )
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 ) ]
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')
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
def test_init_for_ix86_platform(self, mock_machine, mock_tempfile): mock_machine.return_value = 'i686' iso = Iso('source-dir') assert iso.arch == 'ix86'
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'] )
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')
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')
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 ) ]
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
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 )
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
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'])
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() )