forked from rpms/leapp-repository
210 lines
9.4 KiB
Diff
210 lines
9.4 KiB
Diff
From 0a203330cee4fba6a28c65f1c6e0e450cc45771e Mon Sep 17 00:00:00 2001
|
|
From: Michal Hecko <mhecko@redhat.com>
|
|
Date: Thu, 30 Oct 2025 11:52:39 +0100
|
|
Subject: [PATCH 48/55] mount_unit_gen: bind mount /sysroot/boot to /boot
|
|
|
|
Our changes towards using systemd-fstab-generator in the upgrade
|
|
initramfs caused that we are mounting almost all partitions, including
|
|
/boot (the actual mount target is /sysroot/boot) early in the boot
|
|
process. When upgrading with FIPS, the dracut fips module tries to mount
|
|
the device where the boot partition resides to check the integrity of
|
|
the kernel, however, it fails as the boot block device is already
|
|
mounted by us. This patch therefore introduces a static unit that
|
|
bind-mounts What=/sysroot/boot to Where=/boot, making the contents of
|
|
/boot available to the fips module. The bind-mounting service is
|
|
introduced only if the source system has /boot on a separate partition.
|
|
This is determined by checking whether anything shuld be mounted at
|
|
/boot according to fstab.
|
|
|
|
Jira-ref: RHEL-123886
|
|
---
|
|
.../initramfs/mount_units_generator/actor.py | 3 +-
|
|
.../files/bundled_units/boot.mount | 11 ++++
|
|
.../libraries/mount_unit_generator.py | 38 ++++++++++-
|
|
.../tests/test_mount_unit_generation.py | 63 ++++++++++++++++++-
|
|
4 files changed, 111 insertions(+), 4 deletions(-)
|
|
create mode 100644 repos/system_upgrade/common/actors/initramfs/mount_units_generator/files/bundled_units/boot.mount
|
|
|
|
diff --git a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/actor.py b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/actor.py
|
|
index dd667513..23c618b6 100644
|
|
--- a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/actor.py
|
|
+++ b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/actor.py
|
|
@@ -1,6 +1,6 @@
|
|
from leapp.actors import Actor
|
|
from leapp.libraries.actor import mount_unit_generator as mount_unit_generator_lib
|
|
-from leapp.models import LiveModeConfig, TargetUserSpaceInfo, UpgradeInitramfsTasks
|
|
+from leapp.models import LiveModeConfig, StorageInfo, TargetUserSpaceInfo, UpgradeInitramfsTasks
|
|
from leapp.tags import InterimPreparationPhaseTag, IPUWorkflowTag
|
|
|
|
|
|
@@ -15,6 +15,7 @@ class MountUnitGenerator(Actor):
|
|
consumes = (
|
|
LiveModeConfig,
|
|
TargetUserSpaceInfo,
|
|
+ StorageInfo,
|
|
)
|
|
produces = (
|
|
UpgradeInitramfsTasks,
|
|
diff --git a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/files/bundled_units/boot.mount b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/files/bundled_units/boot.mount
|
|
new file mode 100644
|
|
index 00000000..869c5e4c
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/files/bundled_units/boot.mount
|
|
@@ -0,0 +1,11 @@
|
|
+[Unit]
|
|
+DefaultDependencies=no
|
|
+Before=local-fs.target
|
|
+After=sysroot-boot.target
|
|
+Requires=sysroot-boot.target
|
|
+
|
|
+[Mount]
|
|
+What=/sysroot/boot
|
|
+Where=/boot
|
|
+Type=none
|
|
+Options=bind
|
|
diff --git a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/libraries/mount_unit_generator.py b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/libraries/mount_unit_generator.py
|
|
index 943bddd4..e3070986 100644
|
|
--- a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/libraries/mount_unit_generator.py
|
|
+++ b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/libraries/mount_unit_generator.py
|
|
@@ -5,7 +5,9 @@ import tempfile
|
|
from leapp.exceptions import StopActorExecutionError
|
|
from leapp.libraries.common import mounting
|
|
from leapp.libraries.stdlib import api, CalledProcessError, run
|
|
-from leapp.models import LiveModeConfig, TargetUserSpaceInfo, UpgradeInitramfsTasks
|
|
+from leapp.models import LiveModeConfig, StorageInfo, TargetUserSpaceInfo, UpgradeInitramfsTasks
|
|
+
|
|
+BIND_MOUNT_SYSROOT_BOOT_UNIT = 'boot.mount'
|
|
|
|
|
|
def run_systemd_fstab_generator(output_directory):
|
|
@@ -294,6 +296,39 @@ def request_units_inclusion_in_initramfs(files_to_include):
|
|
api.produce(tasks)
|
|
|
|
|
|
+def does_system_have_separate_boot_partition():
|
|
+ storage_info = next(api.consume(StorageInfo), None)
|
|
+ if not storage_info:
|
|
+ err_msg = 'Actor did not receive required information about system storage (StorageInfo)'
|
|
+ raise StopActorExecutionError(err_msg)
|
|
+
|
|
+ for fstab_entry in storage_info.fstab:
|
|
+ if fstab_entry.fs_file == '/boot':
|
|
+ return True
|
|
+
|
|
+ return False
|
|
+
|
|
+
|
|
+def inject_bundled_units(workspace):
|
|
+ """
|
|
+ Copy static units that are bundled within this actor into the workspace.
|
|
+ """
|
|
+ bundled_units_dir = api.get_actor_folder_path('bundled_units')
|
|
+ for unit in os.listdir(bundled_units_dir):
|
|
+ if unit == BIND_MOUNT_SYSROOT_BOOT_UNIT:
|
|
+ has_separate_boot = does_system_have_separate_boot_partition()
|
|
+ if not has_separate_boot:
|
|
+ # We perform bind-mounting because of dracut's fips module.
|
|
+ # When /boot is not a separate partition, we don't need to bind mount it --
|
|
+ # the fips module itself will create a symlink.
|
|
+ continue
|
|
+
|
|
+ unit_path = os.path.join(bundled_units_dir, unit)
|
|
+ unit_dst = os.path.join(workspace, unit)
|
|
+ api.current_logger().debug('Copying static unit bundled within leapp {} to {}'.format(unit, unit_dst))
|
|
+ shutil.copyfile(unit_path, unit_dst)
|
|
+
|
|
+
|
|
def setup_storage_initialization():
|
|
livemode_config = next(api.consume(LiveModeConfig), None)
|
|
if livemode_config and livemode_config.is_enabled:
|
|
@@ -306,6 +341,7 @@ def setup_storage_initialization():
|
|
run_systemd_fstab_generator(workspace_path)
|
|
remove_units_for_targets_that_are_already_mounted_by_dracut(workspace_path)
|
|
prefix_all_mount_units_with_sysroot(workspace_path)
|
|
+ inject_bundled_units(workspace_path)
|
|
fix_symlinks_in_targets(workspace_path)
|
|
mount_unit_files = copy_units_into_system_location(upgrade_container_ctx, workspace_path)
|
|
request_units_inclusion_in_initramfs(mount_unit_files)
|
|
diff --git a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/tests/test_mount_unit_generation.py b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/tests/test_mount_unit_generation.py
|
|
index 8849ada9..eb90a75d 100644
|
|
--- a/repos/system_upgrade/common/actors/initramfs/mount_units_generator/tests/test_mount_unit_generation.py
|
|
+++ b/repos/system_upgrade/common/actors/initramfs/mount_units_generator/tests/test_mount_unit_generation.py
|
|
@@ -5,9 +5,9 @@ import pytest
|
|
|
|
from leapp.exceptions import StopActorExecutionError
|
|
from leapp.libraries.actor import mount_unit_generator
|
|
-from leapp.libraries.common.testutils import logger_mocked
|
|
+from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked
|
|
from leapp.libraries.stdlib import api, CalledProcessError
|
|
-from leapp.models import TargetUserSpaceInfo, UpgradeInitramfsTasks
|
|
+from leapp.models import FstabEntry, StorageInfo, TargetUserSpaceInfo, UpgradeInitramfsTasks
|
|
|
|
|
|
def test_run_systemd_fstab_generator_successful_generation(monkeypatch):
|
|
@@ -267,3 +267,62 @@ def test_copy_units_mixed_content(monkeypatch):
|
|
]
|
|
assert sorted(files) == sorted(expected_files)
|
|
assert mount_unit_generator._delete_file.removal_called
|
|
+
|
|
+
|
|
+class CurrentActorMockedWithActorFolder(CurrentActorMocked):
|
|
+ def __init__(self, actor_folder_path, *args, **kwargs):
|
|
+ self.actor_folder_path = actor_folder_path
|
|
+ super().__init__(*args, **kwargs)
|
|
+
|
|
+ def get_actor_folder_path(self, subfolder):
|
|
+ return os.path.join(self.actor_folder_path, subfolder)
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize('has_separate_boot', (True, False))
|
|
+def test_injection_of_sysroot_boot_bindmount_unit(monkeypatch, has_separate_boot):
|
|
+ fstab_entries = [
|
|
+ FstabEntry(fs_spec='UUID=123', fs_file='/root', fs_vfstype='xfs',
|
|
+ fs_mntops='defaults', fs_freq='0', fs_passno='0')
|
|
+ ]
|
|
+
|
|
+ if has_separate_boot:
|
|
+ boot_fstab_entry = FstabEntry(fs_spec='UUID=123', fs_file='/root', fs_vfstype='xfs',
|
|
+ fs_mntops='defaults', fs_freq='0', fs_passno='0')
|
|
+ fstab_entries.append(boot_fstab_entry)
|
|
+
|
|
+ storage_info = StorageInfo(fstab=fstab_entries)
|
|
+
|
|
+ actor_mock = CurrentActorMockedWithActorFolder(actor_folder_path='/actor', msgs=[storage_info])
|
|
+ monkeypatch.setattr(api, 'current_actor', actor_mock)
|
|
+
|
|
+ workspace_path = '/workspace'
|
|
+ was_copyfile_for_sysroot_boot_called = False
|
|
+
|
|
+ def copyfile_mocked(source, dest, *args, **kwargs):
|
|
+ if not os.path.basename(source) == mount_unit_generator.BIND_MOUNT_SYSROOT_BOOT_UNIT:
|
|
+ return
|
|
+
|
|
+ assert has_separate_boot
|
|
+ assert dest == os.path.join(workspace_path, mount_unit_generator.BIND_MOUNT_SYSROOT_BOOT_UNIT)
|
|
+
|
|
+ nonlocal was_copyfile_for_sysroot_boot_called
|
|
+ was_copyfile_for_sysroot_boot_called = True
|
|
+
|
|
+ monkeypatch.setattr(shutil, 'copyfile', copyfile_mocked)
|
|
+
|
|
+ def listdir_mocked(path):
|
|
+ assert path == actor_mock.get_actor_folder_path('bundled_units')
|
|
+ return [
|
|
+ mount_unit_generator.BIND_MOUNT_SYSROOT_BOOT_UNIT,
|
|
+ 'other.mount'
|
|
+ ]
|
|
+
|
|
+ monkeypatch.setattr(os, 'listdir', listdir_mocked)
|
|
+ monkeypatch.setattr(mount_unit_generator,
|
|
+ 'does_system_have_separate_boot_partition',
|
|
+ lambda: has_separate_boot)
|
|
+
|
|
+ mount_unit_generator.inject_bundled_units(workspace_path)
|
|
+
|
|
+ if has_separate_boot:
|
|
+ assert was_copyfile_for_sysroot_boot_called
|
|
--
|
|
2.51.1
|
|
|