]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Simplify kernel image and initrd handling
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 9 Feb 2023 11:53:32 +0000 (12:53 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 13 Feb 2023 08:59:25 +0000 (09:59 +0100)
- Let's stop writing files in /etc in favor of passing the
information via other ways
- Let's stop defaulting to "bls" layout which is intended
for type 1 images, we only use UKIs so we don't need the
"bls" layout
- kernel-install now defaults to the "other" layout, which
means it won't create the entry directory in /boot anymore.
We update the initrd find logic to take this into account
- Remove --machine-id as it was only really there for testing
the config parsing which we now deal with by not storing the
machine ID at all

NEWS.md
mkosi.md
mkosi/__init__.py
mkosi/backend.py
mkosi/distributions/__init__.py
mkosi/distributions/debian.py
mkosi/distributions/opensuse.py
mkosi/run.py
tests/test_backend.py
tests/test_parse_load_args.py

diff --git a/NEWS.md b/NEWS.md
index 2b3679a83d11e0b73120b1a89a8ea62315ffda50..af3724cc8e0de6d64b4ad3586b46ea1dfed5c701 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -45,6 +45,7 @@
   `--source-file-transfer-final` might be reimplemented in the future using virtiofsd.
 - Dropped `--include-dir` option. Usage can be replaced by using `--incremental` and reading includes from
   the cached build image tree.
+- Removed `--machine-id` in favor of shipping images without a machine ID at all.
 
 ## v14
 
index fc64bd40fe17436a0a3602b7b25d881d9052d4f6..b6004a93e72a83d719e57aab048271d94eabdf8e 100644 (file)
--- a/mkosi.md
+++ b/mkosi.md
@@ -543,12 +543,6 @@ a boolean argument: either "1", "yes", or "true" to enable, or "0",
   in building or further container import stages.  This option strips
   SELinux context attributes from the resulting tar archive.
 
-`MachineID=`, `--machine-id`
-
-: Set the machine's ID to the specified value. If unused, a random ID will
-be used while building the image and the final image will be shipped without
-a machine ID.
-
 ### [Content] Section
 
 `BasePackages=`, `--base-packages`
index 0172036166cda9e64fbb8dbd1ef239aee9d7c2ea..dc90e9fd7d9b7d47a61852818891f14958318362 100644 (file)
@@ -249,27 +249,6 @@ def prepare_tree_root(state: MkosiState) -> None:
             btrfs_subvol_create(state.root)
 
 
-def prepare_tree(state: MkosiState, cached: bool) -> None:
-    if cached:
-        # Reuse machine-id from cached image.
-        state.machine_id = uuid.UUID(state.root.joinpath("etc/machine-id").read_text().strip()).hex
-        # Always update kernel command line.
-        if not state.do_run_build_script and state.config.bootable:
-            state.root.joinpath("etc/kernel/cmdline").write_text(" ".join(state.config.kernel_command_line) + "\n")
-        return
-
-    with complete_step("Setting up basic OS tree…"):
-        state.root.mkdir(mode=0o755, exist_ok=True)
-        # We need an initialized machine ID for the build & boot logic to work
-        state.root.joinpath("etc").mkdir(mode=0o755, exist_ok=True)
-        state.root.joinpath("etc/machine-id").write_text(f"{state.machine_id}\n")
-
-        state.root.joinpath("etc/kernel").mkdir(mode=0o755, exist_ok=True)
-        state.root.joinpath("etc/kernel/cmdline").write_text(" ".join(state.config.kernel_command_line) + "\n")
-        state.root.joinpath("etc/kernel/entry-token").write_text(f"{state.machine_id}\n")
-        state.root.joinpath("etc/kernel/install.conf").write_text("layout=bls\n")
-
-
 def clean_paths(
         root: Path,
         globs: Sequence[str],
@@ -429,18 +408,9 @@ def reset_machine_id(state: MkosiState) -> None:
         return
 
     with complete_step("Resetting machine ID"):
-        if not state.config.machine_id:
-            machine_id = state.root / "etc/machine-id"
-            machine_id.unlink(missing_ok=True)
-            machine_id.write_text("uninitialized\n")
-
-        dbus_machine_id = state.root / "var/lib/dbus/machine-id"
-        try:
-            dbus_machine_id.unlink()
-        except FileNotFoundError:
-            pass
-        else:
-            dbus_machine_id.symlink_to("../../../etc/machine-id")
+        machine_id = state.root / "etc/machine-id"
+        machine_id.unlink(missing_ok=True)
+        machine_id.write_text("uninitialized\n")
 
 
 def reset_random_seed(root: Path) -> None:
@@ -610,7 +580,7 @@ def install_boot_loader(state: MkosiState) -> None:
         return
 
     with complete_step("Installing boot loader…"):
-        run(["bootctl", "install", "--root", state.root], env={"SYSTEMD_ESP_PATH": "/boot", **os.environ})
+        run(["bootctl", "install", "--root", state.root], env={"SYSTEMD_ESP_PATH": "/boot"})
 
 
 def install_extra_trees(state: MkosiState) -> None:
@@ -750,15 +720,6 @@ def gen_kernel_images(state: MkosiState) -> Iterator[tuple[str, Path]]:
         yield kver.name, kimg
 
 
-def initrd_path(state: MkosiState, kver: str) -> Path:
-    # initrd file is versioned in Debian Bookworm
-    initrd = state.root / boot_directory(state, kver) / f"initrd.img-{kver}"
-    if not initrd.exists():
-        initrd = state.root / boot_directory(state, kver) / "initrd"
-
-    return initrd
-
-
 def install_unified_kernel(state: MkosiState, roothash: Optional[str]) -> None:
     # Iterates through all kernel versions included in the image and generates a combined
     # kernel+initrd+cmdline+osrelease EFI file from it and places it in the /EFI/Linux directory of the ESP.
@@ -815,6 +776,9 @@ def install_unified_kernel(state: MkosiState, roothash: Optional[str]) -> None:
             else:
                 boot_options = ""
 
+            if state.config.kernel_command_line:
+                boot_options = f"{boot_options} {' '.join(state.config.kernel_command_line)}"
+
             if roothash:
                 boot_options = f"{boot_options} {roothash}"
 
@@ -842,7 +806,11 @@ def install_unified_kernel(state: MkosiState, roothash: Optional[str]) -> None:
                         "--pcr-banks", "sha1,sha256"
                     ]
 
-            cmd += [state.root / kimg, initrd_path(state, kver)]
+            initrd = state.root.joinpath(state.installer.initrd_path(kver))
+            if not initrd.exists():
+                die(f"Initrd not found at {initrd}")
+
+            cmd += [state.root / kimg, initrd]
 
             run(cmd)
 
@@ -1341,7 +1309,6 @@ class ArgumentParserMkosi(argparse.ArgumentParser):
         "BuildPackages": "--build-package",
         "PostInstallationScript": "--postinst-script",
         "TarStripSELinuxContext": "--tar-strip-selinux-context",
-        "MachineID": "--machine-id",
         "SignExpectedPCR": "--sign-expected-pcr",
         "RepositoryDirectories": "--repository-directory",
         "Credentials": "--credential",
@@ -1742,10 +1709,6 @@ def create_parser() -> ArgumentParserMkosi:
         default=True,
         help=argparse.SUPPRESS,
     )
