Repository: osbuild/osbuild
Pull request #2011 (2025-02-12 07:00:59)

stages/coreos.live-artifacts: update comments/names to reflect erofs related changes
This fixes what was skipped in https://github.com/osbuild/osbuild/pull/2002


Patch:
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
index 25a6ab62..240f6986 100644
--- a/.github/workflows/check.yml
+++ b/.github/workflows/check.yml
@@ -8,7 +8,7 @@ permissions:
 jobs:
   spelling_checker:
     name: "Spelling"
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     steps:
       - uses: actions/checkout@v4
       - uses: codespell-project/actions-codespell@master
@@ -18,7 +18,7 @@ jobs:
 
   python_code_linters:
       name: "Python Linters"
-      runs-on: ubuntu-latest
+      runs-on: ubuntu-24.04
       steps:
       - name: "Clone Repository"
         uses: actions/checkout@v4
@@ -31,7 +31,7 @@ jobs:
 
   shell_linters:
     name: "Shell Linters"
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
 
     steps:
     - name: "Clone Repository"
@@ -47,7 +47,7 @@ jobs:
 
   packit-config-lint:
     name: "📦 Packit config lint"
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     container:
       image: registry.fedoraproject.org/fedora:latest
     steps:
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
index 59dff7e6..0bd940a2 100644
--- a/.github/workflows/coverity.yml
+++ b/.github/workflows/coverity.yml
@@ -7,7 +7,7 @@ jobs:
   coverity:
     name: "Test Suite"
     if: github.repository == 'osbuild/osbuild'
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     defaults:
       run:
         working-directory: osbuild
diff --git a/.github/workflows/create-tag.yml b/.github/workflows/create-tag.yml
index 69b0537f..134f7569 100644
--- a/.github/workflows/create-tag.yml
+++ b/.github/workflows/create-tag.yml
@@ -8,7 +8,7 @@ on:
 
 jobs:
   tag-and-push:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
 
     steps:
       - name: Even or odd week
diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml
index 0eda9039..0082eb11 100644
--- a/.github/workflows/generate.yml
+++ b/.github/workflows/generate.yml
@@ -5,7 +5,7 @@ on: [pull_request, push]
 jobs:
   generate_documentation:
     name: "Documentation"
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     container:
       image: docker.io/library/python:3.7
     steps:
@@ -35,7 +35,7 @@ jobs:
 
   generate_test_data:
     name: "Test Data"
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     env:
       OSBUILD_MPP_CACHEDIR: "/var/tmp/osbuild-mpp-cache"
     steps:
diff --git a/.github/workflows/pr_best_practices.yml b/.github/workflows/pr_best_practices.yml
index d7a1b0c4..0bcf3bc5 100644
--- a/.github/workflows/pr_best_practices.yml
+++ b/.github/workflows/pr_best_practices.yml
@@ -9,7 +9,7 @@ on:
 
 jobs:
   pr-best-practices:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     steps:
       - name: PR best practice check
         uses: osbuild/pr-best-practices@main
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0ab01a68..89691ad2 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -7,7 +7,7 @@ on:
 
 jobs:
   release:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     steps:
       - name: Upstream release
         uses: osbuild/release-action@main
diff --git a/.github/workflows/stale-cleanup.yml b/.github/workflows/stale-cleanup.yml
index 56bbc780..0384c0d0 100644
--- a/.github/workflows/stale-cleanup.yml
+++ b/.github/workflows/stale-cleanup.yml
@@ -6,7 +6,7 @@ on:
 
 jobs:
   stale:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     permissions:
       issues: write
       pull-requests: write
diff --git a/.github/workflows/trigger-gitlab.yml b/.github/workflows/trigger-gitlab.yml
index 0ca8db2e..1557bde3 100644
--- a/.github/workflows/trigger-gitlab.yml
+++ b/.github/workflows/trigger-gitlab.yml
@@ -10,7 +10,7 @@ on:
 jobs:
   trigger-gitlab:
     if: ${{ github.event.workflow_run.conclusion == 'success' }}
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     env:
       IMAGEBUILDER_BOT_GITLAB_SSH_KEY: ${{ secrets.IMAGEBUILDER_BOT_GITLAB_SSH_KEY }}
     steps:
