diff --git a/kiwi/bootloader/config/base.py b/kiwi/bootloader/config/base.py index 7b57e98a..5163d252 100644 --- a/kiwi/bootloader/config/base.py +++ b/kiwi/bootloader/config/base.py @@ -25,6 +25,7 @@ from kiwi.mount_manager import MountManager from kiwi.storage.setup import DiskSetup from kiwi.path import Path from kiwi.defaults import Defaults +from kiwi.utils.block import BlockID from kiwi.exceptions import ( KiwiBootLoaderTargetError @@ -549,6 +550,7 @@ class BootLoaderConfigBase: def _get_root_cmdline_parameter(self, uuid): cmdline = self.xml_state.build_type.get_kernelcmdline() + persistency_type = self.xml_state.build_type.get_devicepersistency() if cmdline and 'root=' in cmdline: log.info( 'Kernel root device explicitly set via kernelcmdline' @@ -560,10 +562,13 @@ class BootLoaderConfigBase: if uuid and self.xml_state.build_type.get_overlayroot(): return 'root=overlay:UUID={0}'.format(uuid) elif uuid: - return 'root=UUID={0} rw'.format(uuid) + block_operation = BlockID(f'UUID={uuid}') + blkid_type = 'LABEL' if persistency_type == 'by-label' else 'UUID' + location = block_operation.get_blkid(blkid_type) + return f'root={blkid_type}={location} rw' else: log.warning( - 'root=UUID= setup requested, but uuid is not provided' + 'root setup based on UUID requested, but uuid is not provided' ) def __del__(self): diff --git a/kiwi/bootloader/config/grub2.py b/kiwi/bootloader/config/grub2.py index ef76054e..5b094dc1 100644 --- a/kiwi/bootloader/config/grub2.py +++ b/kiwi/bootloader/config/grub2.py @@ -101,6 +101,8 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase): self.failsafe_boot = self.failsafe_boot_entry_requested() self.mediacheck_boot = self.xml_state.build_type.get_mediacheck() self.xen_guest = self.xml_state.is_xen_guest() + self.persistency_type = \ + self.xml_state.build_type.get_devicepersistency() self.firmware = FirmWare( self.xml_state ) @@ -610,6 +612,7 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase): * GRUB_GFXMODE * GRUB_TERMINAL * GRUB_DISTRIBUTOR + * GRUB_DISABLE_LINUX_UUID """ grub_default_entries = { 'GRUB_TIMEOUT': self.timeout, @@ -619,6 +622,8 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase): grub_final_cmdline = re.sub( r'root=.* |root=.*$', '', self.cmdline ).strip() + if self.persistency_type != 'by-uuid': + grub_default_entries['GRUB_DISABLE_LINUX_UUID'] = 'true' if self.displayname: grub_default_entries['GRUB_DISTRIBUTOR'] = '"{0}"'.format( self.displayname @@ -1229,48 +1234,45 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase): def _fix_grub_root_device_reference(self, config_file, boot_options): if self.root_reference: - if self.root_filesystem_is_overlay or \ - self.arch.startswith('s390') or \ - Defaults.is_buildservice_worker(): - # grub2-mkconfig has no idea how the correct root= setup is - # for disk images created with overlayroot enabled or in a - # buildservice worker environment. Because of that the mkconfig - # tool just finds the raw partition loop device and includes it - # which is wrong. In this particular case we have to patch the - # written config file and replace the wrong root= reference with - # the correct value. - with open(config_file) as grub_config_file: - grub_config = grub_config_file.read() - # The following expression matches any of the following - # grub mkconfig root= settings and replaces it with a - # correct value - # 1. root=LOCAL-KIWI-MAPPED-DEVICE - # 2. root=[a-zA-Z]=ANY-LINUX-BY-ID-VALUE - grub_config = re.sub( - r'(root=[a-zA-Z]+=[a-zA-Z0-9:\.-]+)|(root={0})'.format( - boot_options.get('root_device') - ), - '{0}'.format(self.root_reference), - grub_config - ) + # grub2-mkconfig has no idea how the correct root= setup is + # for disk images created with overlayroot enabled or in a + # buildservice worker environment. Because of that the mkconfig + # tool just finds the raw partition loop device and includes it + # which is wrong. In this particular case we have to patch the + # written config file and replace the wrong root= reference with + # the correct value. + with open(config_file) as grub_config_file: + grub_config = grub_config_file.read() + # The following expression matches any of the following + # grub mkconfig root= settings and replaces it with a + # correct value + # 1. root=LOCAL-KIWI-MAPPED-DEVICE + # 2. root=[a-zA-Z]=ANY-LINUX-BY-ID-VALUE + grub_config = re.sub( + r'(root=[a-zA-Z]+=[a-zA-Z0-9:\.-]+)|(root={0})'.format( + boot_options.get('root_device') + ), + '{0}'.format(self.root_reference), + grub_config + ) - with open(config_file, 'w') as grub_config_file: - grub_config_file.write(grub_config) + with open(config_file, 'w') as grub_config_file: + grub_config_file.write(grub_config) - if self.firmware.efi_mode(): - vendor_grubenv_file = \ - Defaults.get_vendor_grubenv(self.efi_mount.mountpoint) - if vendor_grubenv_file: - with open(vendor_grubenv_file) as vendor_grubenv: - grubenv = vendor_grubenv.read() - grubenv = grubenv.replace( - 'root={0}'.format( - boot_options.get('root_device') - ), - self.root_reference - ) - with open(vendor_grubenv_file, 'w') as vendor_grubenv: - vendor_grubenv.write(grubenv) + if self.firmware.efi_mode(): + vendor_grubenv_file = \ + Defaults.get_vendor_grubenv(self.efi_mount.mountpoint) + if vendor_grubenv_file: + with open(vendor_grubenv_file) as vendor_grubenv: + grubenv = vendor_grubenv.read() + grubenv = grubenv.replace( + 'root={0}'.format( + boot_options.get('root_device') + ), + self.root_reference + ) + with open(vendor_grubenv_file, 'w') as vendor_grubenv: + vendor_grubenv.write(grubenv) def _fix_grub_loader_entries_boot_cmdline(self): if self.cmdline: diff --git a/kiwi/utils/block.py b/kiwi/utils/block.py index bc242862..65ce8df6 100644 --- a/kiwi/utils/block.py +++ b/kiwi/utils/block.py @@ -16,6 +16,7 @@ # along with kiwi. If not, see # import os +import re # project from kiwi.command import Command @@ -25,11 +26,20 @@ class BlockID: """ **Get information from a block device** - :param str device: block device node name name + :param str device: + block device node name name. The device can + also be specified as UUID= """ def __init__(self, device): - self.device = device + uuid_format = re.match(r'^UUID=(.*)', device) + if uuid_format: + blkid_result = Command.run( + ['blkid', '--uuid', uuid_format.group(1)] + ) + self.device = blkid_result.output.strip(os.linesep) + else: + self.device = device def get_label(self): """ diff --git a/test/unit/bootloader/config/base_test.py b/test/unit/bootloader/config/base_test.py index 8d66fc9a..0607703c 100644 --- a/test/unit/bootloader/config/base_test.py +++ b/test/unit/bootloader/config/base_test.py @@ -109,22 +109,26 @@ class TestBootLoaderConfigBase: mock_cmdline.return_value = 'root=/dev/myroot' assert self.bootloader.get_boot_cmdline() == 'root=/dev/myroot' - @patch('kiwi.xml_parse.type_.get_firmware') - def test_get_boot_cmdline_firmware_ec2(self, mock_firmware): - mock_firmware.return_value = 'ec2' - assert self.bootloader.get_boot_cmdline('uuid') == \ - 'splash root=UUID=uuid rw' - @patch('kiwi.xml_parse.type_.get_initrd_system') - def test_get_boot_cmdline_initrd_system_is_dracut(self, mock_initrd): + @patch('kiwi.bootloader.config.base.BlockID') + def test_get_boot_cmdline_initrd_system_is_dracut( + self, mock_BlockID, mock_initrd + ): + block_operation = Mock() + block_operation.get_blkid.return_value = 'uuid' + mock_BlockID.return_value = block_operation mock_initrd.return_value = 'dracut' assert self.bootloader.get_boot_cmdline('uuid') == \ 'splash root=UUID=uuid rw' @patch('kiwi.xml_parse.type_.get_initrd_system') + @patch('kiwi.bootloader.config.base.BlockID') def test_get_boot_cmdline_initrd_system_is_dracut_with_overlay( - self, mock_initrd + self, mock_BlockID, mock_initrd ): + block_operation = Mock() + block_operation.get_blkid.return_value = 'uuid' + mock_BlockID.return_value = block_operation mock_initrd.return_value = 'dracut' self.state.build_type.get_overlayroot = Mock( return_value=True @@ -132,12 +136,6 @@ class TestBootLoaderConfigBase: assert self.bootloader.get_boot_cmdline('uuid') == \ 'splash root=overlay:UUID=uuid' - @patch('kiwi.xml_parse.type_.get_firmware') - def test_get_boot_cmdline_firmware_ec2_no_uuid(self, mock_firmware): - mock_firmware.return_value = 'ec2' - with self._caplog.at_level(logging.WARNING): - self.bootloader.get_boot_cmdline() - @patch('kiwi.xml_parse.type_.get_installboot') def test_get_install_image_boot_default(self, mock_installboot): mock_installboot.return_value = None diff --git a/test/unit/bootloader/config/grub2_test.py b/test/unit/bootloader/config/grub2_test.py index 6b85ebf7..54bb51ad 100644 --- a/test/unit/bootloader/config/grub2_test.py +++ b/test/unit/bootloader/config/grub2_test.py @@ -539,6 +539,7 @@ class TestBootLoaderConfigGrub2: '/boot/grub2/themes/openSUSE/background.png' ), call('GRUB_CMDLINE_LINUX_DEFAULT', '"some-cmdline"'), + call('GRUB_DISABLE_LINUX_UUID', 'true'), call('GRUB_DISTRIBUTOR', '"Bob"'), call('GRUB_ENABLE_BLSCFG', 'true'), call('GRUB_ENABLE_CRYPTODISK', 'y'), @@ -580,6 +581,7 @@ class TestBootLoaderConfigGrub2: 'GRUB_BACKGROUND', '/boot/grub2/themes/openSUSE/background.png' ), + call('GRUB_DISABLE_LINUX_UUID', 'true'), call('GRUB_DISTRIBUTOR', '"Bob"'), call('GRUB_ENABLE_BLSCFG', 'true'), call('GRUB_ENABLE_CRYPTODISK', 'y'), diff --git a/test/unit/utils/block_test.py b/test/unit/utils/block_test.py index ea68fa74..3b3bb50d 100644 --- a/test/unit/utils/block_test.py +++ b/test/unit/utils/block_test.py @@ -7,6 +7,13 @@ class TestBlockID: def setup(self): self.blkid = BlockID('device') + @patch('kiwi.utils.block.Command.run') + def test_setup_with_uuid_format(self, mock_command): + BlockID('UUID=uuid') + mock_command.assert_called_once_with( + ['blkid', '--uuid', 'uuid'] + ) + @patch('kiwi.utils.block.Command.run') def test_get_blkid(self, mock_command): self.blkid.get_blkid('LABEL')