-    group.add_argument(
-        "--machine-id",
-        help="Defines a fixed machine ID for all our build-time runs.",
-    )
 
     group.add_argument("--password", help="Set the root password")
     group.add_argument(
@@ -2711,12 +2674,6 @@ def load_args(args: argparse.Namespace) -> MkosiConfig:
     if args.netdev and is_centos_variant(args.distribution) and "epel" not in args.repositories:
         die("--netdev is only supported on EPEL centOS variants")
 
-    if args.machine_id is not None:
-        try:
-            uuid.UUID(hex=args.machine_id)
-        except ValueError:
-            die(f"Sorry, {args.machine_id} is not a valid machine ID.")
-
     # If we are building a sysext we don't want to add base packages to the
     # extension image, as they will already be in the base image.
     if args.base_image is not None:
@@ -2927,8 +2884,6 @@ def print_summary(config: MkosiConfig) -> None:
     if config.secure_boot_certificate:
         print("   SecureBoot Cert.:", config.secure_boot_certificate)
 
-    print("                Machine ID:", none_to_no(config.machine_id))
-
     print("\nCONTENT:")
 
     print("                  Packages:", line_join_list(config.packages))
@@ -3108,10 +3063,6 @@ def configure_netdev(state: MkosiState, cached: bool) -> None:
         run(["systemctl", "--root", state.root, "enable", "systemd-networkd"])
 
 
-def boot_directory(state: MkosiState, kver: str) -> Path:
-    return Path("boot") / state.machine_id / kver
-
-
 def run_kernel_install(state: MkosiState, cached: bool) -> None:
     if not state.config.bootable or state.do_run_build_script:
         return
@@ -3243,7 +3194,6 @@ def build_image(state: MkosiState, *, manifest: Optional[Manifest] = None) -> No
         return
 
     with mount_image(state, cached):
-        prepare_tree(state, cached)
         install_skeleton_trees(state, cached)
         install_distribution(state, cached)
         configure_locale(state.root, cached)
@@ -3375,7 +3325,7 @@ def remove_artifacts(state: MkosiState, for_cache: bool = False) -> None:
 
     with complete_step(f"Removing artifacts from {what}…"):
         unlink_try_hard(state.root)
-        unlink_try_hard(state.var_tmp())
+        unlink_try_hard(state.var_tmp)
 
 
 def build_stuff(uid: int, gid: int, config: MkosiConfig) -> None:
@@ -3390,7 +3340,6 @@ def build_stuff(uid: int, gid: int, config: MkosiConfig) -> None:
         workspace=workspace_dir,
         cache=cache,
         do_run_build_script=False,
-        machine_id=config.machine_id or uuid.uuid4().hex,
         for_cache=False,
     )
 
