File 0001-Add-support-for-mkosi-initrd.patch of Package transactional-update

From 41bff04021ab096cd052541bd24556ff6101e74f Mon Sep 17 00:00:00 2001
From: Antonio Alvarez Feijoo <antonio.feijoo@suse.com>
Date: Thu, 22 Aug 2024 13:41:11 +0200
Subject: [PATCH] Add support for mkosi-initrd

`mkosi` provides the `mkosi-initrd` script [1], which allows to generate initrds
locally on the system. Although it is not equivalent in features to `dracut`,
it's a valid alternative with its own benefits in some use cases:
- Clear ownership of bugs: no 3rd party binary (e.g. dracut) deciding what is
installed from each package or even modifying them.
- Any change on a package configured to be included would automatically apply to
the initrd (if the package triggers initrd rebuild).
- It attempts to shift the maintenance effort from the initrd generator to the
responsible package.

To choose which initrd generator will be used, use a new `INITRD_GENERATOR`
option in `/etc/sysconfig/bootloader`. If not defined, the default will still be
dracut.

[1] https://github.com/systemd/mkosi/commit/99ca14cffb13309a0e6865b2724cc199916c753b
---
 sbin/transactional-update.in | 86 ++++++++++++++++++++++++++++++++----
 1 file changed, 77 insertions(+), 9 deletions(-)

diff --git a/sbin/transactional-update.in b/sbin/transactional-update.in
index afb6e9f..ff56746 100755
--- a/sbin/transactional-update.in
+++ b/sbin/transactional-update.in
@@ -75,6 +75,7 @@ SYSTEM_MANIFEST_FILE="@libdir@/sysimage/tu/system.manifest"
 ZYPPER_AUTO_IMPORT_KEYS=0
 ETC_OVERLAY_PATTERN='^[^[:space:]]\+[[:space:]]\+\/etc[[:space:]]\+overlay[[:space:]]\+\([^[:space:]]*,\|\)workdir=\/sysroot\/var\/lib\/overlay\/work-etc[,[:space:]]'
 NON_ROOTFS_WHITELIST=("/var/lib/YaST2/cookies" "/var/lib/rpm" "/var/lib/systemd/migrated" "/var/run/zypp.pid")
+INITRD_GENERATOR=""
 DRACUT_OPTS=""
 TUKIT_OPTS=""
 
@@ -267,6 +268,59 @@ save_state_file() {
     fi
 }
 
+find_initrd_generator() {
+    INITRD_GENERATOR="$(. /etc/sysconfig/bootloader 2>/dev/null && echo -n "$INITRD_GENERATOR")"
+
+    # dracut is the default initrd generator
+    if [[ -z "$INITRD_GENERATOR" ]]; then
+        INITRD_GENERATOR="dracut"
+    elif [[ "$INITRD_GENERATOR" = "mkosi" ]]; then
+        INITRD_GENERATOR="mkosi-initrd"
+    fi
+
+    [ "$INITRD_GENERATOR" = "dracut" ] || [ "$INITRD_GENERATOR" = "mkosi-initrd" ] || {
+        log_error "ERROR: the initrd generator \"$INITRD_GENERATOR\" configured in /etc/sysconfig/bootloader is not supported."
+        return 1
+    }
+
+    return 0
+}
+
+mkosi_initrd_call() {
+    local tmp_file
+
+    tmp_file=$(mktemp -p /etc -t mkosi-initrd-callXXXXXXXX)
+    if [[ ! -f "$tmp_file" ]]; then
+        log_error "ERROR: failed to create temporary file for the mkosi-initrd call"
+        return
+    fi
+
+    # FIXME: mkosi-initrd does not provide anything like --regenerate-all yet
+    # FIXME: mkosi-initrd fails to cp files directly to /boot
+    cat >> "$tmp_file"<<EOF
+mkosi_initrd_staging_dir="$(mktemp -p /var/tmp/ -d -t mkosi-initrd-stagingXXXXXXXX)"
+if [ ! -d "\$mkosi_initrd_staging_dir" ]; then
+    mkdir -p "\$mkosi_initrd_staging_dir" || exit 1
+fi
+for d in /lib/modules/*; do
+    [ -d "\$d" ] || continue
+    mkosi_initrd_kver=\${d##*/}
+    if mkosi-initrd --kernel-version "\$mkosi_initrd_kver" -O "\$mkosi_initrd_staging_dir" -o "initrd-\$mkosi_initrd_kver"; then
+        if chmod 600 "\$mkosi_initrd_staging_dir/initrd-\$mkosi_initrd_kver"; then
+            # The staging dir will contain: initrd-<kver> -> initrd-<kver>.cpio.zst
+            cp --reflink=auto "\$mkosi_initrd_staging_dir/initrd-\$mkosi_initrd_kver" "/boot/initrd-\$mkosi_initrd_kver"
+            rm -f "\$mkosi_initrd_staging_dir/initrd-\$mkosi_initrd_kver"*
+        else
+            exit 1
+        fi
+    fi
+done
+exit
+EOF
+
+    echo -n "$tmp_file"
+}
+
 rebuild_kdump_initrd() {
     if tukit -q call "$1" systemctl is-enabled --quiet kdump.service; then
 	tukit ${TUKIT_OPTS} call "$1" /sbin/mkdumprd |& tee -a ${LOGFILE} 1>&${origstdout}
@@ -1637,15 +1691,29 @@ if [ -n "${ZYPPER_ARG}" -o ${REWRITE_GRUB_CFG} -eq 1 \
     fi
 
     if [ ${REWRITE_INITRD} -eq 1 ]; then
-	log_info "Creating new initrd"
-	tukit ${TUKIT_OPTS} call "${SNAPSHOT_ID}" dracut ${DRACUT_OPTS} --force --regenerate-all |& tee -a ${LOGFILE} 1>&${origstdout}
-	if [ $? -ne 0 ]; then
-	    log_error "ERROR: initrd creation failed!"
-	    EXITCODE=1
-	else
-	    REBUILD_KDUMP_INITRD=1
-	fi
-	set_reboot_level "kexec"
+        if find_initrd_generator; then
+            log_info "Creating new initrd using $INITRD_GENERATOR"
+            case "$INITRD_GENERATOR" in
+                "dracut")
+                    tukit ${TUKIT_OPTS} call "${SNAPSHOT_ID}" dracut ${DRACUT_OPTS} --force --regenerate-all |& tee -a ${LOGFILE} 1>&${origstdout}
+                    [ $? -eq 0 ] || EXITCODE=1
+                    ;;
+                "mkosi-initrd")
+                    tmp_bash_file="$(mkosi_initrd_call)"
+                    tukit ${TUKIT_OPTS} call "${SNAPSHOT_ID}" bash "$tmp_bash_file" |& tee -a ${LOGFILE} 1>&${origstdout}
+                    [ $? -eq 0 ] || EXITCODE=1
+                    rm -f "$tmp_bash_file"
+                    ;;
+            esac
+            if [ $EXITCODE -ne 0 ]; then
+                log_error "ERROR: initrd creation failed!"
+            else
+                REBUILD_KDUMP_INITRD=1
+            fi
+        else
+            EXITCODE=1
+        fi
+        set_reboot_level "kexec"
     fi
 
     if [ ${REBUILD_KDUMP_INITRD} -eq 1 ]; then
-- 
2.35.3

openSUSE Build Service is sponsored by