diff --git a/dracut/modules.d/90kiwi-dump/kiwi-ramdisk-deployment-generator.sh b/dracut/modules.d/90kiwi-dump/kiwi-ramdisk-deployment-generator.sh index 44f17632..cfc13a88 100755 --- a/dracut/modules.d/90kiwi-dump/kiwi-ramdisk-deployment-generator.sh +++ b/dracut/modules.d/90kiwi-dump/kiwi-ramdisk-deployment-generator.sh @@ -11,6 +11,8 @@ root_uuid=$( grep root= | cut -f2- -d= ) +[ -z "${root_uuid}" ] && exit 1 + { echo "[Unit]" echo "Before=initrd-root-fs.target" diff --git a/dracut/modules.d/90kiwi-dump/module-setup.sh b/dracut/modules.d/90kiwi-dump/module-setup.sh index fdeb886c..33adad05 100755 --- a/dracut/modules.d/90kiwi-dump/module-setup.sh +++ b/dracut/modules.d/90kiwi-dump/module-setup.sh @@ -1,5 +1,10 @@ #!/bin/bash +# called by dracut +check() { + return 255 +} + # called by dracut depends() { echo network rootfs-block dm kiwi-lib diff --git a/dracut/modules.d/90kiwi-overlay/module-setup.sh b/dracut/modules.d/90kiwi-overlay/module-setup.sh index 16116408..1002b974 100755 --- a/dracut/modules.d/90kiwi-overlay/module-setup.sh +++ b/dracut/modules.d/90kiwi-overlay/module-setup.sh @@ -1,5 +1,10 @@ #!/bin/bash +# called by dracut +check() { + return 255 +} + # called by dracut depends() { echo rootfs-block dm diff --git a/dracut/modules.d/90kiwi-repart/module-setup.sh b/dracut/modules.d/90kiwi-repart/module-setup.sh index e608da77..a1a54257 100755 --- a/dracut/modules.d/90kiwi-repart/module-setup.sh +++ b/dracut/modules.d/90kiwi-repart/module-setup.sh @@ -1,5 +1,10 @@ #!/bin/bash +# called by dracut +check() { + return 255 +} + # called by dracut depends() { echo rootfs-block dm kiwi-lib diff --git a/kiwi/boot/image/base.py b/kiwi/boot/image/base.py index 71f337a4..fc5b6bb4 100644 --- a/kiwi/boot/image/base.py +++ b/kiwi/boot/image/base.py @@ -92,6 +92,48 @@ class BootImageBase: """ pass + def include_module(self, module, install_media=False): + """ + Include module to boot image + + For kiwi boot no modules configuration is required. Thus in + such a case this method is a noop. + + :param string module: module to include + :param bool install_media: include the module for install initrds + """ + pass + + def omit_module(self, module, install_media=False): + """ + Omit module to boot image + + For kiwi boot no modules configuration is required. Thus in + such a case this method is a noop. + + :param string module: module to omit + :param bool install_media: omit the module for install initrds + """ + pass + + def write_system_config_file( + self, config, config_file=None + ): + """ + Writes relevant boot image configuration into configuration file + that will be part of the system image. + + This is used to configure any further boot image rebuilds after + deployment. For instance, initrds recreated on kernel update. + + For kiwi boot no specific configuration is required for initrds + recreation, thus this method is a noop in that case. + + :param dict config: dictonary including configuration parameters + :param string config_file: configuration file to write + """ + pass + def dump(self, filename): """ Pickle dump this instance to a file. If the object dump diff --git a/kiwi/boot/image/dracut.py b/kiwi/boot/image/dracut.py index 33818dcd..693c0d13 100644 --- a/kiwi/boot/image/dracut.py +++ b/kiwi/boot/image/dracut.py @@ -45,6 +45,10 @@ class BootImageDracut(BootImageBase): self.dracut_options = [] self.included_files = [] self.included_files_install = [] + self.modules = [] + self.install_modules = [] + self.omit_modules = [] + self.omit_install_modules = [] def include_file(self, filename, install_media=False): """ @@ -58,6 +62,58 @@ class BootImageDracut(BootImageBase): self.included_files_install.append('--install') self.included_files_install.append(filename) + def include_module(self, module, install_media=False): + """ + Include module to dracut boot image + + :param string module: module to include + :param bool install_media: include the module for install initrds + """ + if install_media and module not in self.install_modules: + self.install_modules.append(module) + elif module not in self.modules: + self.modules.append(module) + + def omit_module(self, module, install_media=False): + """ + Omit module to dracut boot image + + :param string module: module to omit + :param bool install_media: omit the module for install initrds + """ + if install_media and module not in self.omit_install_modules: + self.omit_install_modules.append(module) + elif module not in self.omit_modules: + self.omit_modules.append(module) + + def write_system_config_file(self, config, config_file=None): + """ + Writes modules configuration into a dracut configuration file. + + :param dict config: a dictionary containing the modules to add and omit + :param string conf_file: configuration file to write + """ + dracut_config = [] + if not config_file: + config_file = os.path.normpath( + self.boot_root_directory + Defaults.get_dracut_conf_name() + ) + if config.get('modules'): + dracut_config.append( + 'add_dracutmodules+=" {0} "\n'.format( + ' '.join(config['modules']) + ) + ) + if config.get('omit_modules'): + dracut_config.append( + 'omit_dracutmodules+=" {0} "\n'.format( + ' '.join(config['omit_modules']) + ) + ) + if dracut_config: + with open(config_file, 'w') as config: + config.writelines(dracut_config) + def prepare(self): """ Prepare dracut caller environment @@ -95,9 +151,25 @@ class BootImageDracut(BootImageBase): dracut_initrd_basename = self.initrd_base_name if install_initrd: included_files = self.included_files_install + modules_args = [ + '--add', ' {0} '.format(' '.join(self.install_modules)) + ] if self.install_modules else [] + omit_modules_args = [ + '--omit', ' {0} '.format( + ' '.join(self.omit_install_modules) + ) + ] if self.omit_install_modules else [] else: included_files = self.included_files + modules_args = [ + '--add', ' {0} '.format(' '.join(self.modules)) + ] if self.modules else [] + omit_modules_args = [ + '--omit', ' {0} '.format(' '.join(self.omit_modules)) + ] if self.omit_install_modules else [] dracut_initrd_basename += '.xz' + options = self.dracut_options + modules_args +\ + omit_modules_args + included_files dracut_call = Command.run( [ 'chroot', self.boot_root_directory, @@ -105,7 +177,7 @@ class BootImageDracut(BootImageBase): '--no-hostonly', '--no-hostonly-cmdline', '--xz' - ] + self.dracut_options + included_files + [ + ] + options + [ dracut_initrd_basename, kernel_details.version ], diff --git a/kiwi/builder/disk.py b/kiwi/builder/disk.py index dd7987e5..33e548fe 100644 --- a/kiwi/builder/disk.py +++ b/kiwi/builder/disk.py @@ -373,15 +373,19 @@ class DiskBuilder: self._write_generic_fstab_to_system_image(device_map) if self.initrd_system == 'dracut': - self._create_dracut_config() + if self.root_filesystem_is_multipath is False: + self.boot_image.omit_module('multipath') + if self.root_filesystem_is_overlay: + self.boot_image.include_module('kiwi-overlay') + self.boot_image.write_system_config_file( + config={'modules': ['kiwi-overlay']} + ) + if self.build_type_name == 'oem': + self.boot_image.include_module('kiwi-repart') # create initrd cpio archive self.boot_image.create_initrd(self.mbrid) - # create dracut config omitting one time kiwi dracut modules - if self.initrd_system == 'dracut': - self._create_system_dracut_config() - # create second stage metadata to system image self._copy_first_boot_files_to_system_image() @@ -769,55 +773,6 @@ class DiskBuilder: return self.disk.get_device() - def _create_dracut_config(self): - dracut_config = [ - 'hostonly="no"', - 'dracut_rescue_image="no"' - ] - dracut_modules = [] - dracut_modules_omit = ['kiwi-live', 'kiwi-dump'] - if self.root_filesystem_is_multipath is False: - dracut_modules_omit.append('multipath') - if self.root_filesystem_is_overlay: - dracut_modules.append('kiwi-overlay') - else: - dracut_modules_omit.append('kiwi-overlay') - if self.build_type_name == 'oem': - dracut_modules.append('kiwi-lib') - dracut_modules.append('kiwi-repart') - self._write_dracut_config( - config=dracut_config, - modules=dracut_modules, - omit_modules=dracut_modules_omit - ) - - def _create_system_dracut_config(self): - dracut_modules = [] - dracut_modules_omit = ['kiwi-live', 'kiwi-dump', 'kiwi-repart'] - if self.root_filesystem_is_overlay: - dracut_modules.append('kiwi-overlay') - else: - dracut_modules_omit.append('kiwi-overlay') - self._write_dracut_config( - config=[], modules=dracut_modules, omit_modules=dracut_modules_omit - ) - - def _write_dracut_config(self, config, modules, omit_modules): - dracut_config_file = ''.join( - [self.root_dir, Defaults.get_dracut_conf_name()] - ) - if modules: - config.append( - 'add_dracutmodules+=" {0} "'.format(' '.join(modules)) - ) - if omit_modules: - config.append( - 'omit_dracutmodules+=" {0} "'.format(' '.join(omit_modules)) - ) - with open(dracut_config_file, 'w') as dracut_config: - for entry in config: - dracut_config.write(entry + os.linesep) - def _write_partition_id_config_to_boot_image(self): log.info('Creating config.partids in boot system') filename = ''.join( diff --git a/kiwi/builder/install.py b/kiwi/builder/install.py index 145c8f02..afda0908 100644 --- a/kiwi/builder/install.py +++ b/kiwi/builder/install.py @@ -358,7 +358,13 @@ class InstallImageBuilder: self.boot_image_task.boot_root_directory ) if self.initrd_system == 'dracut': - self._create_dracut_install_config() + self.boot_image_task.include_module( + 'kiwi-dump', install_media=True + ) + if self.root_filesystem_is_multipath is False: + self.boot_image_task.omit_module( + 'multipath', install_media=True + ) self._add_system_image_boot_options_to_boot_image() self.boot_image_task.create_initrd( self.mbrid, 'initrd_kiwi_install', @@ -392,7 +398,13 @@ class InstallImageBuilder: self.boot_image_task.boot_root_directory ) if self.initrd_system == 'dracut': - self._create_dracut_install_config() + self.boot_image_task.include_module( + 'kiwi-dump', install_media=True + ) + if self.root_filesystem_is_multipath is False: + self.boot_image_task.omit_module( + 'multipath', install_media=True + ) self._add_system_image_boot_options_to_boot_image() self.boot_image_task.create_initrd( self.mbrid, 'initrd_kiwi_install', @@ -433,33 +445,8 @@ class InstallImageBuilder: with open(initrd_trigger, 'w') as vmx_system: vmx_system.write('IMAGE="%s"\n' % self.squashed_diskname) - def _create_dracut_install_config(self): - dracut_config = [ - 'hostonly="no"', - 'dracut_rescue_image="no"' - ] - dracut_modules = ['kiwi-lib', 'kiwi-dump'] - dracut_modules_omit = ['kiwi-overlay', 'kiwi-live', 'kiwi-repart'] - if self.root_filesystem_is_multipath is False: - dracut_modules_omit.append('multipath') - dracut_config.append( - 'add_dracutmodules+=" {0} "'.format(' '.join(dracut_modules)) - ) - dracut_config.append( - 'omit_dracutmodules+=" {0} "'.format(' '.join(dracut_modules_omit)) - ) - with open(self.dracut_config_file, 'w') as config: - for entry in dracut_config: - config.write(entry + os.linesep) - - def _delete_dracut_install_config(self): - if os.path.exists(self.dracut_config_file): - os.remove(self.dracut_config_file) - def __del__(self): log.info('Cleaning up %s instance', type(self).__name__) - if self.initrd_system == 'dracut': - self._delete_dracut_install_config() if self.media_dir: Path.wipe(self.media_dir) if self.pxe_dir: diff --git a/kiwi/builder/live.py b/kiwi/builder/live.py index a3c87458..7d35da1b 100644 --- a/kiwi/builder/live.py +++ b/kiwi/builder/live.py @@ -182,7 +182,19 @@ class LiveImageBuilder: # create dracut initrd for live image log.info('Creating live ISO boot image') - self._create_dracut_live_iso_config() + live_dracut_module = Defaults.get_live_dracut_module_from_flag( + self.live_type + ) + self.boot_image.include_module('pollcdrom') + self.boot_image.include_module(live_dracut_module) + self.boot_image.omit_module('multipath') + self.boot_image.write_system_config_file( + config={ + 'modules': ['pollcdrom', live_dracut_module], + '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 @@ -293,23 +305,6 @@ class LiveImageBuilder: ) return self.result - def _create_dracut_live_iso_config(self): - live_config_file = self.root_dir + '/etc/dracut.conf.d/02-livecd.conf' - omit_modules = [ - 'kiwi-dump', 'kiwi-overlay', 'kiwi-repart', 'kiwi-lib', 'multipath' - ] - live_config = [ - 'add_dracutmodules+=" {0} pollcdrom "'.format( - Defaults.get_live_dracut_module_from_flag(self.live_type) - ), - 'omit_dracutmodules+=" {0} "'.format(' '.join(omit_modules)), - 'hostonly="no"', - 'dracut_rescue_image="no"' - ] - with open(live_config_file, 'w') as config: - for entry in live_config: - config.write(entry + os.linesep) - def _setup_live_iso_kernel_and_initrd(self): """ Copy kernel and initrd from the root tree into the iso boot structure diff --git a/test/unit/boot_image_base_test.py b/test/unit/boot_image_base_test.py index 0c419f2d..15b917f5 100644 --- a/test/unit/boot_image_base_test.py +++ b/test/unit/boot_image_base_test.py @@ -116,3 +116,8 @@ class TestBootImageBase: @raises(NotImplementedError) def test_get_boot_names(self): self.boot_image.get_boot_names() + + def test_noop_methods(self): + self.boot_image.include_module('module') + self.boot_image.omit_module('module') + self.boot_image.write_system_config_file({'config_key': 'value'}) diff --git a/test/unit/boot_image_dracut_test.py b/test/unit/boot_image_dracut_test.py index 958ccf59..857b578d 100644 --- a/test/unit/boot_image_dracut_test.py +++ b/test/unit/boot_image_dracut_test.py @@ -57,6 +57,50 @@ class TestBootImageKiwi: ] assert self.boot_image.included_files_install == [] + def test_include_module(self): + self.boot_image.include_module('foobar') + assert self.boot_image.modules == ['foobar'] + assert self.boot_image.install_modules == [] + + self.boot_image.include_module('module', install_media=True) + self.boot_image.include_module('foobar') + assert self.boot_image.modules == ['foobar'] + assert self.boot_image.install_modules == ['module'] + + def test_omit_module(self): + self.boot_image.omit_module('foobar') + assert self.boot_image.omit_modules == ['foobar'] + assert self.boot_image.omit_install_modules == [] + + self.boot_image.omit_module('module', install_media=True) + self.boot_image.omit_module('foobar') + assert self.boot_image.omit_modules == ['foobar'] + assert self.boot_image.omit_install_modules == ['module'] + + def test_write_system_config_file(self): + with patch('builtins.open', create=True) as mock_write: + self.boot_image.write_system_config_file( + config={'modules': ['module'], 'omit_modules': ['foobar']}, + config_file='/root/dir/my_dracut_conf.conf' + ) + assert call().__enter__().writelines( + [ + 'add_dracutmodules+=" module "\n', + 'omit_dracutmodules+=" foobar "\n' + ] + ) in mock_write.mock_calls + assert call( + '/root/dir/my_dracut_conf.conf', 'w' + ) in mock_write.mock_calls + + with patch('builtins.open', create=True) as mock_write: + self.boot_image.write_system_config_file( + config={'modules': ['module'], 'omit_modules': ['foobar']}, + ) + assert call( + 'system-directory/etc/dracut.conf.d/02-kiwi.conf', 'w' + ) in mock_write.mock_calls + def test_include_file_install(self): self.boot_image.include_file('foo', install_media=True) assert self.boot_image.included_files == [ diff --git a/test/unit/builder_disk_test.py b/test/unit/builder_disk_test.py index c1fe49bc..3fab7051 100644 --- a/test/unit/builder_disk_test.py +++ b/test/unit/builder_disk_test.py @@ -462,8 +462,6 @@ class TestDiskBuilder: assert mock_open.call_args_list == [ call('boot_dir/config.partids', 'w'), call('root_dir/boot/mbrid', 'w'), - call('root_dir/etc/dracut.conf.d/02-kiwi.conf', 'w'), - call('root_dir/etc/dracut.conf.d/02-kiwi.conf', 'w'), call('boot_dir/config.bootoptions', 'w'), call('/dev/some-loop', 'wb') ] @@ -471,13 +469,6 @@ class TestDiskBuilder: call('kiwi_BootPart="1"\n'), call('kiwi_RootPart="1"\n'), call('0x0f0f0f0f\n'), - call('hostonly="no"\n'), - call('dracut_rescue_image="no"\n'), - # before dracut is called, image dracut setup - call('add_dracutmodules+=" kiwi-lib kiwi-repart "\n'), - call('omit_dracutmodules+=" kiwi-live kiwi-dump multipath kiwi-overlay "\n'), - # after dracut was called, system dracut setup - call('omit_dracutmodules+=" kiwi-live kiwi-dump kiwi-repart kiwi-overlay "\n'), call('boot_cmdline\n'), call(bytes(b'\x0f\x0f\x0f\x0f')) ] @@ -495,6 +486,11 @@ class TestDiskBuilder: call('/config.partids'), call('/recovery.partition.size') ] + self.boot_image_task.include_module.assert_called_once_with( + 'kiwi-repart' + ) + self.boot_image_task.omit_module.assert_called_once_with('multipath') + assert self.boot_image_task.write_system_config_file.call_args_list == [] @patch('kiwi.builder.disk.FileSystem') @patch('kiwi.builder.disk.FileSystemSquashFs') @@ -543,17 +539,16 @@ class TestDiskBuilder: call('kiwi_BootPart="1"\n'), call('kiwi_RootPart="1"\n'), call('0x0f0f0f0f\n'), - call('hostonly="no"\n'), - call('dracut_rescue_image="no"\n'), - # before dracut is called, image dracut setup - call('add_dracutmodules+=" kiwi-overlay kiwi-lib kiwi-repart "\n'), - call('omit_dracutmodules+=" kiwi-live kiwi-dump multipath "\n'), - # after dracut was called, system dracut setup - call('add_dracutmodules+=" kiwi-overlay "\n'), - call('omit_dracutmodules+=" kiwi-live kiwi-dump kiwi-repart "\n'), call('boot_cmdline\n'), call(b'\x0f\x0f\x0f\x0f') ] + assert self.boot_image_task.include_module.call_args_list == [ + call('kiwi-overlay'), call('kiwi-repart') + ] + self.boot_image_task.omit_module.assert_called_once_with('multipath') + self.boot_image_task.write_system_config_file.assert_called_once_with( + config={'modules': ['kiwi-overlay']} + ) @patch('kiwi.builder.disk.FileSystem') @patch_open diff --git a/test/unit/builder_install_test.py b/test/unit/builder_install_test.py index d57c8938..f885997b 100644 --- a/test/unit/builder_install_test.py +++ b/test/unit/builder_install_test.py @@ -213,22 +213,21 @@ class TestInstallImageBuilder: self.install_image.create_install_iso() + self.boot_image_task.include_module.assert_called_once_with( + 'kiwi-dump', install_media=True + ) + self.boot_image_task.omit_module.assert_called_once_with( + 'multipath', install_media=True + ) + self.boot_image_task.include_file.assert_called_once_with( '/config.bootoptions', install_media=True ) assert mock_open.call_args_list == [ call('temp_media_dir/config.isoclient', 'w'), - call('root_dir/etc/dracut.conf.d/02-kiwi.conf', 'w') ] assert file_mock.write.call_args_list == [ - call('IMAGE="result-image.raw"\n'), - call('hostonly="no"\n'), - call('dracut_rescue_image="no"\n'), - call('add_dracutmodules+=" kiwi-lib kiwi-dump "\n'), - call( - 'omit_dracutmodules+=" kiwi-overlay kiwi-live kiwi-repart ' - 'multipath "\n' - ) + call('IMAGE="result-image.raw"\n') ] mock_BootLoaderConfig.reset_mock() @@ -392,7 +391,6 @@ class TestInstallImageBuilder: ] assert mock_open.call_args_list == [ call('tmpdir/result-image.append', 'w'), - call('root_dir/etc/dracut.conf.d/02-kiwi.conf', 'w') ] assert file_mock.write.call_args_list == [ call( @@ -401,26 +399,25 @@ class TestInstallImageBuilder: 'rd.kiwi.install.image=http://example.com/image.xz', 'custom_kernel_options\n' ]) - ), - call('hostonly="no"\n'), - call('dracut_rescue_image="no"\n'), - call('add_dracutmodules+=" kiwi-lib kiwi-dump "\n'), - call('omit_dracutmodules+=" kiwi-overlay kiwi-live kiwi-repart multipath "\n') + ) ] + self.boot_image_task.include_module.assert_called_once_with( + 'kiwi-dump', install_media=True + ) + self.boot_image_task.omit_module.assert_called_once_with( + 'multipath', install_media=True + ) + @patch('kiwi.builder.install.Path.wipe') @patch('os.path.exists') - @patch('os.remove') - def test_destructor(self, mock_remove, mock_exists, mock_wipe): + def test_destructor(self, mock_exists, mock_wipe): mock_exists.return_value = True self.install_image.initrd_system = 'dracut' self.install_image.pxe_dir = 'pxe-dir' self.install_image.media_dir = 'media-dir' self.install_image.squashed_contents = 'squashed-dir' self.install_image.__del__() - mock_remove.assert_called_once_with( - 'root_dir/etc/dracut.conf.d/02-kiwi.conf' - ) assert mock_wipe.call_args_list == [ call('media-dir'), call('pxe-dir'), call('squashed-dir') ] diff --git a/test/unit/builder_live_test.py b/test/unit/builder_live_test.py index 94661aaf..390b44e9 100644 --- a/test/unit/builder_live_test.py +++ b/test/unit/builder_live_test.py @@ -213,19 +213,17 @@ class TestLiveImageBuilder: working_directory='root_dir' ) - assert call( - 'root_dir/etc/dracut.conf.d/02-livecd.conf', 'w' - ) in mock_open.call_args_list - - assert self.file_mock.write.call_args_list == [ - call('add_dracutmodules+=" kiwi-live pollcdrom "\n'), - call( - 'omit_dracutmodules+=" ' - 'kiwi-dump kiwi-overlay kiwi-repart kiwi-lib multipath "\n' - ), - call('hostonly="no"\n'), - call('dracut_rescue_image="no"\n') + assert self.boot_image_task.include_module.call_args_list == [ + call('pollcdrom'), call('kiwi-live') ] + self.boot_image_task.omit_module.assert_called_once_with('multipath') + self.boot_image_task.write_system_config_file.assert_called_once_with( + config={ + 'modules': ['pollcdrom', 'kiwi-live'], + 'omit_modules': ['multipath'] + }, + config_file='root_dir/etc/dracut.conf.d/02-livecd.conf' + ) kiwi.builder.live.BootLoaderConfig.assert_called_once_with( 'grub2', self.xml_state, root_dir='root_dir',