index 50f0a4a4cc304d873394d7de8b90ca33fd65f6e1..46bb2d571110cea48776c13ca80f7c6c4fa899b3 100644 (file)
@@ -321,7 +321,6 @@ class MkosiConfig:
     debug: list[str]
     auto_bump: bool
     workspace_dir: Optional[Path]
-    machine_id: Optional[str]
 
     # QEMU-specific options
     qemu_headless: bool
@@ -396,7 +395,6 @@ class MkosiState:
     workspace: Path
     cache: Path
     do_run_build_script: bool
-    machine_id: str
     for_cache: bool
     environment: dict[str, str] = dataclasses.field(init=False)
     installer: DistributionInstaller = dataclasses.field(init=False)
@@ -418,20 +416,21 @@ class MkosiState:
             die("No installer for this distribution.")
         self.installer = instance
 
+        self.root.mkdir(exist_ok=True, mode=0o755)
+        self.var_tmp.mkdir(exist_ok=True)
+        self.staging.mkdir(exist_ok=True)
+
     @property
     def root(self) -> Path:
         return self.workspace / "root"
 
+    @property
     def var_tmp(self) -> Path:
-        p = self.workspace / "var-tmp"
-        p.mkdir(exist_ok=True)
-        return p
+        return self.workspace / "var-tmp"
 
     @property
     def staging(self) -> Path:
-        p = self.workspace / "staging"
-        p.mkdir(exist_ok=True)
-        return p
+        return self.workspace / "staging"
 
 
 def should_compress_output(config: Union[argparse.Namespace, MkosiConfig]) -> Union[bool, str]:
@@ -449,10 +448,6 @@ def should_compress_output(config: Union[argparse.Namespace, MkosiConfig]) -> Un
     return False if c is None else c
 
 
-def workspace(root: Path) -> Path:
-    return root.parent
-
-
 def format_rlimit(rlimit: int) -> str:
     limits = resource.getrlimit(rlimit)
     soft = "infinity" if limits[0] == resource.RLIM_INFINITY else str(limits[0])
index 3d2e5db365163f6fd6ad18de1ea499bd56aaf7a8..af42b4e0db35d81c83c27b7a030f66a831f56290 100644 (file)
@@ -15,8 +15,12 @@ class DistributionInstaller:
         raise NotImplementedError
 
     @staticmethod
-    def kernel_image(name: str, architecture: str) -> Path:
-        return Path("lib/modules") / name / "vmlinuz"
+    def kernel_image(kver: str, architecture: str) -> Path:
+        return Path("lib/modules") / kver / "vmlinuz"
+
+    @staticmethod
+    def initrd_path(kver: str) -> Path:
+        return Path("boot") / f"initramfs-{kver}.img"
 
     @classmethod
     def cache_path(cls) -> list[str]:
index dba18f87050ace73faa6ef7a1d4b641e6686e315..60cc8b98debacc08a75f950f0bb5c704eb152f41 100644 (file)
@@ -45,6 +45,10 @@ class DebianInstaller(DistributionInstaller):
     def kernel_image(name: str, architecture: str) -> Path:
         return Path(f"boot/vmlinuz-{name}")
 
