class TestFileSystemIsoFs(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.isofs = FileSystemIsoFs(mock.Mock(), 'root_dir') def test_post_init(self): self.isofs.post_init({'some_args': 'data'}) assert self.isofs.custom_args['create_options'] == [] assert self.isofs.custom_args['mount_options'] == [] assert self.isofs.custom_args['some_args'] == 'data' @patch('kiwi.filesystem.isofs.Command.run') @patch('kiwi.filesystem.isofs.Iso') def test_create_on_file(self, mock_iso, mock_command): iso = mock.Mock() iso.header_end_name = 'header_end' iso.get_iso_creation_parameters = mock.Mock(return_value=['args']) mock_iso.return_value = iso self.isofs.create_on_file('myimage', None) iso.init_iso_creation_parameters.assert_called_once_with([]) iso.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with('myimage') mock_command.call_args_list == [ call(['genisoimage', 'args', '-o', 'myimage', 'root_dir']), call([ 'genisoimage', '-hide', 'header_end', '-hide-joliet', 'header_end', 'args', '-o', 'myimage', 'root_dir' ]) ] iso.relocate_boot_catalog.assert_called_once_with('myimage') iso.fix_boot_catalog.assert_called_once_with('myimage')
class TestFileSystemIsoFs(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.isofs = FileSystemIsoFs(mock.Mock(), 'root_dir') def test_post_init(self): self.isofs.post_init({'some_args': 'data'}) assert self.isofs.custom_args['meta_data'] == {} assert self.isofs.custom_args['mount_options'] == [] assert self.isofs.custom_args['some_args'] == 'data' @patch('kiwi.filesystem.isofs.IsoTools') @patch('kiwi.filesystem.isofs.Iso') def test_create_on_file(self, mock_iso, mock_cdrtools): iso_tool = mock.Mock() iso_tool.has_iso_hybrid_capability = mock.Mock( return_value=False ) iso_tool.get_tool_name = mock.Mock( return_value='/usr/bin/mkisofs' ) iso = mock.Mock() iso.header_end_name = 'header_end' mock_cdrtools.return_value = iso_tool mock_iso.return_value = iso self.isofs.create_on_file('myimage', None) iso.setup_isolinux_boot_path.assert_called_once_with() iso.create_header_end_marker.assert_called_once_with() iso_tool.init_iso_creation_parameters.assert_called_once_with({}) iso_tool.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with('myimage') assert iso_tool.create_iso.call_args_list == [ call('myimage'), call('myimage', hidden_files=['header_end']) ] iso.relocate_boot_catalog.assert_called_once_with( 'myimage' ) iso.fix_boot_catalog.assert_called_once_with( 'myimage' ) iso.create_hybrid.assert_called_once_with( iso.create_header_end_block.return_value, '0xffffffff', 'myimage', False )
class TestFileSystemIsoFs(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.isofs = FileSystemIsoFs(mock.Mock(), 'root_dir') def test_post_init(self): self.isofs.post_init({'some_args': 'data'}) assert self.isofs.custom_args['meta_data'] == {} assert self.isofs.custom_args['mount_options'] == [] assert self.isofs.custom_args['some_args'] == 'data' @patch('kiwi.filesystem.isofs.IsoTools') @patch('kiwi.filesystem.isofs.Iso') @patch('kiwi.filesystem.isofs.platform.machine') def test_create_on_file(self, mock_platform_machine, mock_iso, mock_cdrtools): mock_platform_machine.return_value = 'x86_64' iso_tool = mock.Mock() iso_tool.has_iso_hybrid_capability = mock.Mock(return_value=False) iso_tool.get_tool_name = mock.Mock(return_value='/usr/bin/mkisofs') iso = mock.Mock() iso.header_end_name = 'header_end' mock_cdrtools.return_value = iso_tool mock_iso.return_value = iso self.isofs.create_on_file('myimage', None) iso.setup_isolinux_boot_path.assert_called_once_with() iso.create_header_end_marker.assert_called_once_with() iso_tool.init_iso_creation_parameters.assert_called_once_with({}) iso_tool.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with('myimage') assert iso_tool.create_iso.call_args_list == [ call('myimage'), call('myimage', hidden_files=['header_end']) ] iso.relocate_boot_catalog.assert_called_once_with('myimage') iso.fix_boot_catalog.assert_called_once_with('myimage') iso.create_hybrid.assert_called_once_with( iso.create_header_end_block.return_value, '0xffffffff', 'myimage', False)
class TestFileSystemIsoFs(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.isofs = FileSystemIsoFs(mock.Mock(), 'root_dir') def test_post_init(self): self.isofs.post_init({'some_args': 'data'}) assert self.isofs.custom_args['create_options'] == [] assert self.isofs.custom_args['mount_options'] == [] assert self.isofs.custom_args['some_args'] == 'data' @patch('kiwi.filesystem.isofs.Command.run') @patch('kiwi.filesystem.isofs.Iso') def test_create_on_file(self, mock_iso, mock_command): iso = mock.Mock() iso.header_end_name = 'header_end' iso.get_iso_creation_parameters = mock.Mock( return_value=['args'] ) mock_iso.return_value = iso self.isofs.create_on_file('myimage', None) iso.init_iso_creation_parameters.assert_called_once_with([]) iso.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with( 'myimage' ) mock_command.call_args_list == [ call([ 'genisoimage', 'args', '-o', 'myimage', 'root_dir' ]), call([ 'genisoimage', '-hide', 'header_end', '-hide-joliet', 'header_end', 'args', '-o', 'myimage', 'root_dir' ]) ] iso.relocate_boot_catalog.assert_called_once_with( 'myimage' ) iso.fix_boot_catalog.assert_called_once_with( 'myimage' )
class TestFileSystemIsoFs: @fixture(autouse=True) def inject_fixtures(self, caplog): self._caplog = caplog @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.isofs = FileSystemIsoFs(mock.Mock(), 'root_dir') def test_post_init(self): self.isofs.post_init({'some_args': 'data'}) assert self.isofs.custom_args['meta_data'] == {} assert self.isofs.custom_args['mount_options'] == [] assert self.isofs.custom_args['some_args'] == 'data' @patch('kiwi.filesystem.isofs.IsoTools') @patch('kiwi.filesystem.isofs.Iso') def test_create_on_file(self, mock_iso, mock_cdrtools): iso_tool = mock.Mock() iso_tool.has_iso_hybrid_capability = mock.Mock(return_value=False) iso_tool.get_tool_name = mock.Mock(return_value='/usr/bin/mkisofs') iso = mock.Mock() iso.header_end_name = 'header_end' mock_cdrtools.new.return_value = iso_tool mock_iso.return_value = iso self.isofs.create_on_file('myimage', None) iso.setup_isolinux_boot_path.assert_called_once_with() iso.create_header_end_marker.assert_called_once_with() iso_tool.init_iso_creation_parameters.assert_called_once_with({}) iso_tool.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with('myimage') assert iso_tool.create_iso.call_args_list == [ call('myimage'), call('myimage', hidden_files=['header_end']) ] iso.relocate_boot_catalog.assert_called_once_with('myimage') iso.fix_boot_catalog.assert_called_once_with('myimage') iso.create_hybrid.assert_called_once_with( iso.create_header_end_block.return_value, '0xffffffff', 'myimage') @patch('kiwi.filesystem.isofs.IsoTools') @patch('kiwi.filesystem.isofs.Iso') def test_create_on_file_EFI_enabled(self, mock_iso, mock_cdrtools): iso_tool = mock.Mock() iso_tool.has_iso_hybrid_capability = mock.Mock(return_value=False) iso_tool.get_tool_name = mock.Mock(return_value='/usr/bin/mkisofs') iso = mock.Mock() iso.header_end_name = 'header_end' mock_cdrtools.new.return_value = iso_tool mock_iso.return_value = iso self.isofs.custom_args['meta_data']['efi_mode'] = 'uefi' with self._caplog.at_level(logging.WARNING): self.isofs.create_on_file('myimage') iso_tool.create_iso.assert_called_once_with('myimage')
def setup(self, mock_exists): mock_exists.return_value = True self.isofs = FileSystemIsoFs(mock.Mock(), 'root_dir')
def create_install_iso(self) -> None: """ 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 ) # unpack cdroot user files to media dir self.setup.import_cdroot_files(self.media_dir) # custom iso metadata self.custom_iso_args = { 'meta_data': { 'volume_id': self.iso_volume_id, 'mbr_id': self.mbrid.get_id(), 'efi_mode': self.firmware.efi_mode(), 'ofw_mode': self.firmware.ofw_mode() } } # 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=DeviceProvider(), root_dir=self.squashed_contents, custom_args={ 'compression': self.xml_state.build_type.get_squashfscompression() } ) squashed_image.create_on_file(squashed_image_file) Command.run( ['mv', squashed_image_file, self.media_dir] ) log.info( 'Setting up install image bootloader configuration' ) if self.firmware.efi_mode(): # setup bootloader config to boot the ISO via EFI # This also embedds an MBR and the respective BIOS modules # for compat boot. The complete bootloader setup will be # based on grub bootloader_config = BootLoaderConfig.new( 'grub2', self.xml_state, root_dir=self.root_dir, boot_dir=self.media_dir, custom_args={ 'grub_directory_name': Defaults.get_grub_boot_directory_name(self.root_dir) } ) bootloader_config.setup_install_boot_images( mbrid=self.mbrid, lookup_path=self.boot_image_task.boot_root_directory ) else: # setup bootloader config to boot the ISO via isolinux. # This allows for booting on x86 platforms in BIOS mode # only. bootloader_config = BootLoaderConfig.new( 'isolinux', self.xml_state, root_dir=self.root_dir, boot_dir=self.media_dir ) IsoToolsBase.setup_media_loader_directory( self.boot_image_task.boot_root_directory, self.media_dir, bootloader_config.get_boot_theme() ) bootloader_config.write_meta_data() bootloader_config.setup_install_image_config( mbrid=self.mbrid ) bootloader_config.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=DeviceProvider(), root_dir=self.media_dir, custom_args=self.custom_iso_args ) iso_image.create_on_file(self.isoname) self.boot_image_task.cleanup()
def create(self): """ Build a bootable hybrid live ISO image Image types which triggers this builder are: * image="iso" :raises KiwiLiveBootImageError: if no kernel or hipervisor is found in boot image tree :return: result :rtype: instance of :class:`Result` """ # media dir to store CD contents self.media_dir = mkdtemp(prefix='live-media.', dir=self.target_dir) # unpack cdroot user files to media dir self.system_setup.import_cdroot_files(self.media_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 = { 'meta_data': { 'publisher': self.publisher, 'preparer': Defaults.get_preparer(), 'volume_id': self.volume_id, 'mbr_id': self.mbrid.get_id(), 'efi_mode': self.firmware.efi_mode() } } log.info('Setting up live image bootloader configuration') if self.firmware.efi_mode(): # setup bootloader config to boot the ISO via EFI # This also embedds an MBR and the respective BIOS modules # for compat boot. The complete bootloader setup will be # based on grub bootloader_config = BootLoaderConfig( 'grub2', self.xml_state, root_dir=self.root_dir, boot_dir=self.media_dir, custom_args={ 'grub_directory_name': Defaults.get_grub_boot_directory_name(self.root_dir) }) bootloader_config.setup_live_boot_images(mbrid=self.mbrid, lookup_path=self.root_dir) else: # setup bootloader config to boot the ISO via isolinux. # This allows for booting on x86 platforms in BIOS mode # only. bootloader_config = BootLoaderConfig('isolinux', self.xml_state, root_dir=self.root_dir, boot_dir=self.media_dir) IsoToolsBase.setup_media_loader_directory( self.boot_image.boot_root_directory, self.media_dir, bootloader_config.get_boot_theme()) bootloader_config.write_meta_data() bootloader_config.setup_live_image_config(mbrid=self.mbrid) bootloader_config.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) # prepare dracut initrd call self.boot_image.prepare() # create dracut initrd for live image log.info('Creating live ISO boot image') live_dracut_modules = Defaults.get_live_dracut_modules_from_flag( self.live_type) live_dracut_modules.append('pollcdrom') for dracut_module in live_dracut_modules: self.boot_image.include_module(dracut_module) self.boot_image.omit_module('multipath') self.boot_image.write_system_config_file( config={ 'modules': live_dracut_modules, 'omit_modules': ['multipath'] }, config_file=self.root_dir + '/etc/dracut.conf.d/02-livecd.conf') 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['meta_data']['udf'] = True # 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(), 'create_options': self.xml_state.get_fs_create_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, custom_args={ 'compression': self.xml_state.build_type.get_squashfscompression() }) 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') # 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_image.create_on_file(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.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 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 )
class TestFileSystemIsoFs(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.isofs = FileSystemIsoFs(mock.Mock(), 'root_dir') def test_post_init(self): self.isofs.post_init({'some_args': 'data'}) assert self.isofs.custom_args['create_options'] == [] assert self.isofs.custom_args['mount_options'] == [] assert self.isofs.custom_args['some_args'] == 'data' @raises(KiwiIsoToolError) @patch('kiwi.filesystem.isofs.Command.run') @patch('kiwi.filesystem.isofs.Iso') @patch('kiwi.filesystem.isofs.Path.which') def test_create_on_file_no_tool_found( self, mock_which, mock_iso, mock_command ): mock_which.return_value = None self.isofs.create_on_file('myimage', None) @patch('kiwi.filesystem.isofs.Command.run') @patch('kiwi.filesystem.isofs.Iso') @patch('kiwi.filesystem.isofs.Path.which') def test_create_on_file_mkisofs( self, mock_which, mock_iso, mock_command ): iso = mock.Mock() iso.header_end_name = 'header_end' iso.get_iso_creation_parameters = mock.Mock( return_value=['args'] ) mock_iso.return_value = iso path_return_values = [ '/usr/bin/mkisofs', '/usr/bin/mkisofs' ] def side_effect(arg): return path_return_values.pop() mock_which.side_effect = side_effect self.isofs.create_on_file('myimage', None) iso.init_iso_creation_parameters.assert_called_once_with([]) iso.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with( 'myimage' ) assert mock_command.call_args_list == [ call([ '/usr/bin/mkisofs', 'args', '-o', 'myimage', 'root_dir' ]), call([ '/usr/bin/mkisofs', '-hide', 'header_end', '-hide-joliet', 'header_end', 'args', '-o', 'myimage', 'root_dir' ]) ] iso.relocate_boot_catalog.assert_called_once_with( 'myimage' ) iso.fix_boot_catalog.assert_called_once_with( 'myimage' ) @patch('kiwi.filesystem.isofs.Command.run') @patch('kiwi.filesystem.isofs.Iso') @patch('kiwi.filesystem.isofs.Path.which') def test_create_on_file_genisoimage( self, mock_which, mock_iso, mock_command ): iso = mock.Mock() iso.header_end_name = 'header_end' iso.get_iso_creation_parameters = mock.Mock( return_value=['args'] ) mock_iso.return_value = iso path_return_values = [ '/usr/bin/genisoimage', None, '/usr/bin/genisoimage', None ] def side_effect(arg): return path_return_values.pop() mock_which.side_effect = side_effect self.isofs.create_on_file('myimage', None) iso.init_iso_creation_parameters.assert_called_once_with([]) iso.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with( 'myimage' ) assert mock_command.call_args_list == [ call([ '/usr/bin/genisoimage', 'args', '-o', 'myimage', 'root_dir' ]), call([ '/usr/bin/genisoimage', '-hide', 'header_end', '-hide-joliet', 'header_end', 'args', '-o', 'myimage', 'root_dir' ]) ] iso.relocate_boot_catalog.assert_called_once_with( 'myimage' ) iso.fix_boot_catalog.assert_called_once_with( 'myimage' )
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() )
def create(self): """ Build a bootable hybrid live ISO image Image types which triggers this builder are: * image="iso" :raises KiwiLiveBootImageError: if no kernel or hipervisor is found in boot image tree :return: result :rtype: instance of :class:`Result` """ # media dir to store CD contents self.media_dir = mkdtemp( prefix='live-media.', dir=self.target_dir ) # unpack cdroot user files to media dir self.system_setup.import_cdroot_files(self.media_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 = { 'meta_data': { 'publisher': self.publisher, 'preparer': Defaults.get_preparer(), 'volume_id': self.volume_id, 'mbr_id': self.mbrid.get_id(), 'efi_mode': self.firmware.efi_mode() } } # 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 ) # prepare dracut initrd call self.boot_image.prepare() # 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['meta_data']['udf'] = True # 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_image.create_on_file(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.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 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 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) # unpack cdroot user files to media dir self.setup.import_cdroot_files(self.media_dir) # custom iso metadata self.custom_iso_args = { 'meta_data': { 'volume_id': Defaults.get_install_volume_id(), 'mbr_id': self.mbrid.get_id(), 'efi_mode': self.firmware.efi_mode() } } # 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_image.create_on_file(self.isoname)
class TestFileSystemIsoFs(object): @patch('os.path.exists') def setup(self, mock_exists): mock_exists.return_value = True self.isofs = FileSystemIsoFs(mock.Mock(), 'root_dir') def test_post_init(self): self.isofs.post_init({'some_args': 'data'}) assert self.isofs.custom_args['create_options'] == [] assert self.isofs.custom_args['mount_options'] == [] assert self.isofs.custom_args['some_args'] == 'data' @raises(KiwiIsoToolError) @patch('kiwi.filesystem.isofs.Command.run') @patch('kiwi.filesystem.isofs.Iso') @patch('kiwi.filesystem.isofs.Path.which') def test_create_on_file_no_tool_found(self, mock_which, mock_iso, mock_command): mock_which.return_value = None self.isofs.create_on_file('myimage', None) @patch('kiwi.filesystem.isofs.Command.run') @patch('kiwi.filesystem.isofs.Iso') @patch('kiwi.filesystem.isofs.Path.which') def test_create_on_file_mkisofs(self, mock_which, mock_iso, mock_command): iso = mock.Mock() iso.header_end_name = 'header_end' iso.get_iso_creation_parameters = mock.Mock(return_value=['args']) mock_iso.return_value = iso path_return_values = ['/usr/bin/mkisofs', '/usr/bin/mkisofs'] def side_effect(arg): return path_return_values.pop() mock_which.side_effect = side_effect self.isofs.create_on_file('myimage', None) iso.init_iso_creation_parameters.assert_called_once_with([]) iso.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with('myimage') assert mock_command.call_args_list == [ call(['/usr/bin/mkisofs', 'args', '-o', 'myimage', 'root_dir']), call([ '/usr/bin/mkisofs', '-hide', 'header_end', '-hide-joliet', 'header_end', 'args', '-o', 'myimage', 'root_dir' ]) ] iso.relocate_boot_catalog.assert_called_once_with('myimage') iso.fix_boot_catalog.assert_called_once_with('myimage') @patch('kiwi.filesystem.isofs.Command.run') @patch('kiwi.filesystem.isofs.Iso') @patch('kiwi.filesystem.isofs.Path.which') def test_create_on_file_genisoimage(self, mock_which, mock_iso, mock_command): iso = mock.Mock() iso.header_end_name = 'header_end' iso.get_iso_creation_parameters = mock.Mock(return_value=['args']) mock_iso.return_value = iso path_return_values = [ '/usr/bin/genisoimage', None, '/usr/bin/genisoimage', None ] def side_effect(arg): return path_return_values.pop() mock_which.side_effect = side_effect self.isofs.create_on_file('myimage', None) iso.init_iso_creation_parameters.assert_called_once_with([]) iso.add_efi_loader_parameters.assert_called_once_with() iso.create_header_end_block.assert_called_once_with('myimage') assert mock_command.call_args_list == [ call(['/usr/bin/genisoimage', 'args', '-o', 'myimage', 'root_dir']), call([ '/usr/bin/genisoimage', '-hide', 'header_end', '-hide-joliet', 'header_end', 'args', '-o', 'myimage', 'root_dir' ]) ] iso.relocate_boot_catalog.assert_called_once_with('myimage') iso.fix_boot_catalog.assert_called_once_with('myimage')