]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
mkosi-initrd: Rewrite kernel-install plugin in python and support UKIs 2164/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Tue, 12 Dec 2023 11:26:45 +0000 (12:26 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 13 Dec 2023 08:51:11 +0000 (09:51 +0100)
There's really no point for the kernel-install plugin to be in bash,
so let's rewrite it in python. While we're at it, let's also support
running as a UKI generator.

.github/workflows/ci.yml
kernel-install/50-mkosi-initrd.install [deleted file]
kernel-install/50-mkosi.install [new file with mode: 0644]
mkosi/resources/mkosi-initrd/mkosi.conf.d/20-stub.conf [new file with mode: 0644]

index 02ec88ed3adcf808d0a5e241209691e0081609ba..9c5f8fb5e2e50eb4eadb237e7fd00cfe85332b84 100644 (file)
@@ -28,7 +28,7 @@ jobs:
     - name: Run ruff
       run: |
         ruff --version
-        ruff mkosi/ tests/
+        ruff mkosi/ tests/ kernel-install/50-mkosi.install
 
     - name: Check that tabs are not used in code
       run: sh -c '! git grep -P "\\t" "*.py"'
@@ -36,12 +36,12 @@ jobs:
     - name: Type Checking (mypy)
       run: |
         python3 -m mypy --version
-        python3 -m mypy mkosi/ tests/
+        python3 -m mypy mkosi/ tests/ kernel-install/50-mkosi.install
 
     - name: Type Checking (pyright)
       run: |
         pyright --version
-        pyright mkosi/ tests/
+        pyright mkosi/ tests/ kernel-install/50-mkosi.install
 
     - name: Unit Tests
       run: |
diff --git a/kernel-install/50-mkosi-initrd.install b/kernel-install/50-mkosi-initrd.install
deleted file mode 100644 (file)
index 1b3e6c0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/bash
-# SPDX-License-Identifier: LGPL-2.1-or-later
-set -e
-export LANG=C.UTF-8
-
-COMMAND="$1"
-KERNEL_VERSION="$2"
-BOOT_DIR_ABS="$3"
-KERNEL_IMAGE="$4"
-INITRD_OPTIONS_SHIFT=4
-
-# Skip this plugin if we're using a different generator.
-[ "${KERNEL_INSTALL_INITRD_GENERATOR}" != "mkosi-initrd" ] && exit 0
-
-: "${KERNEL_INSTALL_STAGING_AREA:?}"
-
-case "$COMMAND" in
-    add)
-        # If the initrd was provided on the kernel command line, we shouldn't generate our own.
-        [ "$#" -gt "$INITRD_OPTIONS_SHIFT" ] && exit 0
-
-        (
-            [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && set -x
-
-            mkosi --directory "" \
-                  $([ -e /usr/lib/mkosi-initrd ] && echo --include=/usr/lib/mkosi-initrd) \
-                  $([ -e /etc/mkosi-initrd ] && echo --include=/etc/mkosi-initrd) \
-                  --image-version="$KERNEL_VERSION" \
-                  --environment="KERNEL_VERSION=$KERNEL_VERSION" \
-                  --workspace-dir=/var/tmp \
-                  --cache-dir=/var/cache \
-                  --output-dir="$KERNEL_INSTALL_STAGING_AREA" \
-                  --extra-tree="/usr/lib/modules/${KERNEL_VERSION}:/usr/lib/modules/${KERNEL_VERSION}" \
-                  --extra-tree="/usr/lib/firmware:/usr/lib/firmware" \
-                  --kernel-modules-exclude=".*" \
-                  --kernel-modules-include-host=yes
-
-            rm "${KERNEL_INSTALL_STAGING_AREA}/initrd"
-            mv -v "${KERNEL_INSTALL_STAGING_AREA}"/initrd_*.cpio.zst "${KERNEL_INSTALL_STAGING_AREA}/initrd"
-        )
-        ;;
-
-    remove)
-        ;;
-esac
-
-exit 0
diff --git a/kernel-install/50-mkosi.install b/kernel-install/50-mkosi.install
new file mode 100644 (file)
index 0000000..c8f1e91
--- /dev/null
@@ -0,0 +1,134 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: LGPL-2.1+
+
+import argparse
+import logging
+import os
+import shutil
+from pathlib import Path
+from typing import NamedTuple, Optional
+
+from mkosi.config import OutputFormat, __version__
+from mkosi.log import die, log_setup
+from mkosi.run import run, uncaught_exception_handler
+from mkosi.types import PathString
+
+
+class Context(NamedTuple):
+    command: str
+    kernel_version: str
+    entry_dir: Path
+    kernel_image: Path
+    initrds: list[Path]
+    staging_area: Path
+    layout: str
+    image_type: str
+    initrd_generator: Optional[str]
+    uki_generator: Optional[str]
+    verbose: bool
+
+
+def we_are_wanted(context: Context) -> bool:
+    return context.uki_generator == "mkosi" or context.initrd_generator in ("mkosi", "mkosi-initrd")
+
+
+def mandatory_variable(name: str) -> str:
+    try:
+        return os.environ[name]
+    except KeyError:
+        die(f"${name} must be set in the environment")
+
+
+@uncaught_exception_handler()
+def main() -> None:
+    log_setup()
+
+    p = argparse.ArgumentParser(
+        description='kernel-install plugin to build initrds or Unified Kernel Images using mkosi',
+        allow_abbrev=False,
+        usage='50-mkosi.install COMMAND KERNEL_VERSION ENTRY_DIR KERNEL_IMAGE INITRD…',
+    )
+
+    p.add_argument("command",
+                   metavar="COMMAND",
+                   help="The action to perform. Only 'add' is supported.")
+    p.add_argument("kernel_version",
+                   metavar="KERNEL_VERSION",
+                   help="Kernel version string")
+    p.add_argument("entry_dir",
+                   metavar="ENTRY_DIR",
+                   type=Path,
+                   help="Type#1 entry directory (ignored)")
+    p.add_argument("kernel_image",
+                   metavar="KERNEL_IMAGE",
+                   type=Path,
+                   help="Kernel image")
+    p.add_argument("initrds",
+                   metavar="INITRD…",
+                   type=Path,
+                   nargs="*",
+                   help="Initrd files")
+    p.add_argument("--version",
+                   action="version",
+                   version=f"mkosi {__version__}")
+
+    context = Context(
+        **vars(p.parse_args()),
+        staging_area=Path(mandatory_variable("KERNEL_INSTALL_STAGING_AREA")),
+        layout=mandatory_variable("KERNEL_INSTALL_LAYOUT"),
+        image_type=mandatory_variable("KERNEL_INSTALL_IMAGE_TYPE"),
+        initrd_generator=os.getenv("KERNEL_INSTALL_INITRD_GENERATOR"),
+        uki_generator=os.getenv("KERNEL_INSTALL_UKI_GENERATOR"),
+        verbose=int(os.getenv("KERNEL_INSTALL_VERBOSE", 0)) > 0,
+    )
+
+    if context.command != "add" or not we_are_wanted(context):
+        return
+
+    # If kernel-install was passed a UKI, there's no need to build anything ourselves.
+    if context.image_type == "uki":
+        return
+
+    # If the initrd was provided on the kernel command line, we shouldn't generate our own.
+    if context.layout != "uki" and context.initrds:
+        return
+
+    format = OutputFormat.uki if context.layout == "uki" else OutputFormat.cpio
+    output = "initrd" if format == OutputFormat.cpio else "uki"
+
+    cmdline: list[PathString] = [
+        "mkosi",
+        "--directory", "",
+        "--format", str(format),
+        "--output", output,
+        "--workspace-dir=/var/tmp",
+        "--cache-dir=/var/cache",
+        "--output-dir", context.staging_area,
+        "--extra-tree", f"/usr/lib/modules/{context.kernel_version}:/usr/lib/modules/{context.kernel_version}",
+        "--extra-tree=/usr/lib/firmware:/usr/lib/firmware",
+        "--kernel-modules-exclude=.*",
+        "--kernel-modules-include-host=yes",
+    ]
+
+    if context.verbose:
+        cmdline += ["--debug"]
+
+    for d in ("/usr/lib/mkosi-initrd", "/etc/mkosi-initrd"):
+        if Path(d).exists():
+            cmdline += ["--include", d]
+
+    logging.info(f"Building {output}")
+
+    run(cmdline)
+
+    (context.staging_area / output).unlink()
+
+    if format == OutputFormat.cpio:
+        shutil.move(next(context.staging_area.glob("initrd*.cpio*")), context.staging_area / "initrd")
+    else:
+        (context.staging_area / f"{output}.vmlinuz").unlink()
+        (context.staging_area / f"{output}.initrd").unlink()
+
+
+if __name__ == '__main__':
+    main()
diff --git a/mkosi/resources/mkosi-initrd/mkosi.conf.d/20-stub.conf b/mkosi/resources/mkosi-initrd/mkosi.conf.d/20-stub.conf
new file mode 100644 (file)
index 0000000..42b6b04
--- /dev/null
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+[Match]
+Format=uki
+Distribution=!arch
+
+[Content]
+Packages=systemd-boot