+    @staticmethod
+    def initrd_path(kver: str) -> Path:
+        return Path("boot") / f"initrd.img-{kver}"
+
     @classmethod
     def install(cls, state: "MkosiState") -> None:
         # Either the image builds or it fails and we restart, we don't need safety fsyncs when bootstrapping
index f4540376dd11c84789c2979b0084c0e108b2ec66..dc341eaa672c4f1bb656b17fbe357dac519878bf 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: LGPL-2.1+
 
 import shutil
+from pathlib import Path
 
 from mkosi.backend import MkosiState, add_packages, patch_file, sort_packages
 from mkosi.distributions import DistributionInstaller
@@ -22,6 +23,10 @@ class OpensuseInstaller(DistributionInstaller):
     def install(cls, state: "MkosiState") -> None:
         return install_opensuse(state)
 
+    @staticmethod
+    def initrd_path(kver: str) -> Path:
+        return Path("boot") / f"initrd-{kver}"
+
 
 @complete_step("Installing openSUSE…")
 def install_opensuse(state: MkosiState) -> None:
index 61475c500d784370110174c5275e402856fd7c71..d36821910b5573489a6d98d2f1f4250a70c24bda 100644 (file)
@@ -260,7 +260,7 @@ def run_with_apivfs(
         "--proc", state.root / "proc",
         "--dev", state.root / "dev",
         "--ro-bind", "/sys", state.root / "sys",
-        "--bind", state.var_tmp(), state.root / "var/tmp",
+        "--bind", state.var_tmp, state.root / "var/tmp",
         *bwrap_params,
         "sh", "-c",
     ]
@@ -297,7 +297,7 @@ def run_workspace_command(
         "--dev", "/dev",
         "--proc", "/proc",
         "--ro-bind", "/sys", "/sys",
-        "--bind", state.var_tmp(), "/var/tmp",
+        "--bind", state.var_tmp, "/var/tmp",
         *bwrap_params,
     ]
 
index afbcc46e769c7d994940e6ca5e3d2264ad0ccf00..9a8034b0886b96502a55233ff5fefaa4af530d1d 100644 (file)
@@ -13,7 +13,6 @@ from mkosi.backend import (
     safe_tar_extract,
     set_umask,
     strip_suffixes,
-    workspace,
 )
 from mkosi.log import MkosiException
 
@@ -37,13 +36,6 @@ def test_set_umask() -> None:
     assert tmp3 == 0o777
 
 
-def test_workspace() -> None:
-    assert workspace(Path("/home/folder/mkosi/mkosi")) == Path("/home/folder/mkosi")
-    assert workspace(Path("/home/../home/folder/mkosi/mkosi")) == Path("/home/../home/folder/mkosi")
-    assert workspace(Path("/")) == Path("/")
-    assert workspace(Path()) == Path()
-
-
 def test_safe_tar_extract(tmp_path: Path) -> None:
     name = secrets.token_hex()
     testfile = tmp_path / name
index a28f9915f5f8f38e7f3a5ddc8d654f8259fe7636..220762b9d1705e0ad6f8b84a0141df0b2457c3fc 100644 (file)
@@ -2,7 +2,6 @@
 
 import argparse
 import tempfile
-import uuid
 from contextlib import contextmanager
 from os import chdir, getcwd
 from pathlib import Path
@@ -60,28 +59,6 @@ def test_os_distribution() -> None:
             config.write_text(f"[Distribution]\nDistribution={dist}")
             assert parse([]).distribution == dist
 
-def test_machine_id() -> None:
-    id = uuid.uuid4().hex
-    load_args = parse(["--machine-id", id])
-
-    assert load_args.machine_id == id
-
-    with pytest.raises(MkosiException):
-        parse(["--machine-id", "notValidKey"])
-    with pytest.raises(tuple((argparse.ArgumentError, SystemExit))):
-        parse(["--machine-id"])
-
-    with cd_temp_dir():
-        config = Path("mkosi.conf")
-        config.write_text(f"[Output]\nMachineID={id}")
-        load_args = parse([])
-        assert load_args.machine_id == id
-
-    with cd_temp_dir():
-        config = Path("mkosi.conf")
-        config.write_text("[Output]\nMachineID=")
-        with pytest.raises(MkosiException):
-            parse([])
 
 def test_hostname() -> None:
     assert parse(["--hostname", "name"]).hostname == "name"