Fix use of by-label device persistency in grub
If devicepersistency="by-label" is set in the KIWI description it will correctly operate on the fstab values but still uses the UUID based setting for root= in the grub config. This commit allows to set root=LABEL=... in the grub config in case the devicepersistency requested it. In order for this to work this commit also had to increase the scope of the grub helper method _fix_grub_root_device_reference which is now called in any case. This Fixes #1757
This commit is contained in:
parent
5ef9f83e0c
commit
791adcfcb7
@ -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=<uuid> setup requested, but uuid is not provided'
|
||||
'root setup based on UUID requested, but uuid is not provided'
|
||||
)
|
||||
|
||||
def __del__(self):
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
# along with kiwi. If not, see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
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=<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):
|
||||
"""
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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'),
|
||||
|
||||
@ -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')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user