diff --git a/.github/workflows/update-images.yml b/.github/workflows/update-images.yml
index b70fe352..c25b919f 100644
--- a/.github/workflows/update-images.yml
+++ b/.github/workflows/update-images.yml
@@ -10,7 +10,7 @@
     
     jobs:
       update-and-push:
-        runs-on: ubuntu-latest
+        runs-on: ubuntu-24.04
         steps:
           - name: Apt update
             run: sudo apt update
diff --git a/stages/org.osbuild.coreos.live-artifacts.mono b/stages/org.osbuild.coreos.live-artifacts.mono
index f3f7178f..302b24d3 100755
--- a/stages/org.osbuild.coreos.live-artifacts.mono
+++ b/stages/org.osbuild.coreos.live-artifacts.mono
@@ -553,8 +553,8 @@ def mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client):
     Returns the bls entry kernel arguments for the ISO bootloader.
     """
     basearch = os.uname().machine
-    tmp_squashfs_dir = os.path.join(workdir, 'tmp-squashfs-dir')
-    os.mkdir(tmp_squashfs_dir)
+    tmp_rootfs_dir = os.path.join(workdir, 'tmp-rootfs-dir')
+    os.mkdir(tmp_rootfs_dir)
 
     # Since inputs are read-only and we want to modify it, we'll make a
     # copy of the metal.raw image and then mount that.
@@ -569,13 +569,13 @@ def mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client):
             # If mounted via the manifest, the stage begins with mounts already in place,
             # but osmet also performs a mount operation, leading to conflicts due to duplicate
             # filesystem UUIDs. Perform the manual mount only after the osmet stage
-            subprocess.check_call(['mount', '-o', 'rw', loopdev + 'p4', tmp_squashfs_dir])
-            cm.callback(subprocess.run, ['umount', '-R', tmp_squashfs_dir], check=True)
+            subprocess.check_call(['mount', '-o', 'rw', loopdev + 'p4', tmp_rootfs_dir])
+            cm.callback(subprocess.run, ['umount', '-R', tmp_rootfs_dir], check=True)
             subprocess.check_call(['mount', '-o', 'rw', loopdev + 'p3',
-                                   os.path.join(tmp_squashfs_dir, 'boot')])
+                                   os.path.join(tmp_rootfs_dir, 'boot')])
             if basearch in ['x86_64', 'aarch64']:
                 subprocess.check_call(['mount', '-o', 'rw', loopdev + 'p2',
-                                       os.path.join(tmp_squashfs_dir, 'boot/efi')])
+                                       os.path.join(tmp_rootfs_dir, 'boot/efi')])
 
             # Implements necessary CoreOS adjustments
             # including creating hardlinks in the /boot/ filesystem
@@ -584,43 +584,41 @@ def mkrootfs_metal(paths, workdir, img_metal, fstype, fsoptions, loop_client):
             # Make sure to create it, if it is not created yet.
 
             # Remove the sysroot=readonly flag, see https://github.com/ostreedev/ostree/issues/1921
-            subprocess.check_call(['sed', '-i', '/readonly=true/d', f'{tmp_squashfs_dir}/ostree/repo/config'])
+            subprocess.check_call(['sed', '-i', '/readonly=true/d', f'{tmp_rootfs_dir}/ostree/repo/config'])
 
             # And ensure that the kernel binary and hmac file is in the place that dracut
             # expects it to be; xref https://issues.redhat.com/browse/OCPBUGS-15843
 
-            kernel_binary = glob.glob(f"{tmp_squashfs_dir}/boot/ostree/*/vmlinuz*")[0]
-            kernel_hmac = glob.glob(f"{tmp_squashfs_dir}/boot/ostree/*/.*.hmac")[0]
+            kernel_binary = glob.glob(f"{tmp_rootfs_dir}/boot/ostree/*/vmlinuz*")[0]
+            kernel_hmac = glob.glob(f"{tmp_rootfs_dir}/boot/ostree/*/.*.hmac")[0]
             kernel_binary_basename = os.path.basename(kernel_binary)
             kernel_hmac_basename = os.path.basename(kernel_hmac)
 
             # Create hard links in the /boot directory
-            os.link(kernel_hmac, f"{tmp_squashfs_dir}/boot/{kernel_hmac_basename}")
-            os.link(kernel_binary, f"{tmp_squashfs_dir}/boot/{kernel_binary_basename}")
+            os.link(kernel_hmac, f"{tmp_rootfs_dir}/boot/{kernel_hmac_basename}")
+            os.link(kernel_binary, f"{tmp_rootfs_dir}/boot/{kernel_binary_basename}")
 
-            print(f"Kernel binary linked: {tmp_squashfs_dir}/boot/{kernel_binary_basename}")
-            print(f"Kernel HMAC linked: {tmp_squashfs_dir}/boot/{kernel_hmac_basename}")
-            # Generate root squashfs
+            print(f"Kernel binary linked: {tmp_rootfs_dir}/boot/{kernel_binary_basename}")
+            print(f"Kernel HMAC linked: {tmp_rootfs_dir}/boot/{kernel_hmac_basename}")
+            # Generate root squashfs/erofs
             print(f'Creating {fstype} with {fsoptions}')
 
-            # Note the filename must be exactly "root.squashfs" because the 20live
-            # dracut module makes assumptions about the length of the name in sysroot.mount
-            # this matches the set of flags we implicitly passed when doing this
-            # through libguestfs' mksquashfs command
+            # Note the filename must be exactly "root.[squash|ero]fs"
+            # because the 35coreos-live dracut module requires it.
             if fstype == "erofs":
                 subprocess.check_call(['mkfs.erofs',
                                        *fsoptions.split(' '),
                                        paths["initrd-rootfs/root.erofs"],
-                                       tmp_squashfs_dir])
+                                       tmp_rootfs_dir])
             else:
-                subprocess.check_call(['mksquashfs', tmp_squashfs_dir,
+                subprocess.check_call(['mksquashfs', tmp_rootfs_dir,
                                        paths["initrd-rootfs/root.squashfs"],
-                                       '-root-becomes', tmp_squashfs_dir,
+                                       '-root-becomes', tmp_rootfs_dir,
                                        '-wildcards', '-no-recovery',
                                        *fsoptions.split(' ')])
 
             # while it's mounted here, also get the kargs
-            blsentry = ensure_glob(os.path.join(tmp_squashfs_dir, 'boot/loader/entries/*.conf'), n=1)[0]
+            blsentry = ensure_glob(os.path.join(tmp_rootfs_dir, 'boot/loader/entries/*.conf'), n=1)[0]
             blsentry_kargs = []
             with open(blsentry, encoding='utf8') as f:
                 for line in f:
diff --git a/stages/org.osbuild.dracut b/stages/org.osbuild.dracut
index 05a56682..451ef42d 100755
--- a/stages/org.osbuild.dracut
+++ b/stages/org.osbuild.dracut
@@ -1,4 +1,8 @@
 #!/usr/bin/python3
+import contextlib
+import os
+import os.path
+import subprocess
 import sys
 
 import osbuild.api
@@ -10,6 +14,22 @@ def yesno(name: str, value: bool) -> str:
     return f"--{prefix}{name}"
 
 
+@contextlib.contextmanager
+def bind_mount_logger(tree: str) -> None:
+    logger_tree_path = os.path.join(tree, "usr/bin/logger")
+    if not os.path.exists(logger_tree_path):
+        # no logger -> nothing to do
+        yield
+        return
+    # make logger a "noop"
+    true_tree_path = os.path.join(tree, "usr/bin/true")
+    subprocess.run(["mount", "--rbind", true_tree_path, logger_tree_path], check=True)
+    try:
+        yield
+    finally:
+        subprocess.run(["umount", logger_tree_path], check=False)
+
+
 # pylint: disable=too-many-branches
 def main(tree, options):
     kernels = options["kernel"]
@@ -82,8 +102,15 @@ def main(tree, options):
         if initoverlayfs:
             initfs_bin = "/usr/bin/initoverlayfs-install"
 
-        with Chroot(tree) as chroot:
-            chroot.run([initfs_bin, "--no-hostonly", "--kver", kver] + opts, check=True)
+        # the chroot.run() call below will mount /dev with "devtmpfs", this
+        # is needed, see pr #1846 but it means we have likely have a
+        #   /dev/log -> /run/systemd/journal/dev-log
+        # symlink and dracut will try to log on it but end up writing
+        # 5k of "logger: socket /dev/log: No such file or directory"
+        # messages. See also issue #1976
+        with bind_mount_logger(tree):
+            with Chroot(tree) as chroot:
+                chroot.run([initfs_bin, "--no-hostonly", "--kver", kver] + opts, check=True)
 
     return 0
 


Test patch:
diff --git a/.github/workflows/test-on-centos.yml b/.github/workflows/test-on-centos.yml
index d78b55d1..0ae08679 100644
--- a/.github/workflows/test-on-centos.yml
+++ b/.github/workflows/test-on-centos.yml
@@ -15,7 +15,7 @@ jobs:
           - version: "10"
             pytest_exclude: 'not (TestBoot and boot) and not (test_write_read)'
     name: "Unittests on Centos Stream ${{ matrix.centos.version }}"
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     steps:
       - name: "Checkout"
         uses: actions/checkout@v4
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ec72ebc5..034a844c 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -13,7 +13,7 @@ env:
 jobs:
   test_suite:
     name: "Unittest"
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     strategy:
       fail-fast: false
       matrix:
@@ -59,7 +59,7 @@ jobs:
 
   v1_manifests:
     name: "Assembler test (legacy)"
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04
     steps:
       - name: "Clone Repository"
         uses: actions/checkout@v4
diff --git a/stages/test/test_dracut.py b/stages/test/test_dracut.py
index 99530589..4037b50a 100644
--- a/stages/test/test_dracut.py
+++ b/stages/test/test_dracut.py
@@ -29,3 +29,31 @@ def test_dracut_with_initoverlayfs(mocked_run, tmp_path, stage_module, with_init
     run_argv = args[0]
     assert run_argv[0] == "chroot"
     assert run_argv[2] == expected_argv2
+
+
+@patch("subprocess.run")
+def test_dracut_logger(mocked_run, tmp_path, stage_module):
+    fake_logger_path = tmp_path / "usr/bin/logger"
+    fake_logger_path.parent.mkdir(parents=True)
+    fake_logger_path.write_text("")
+    fake_true_path = tmp_path / "usr/bin/true"
+    fake_true_path.write_text("")
+
+    options = {
+        "kernel": [
+            "5.14.0-247.el9.x86_64",
+        ]
+    }
+    stage_module.main(tmp_path.as_posix(), options)
+    assert len(mocked_run.call_args_list) == 9
+    args, kwargs = mocked_run.call_args_list[0]  # bind-mount is the 1th call
+    assert kwargs.get("check") is True
+    run_argv = args[0]
+    assert run_argv == [
+        "mount", "--rbind",
+        fake_true_path.as_posix(), fake_logger_path.as_posix(),
+    ]
+    args, kwargs = mocked_run.call_args_list[8]  # umount is the 9th call
+    assert kwargs.get("check") is False
+    run_argv = args[0]
+    assert run_argv == ["umount", fake_logger_path.as_posix()]