]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
sysupdate: Make it work in combination with a tools tree
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 21 Nov 2024 20:51:43 +0000 (21:51 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 22 Nov 2024 09:17:10 +0000 (10:17 +0100)
- We have to make sure systemd-sysupdate looks at the os-release
from the host even when using a tools tree.
- systemd-sysupdate can't detect the root block device when running
with a tools tree. Let's abuse /run/systemd/volatile-root to shortcut
the detection logic instead.

mkosi/sysupdate.py

index 5bc737f7725c4ccc1d491da7598c4b5b75458647..f23c2edfa6e9e95c497addd8481ef42e48af44bc 100644 (file)
@@ -1,7 +1,9 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 import os
+import subprocess
 import sys
+import tempfile
 from pathlib import Path
 
 from mkosi.config import Args, ArtifactOutput, Config
@@ -24,29 +26,50 @@ def run_sysupdate(args: Args, config: Config) -> None:
     if not (sysupdate := config.find_binary("systemd-sysupdate", "/usr/lib/systemd/systemd-sysupdate")):
         die("Could not find systemd-sysupdate")
 
-    cmd: list[PathString] = [
-        sysupdate,
-        "--definitions", config.sysupdate_dir,
-        "--transfer-source", config.output_dir_or_cwd(),
-        *args.cmdline,
-    ]  # fmt: skip
-
-    run(
-        cmd,
-        stdin=sys.stdin,
-        stdout=sys.stdout,
-        env=os.environ | config.environment,
-        log=False,
-        sandbox=config.sandbox(
-            binary=sysupdate,
-            devices=True,
-            network=True,
-            relaxed=True,
-            setup=["run0"] if os.getuid() != 0 else [],
-            options=[
-                *(["--bind", "/boot", "/boot"] if Path("/boot").exists() else []),
-                *(["--bind", "/efi", "/efi"] if Path("/efi").exists() else []),
-                "--same-dir",
-            ],
-        ),
-    )
+    with tempfile.TemporaryDirectory() as tmp:
+        if config.tools() != Path("/"):
+            # We explicitly run this without a sandbox, because / has to be the original root mountpoint for
+            # bootctl --print-root-device to work properly.
+            blockdev = run(["bootctl", "--print-root-device"], stdout=subprocess.PIPE).stdout.strip()
+
+            # If /run/systemd/volatile-root exists, systemd skips its root block device detection logic and
+            # uses whatever block device /run/systemd/volatile-root points to instead. Let's make use of that
+            # when using a tools tree as in that case the block device detection logic doesn't work properly.
+            (Path(tmp) / "volatile-root").symlink_to(blockdev)
+
+        cmd: list[PathString] = [
+            sysupdate,
+            "--definitions", config.sysupdate_dir,
+            "--transfer-source", config.output_dir_or_cwd(),
+            *args.cmdline,
+        ]  # fmt: skip
+
+        run(
+            cmd,
+            stdin=sys.stdin,
+            stdout=sys.stdout,
+            env=os.environ | config.environment,
+            log=False,
+            sandbox=config.sandbox(
+                binary=sysupdate,
+                devices=True,
+                network=True,
+                relaxed=True,
+                setup=["run0"] if os.getuid() != 0 else [],
+                options=[
+                    *(["--bind", "/boot", "/boot"] if Path("/boot").exists() else []),
+                    *(["--bind", "/efi", "/efi"] if Path("/efi").exists() else []),
+                    *(
+                        [
+                            # Make sure systemd-sysupdate parses os-release from the host and not the tools
+                            # tree.
+                            "--bind", "/usr/lib/os-release", "/usr/lib/os-release",
+                            "--bind", tmp, "/run/systemd",
+                        ]
+                        if config.tools() != Path("/")
+                        else []
+                    ),
+                    "--same-dir",
+                ],
+            ),
+        )  # fmt: skip