]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
Add RuntimeHome= option
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 6 Sep 2024 15:19:06 +0000 (17:19 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Mon, 9 Sep 2024 16:15:23 +0000 (18:15 +0200)
mkosi/__init__.py
mkosi/config.py
mkosi/qemu.py
mkosi/resources/man/mkosi.md
mkosi/run.py
mkosi/util.py
mkosi/vmspawn.py
tests/test_json.py

index 11c19ac9fe61b9c18465f8f9b93e6b19956519b8..34edee726c55925ed7adc87a15c6dc680f05eb4c 100644 (file)
@@ -115,6 +115,7 @@ from mkosi.tree import copy_tree, make_tree, move_tree, rmtree
 from mkosi.types import PathString
 from mkosi.user import INVOKING_USER
 from mkosi.util import (
+    current_home_dir,
     flatten,
     flock,
     flock_or_die,
@@ -3392,6 +3393,10 @@ def run_shell(args: Args, config: Config) -> None:
             uidmap = "rootidmap" if tree.source.stat().st_uid != 0 else "noidmap"
             cmdline += ["--bind", f"{tree.source}:{target}:norbind,{uidmap}"]
 
+        if config.runtime_home and (path := current_home_dir()):
+            uidmap = "rootidmap" if path.stat().st_uid != 0 else "noidmap"
+            cmdline += ["--bind", f"{path}:/root:norbind,{uidmap}"]
+
         if config.runtime_scratch == ConfigFeature.enabled or (
             config.runtime_scratch == ConfigFeature.auto and
             config.output_format == OutputFormat.disk
index 3fa839ed0875bb78b3f6ec9d2c587ab5bfb6062f..c597033451652231f7f68869ca803c7eb474250c 100644 (file)
@@ -1563,6 +1563,7 @@ class Config:
     runtime_scratch: ConfigFeature
     runtime_network: Network
     runtime_build_sources: bool
+    runtime_home: bool
     unit_properties: list[str]
     ssh_key: Optional[Path]
     ssh_certificate: Optional[Path]
@@ -3005,6 +3006,13 @@ SETTINGS = (
         parse=config_parse_boolean,
         help="Mount build sources and build directory in /work when booting the image",
     ),
+    ConfigSetting(
+        dest="runtime_home",
+        metavar="BOOL",
+        section="Host",
+        parse=config_parse_boolean,
+        help="Mount current home directory to /root when booting the image",
+    ),
     ConfigSetting(
         dest="unit_properties",
         long="--unit-property",
@@ -4307,6 +4315,7 @@ def summary(config: Config) -> str:
                     Runtime Scratch: {config.runtime_scratch}
                     Runtime Network: {config.runtime_network}
               Runtime Build Sources: {config.runtime_build_sources}
+  Runtime Home or Working Directory: {yes_no(config.runtime_home)}
                     Unit Properties: {line_join_list(config.unit_properties)}
                     SSH Signing Key: {none_to_none(config.ssh_key)}
                     SSH Certificate: {none_to_none(config.ssh_certificate)}
index a6d84d931ae38ae727f57c1d31a5e3a61d8eaae4..78ce4da42f0e2fda8350e2e4cd8359c8410ca3ff 100644 (file)
@@ -45,7 +45,7 @@ from mkosi.run import SD_LISTEN_FDS_START, AsyncioThread, find_binary, fork_and_
 from mkosi.tree import copy_tree, rmtree
 from mkosi.types import PathString
 from mkosi.user import INVOKING_USER, become_root_in_subuid_range, become_root_in_subuid_range_cmd
-from mkosi.util import StrEnum, flock, flock_or_die, groupby, round_up, try_or
+from mkosi.util import StrEnum, current_home_dir, flock, flock_or_die, groupby, round_up, try_or
 from mkosi.versioncomp import GenericVersion
 
 QEMU_KVM_DEVICE_VERSION = GenericVersion("9.0")
@@ -900,7 +900,12 @@ def run_qemu(args: Args, config: Config) -> None:
 
     # A shared memory backend might increase ram usage so only add one if actually necessary for virtiofsd.
     shm = []
-    if config.runtime_trees or config.runtime_build_sources or config.output_format == OutputFormat.directory:
+    if (
+        config.runtime_trees or
+        config.runtime_build_sources or
+        config.runtime_home or
+        config.output_format == OutputFormat.directory
+    ):
         shm = ["-object", f"memory-backend-memfd,id=mem,size={config.qemu_mem // 1024**2}M,share=on"]
 
     machine = f"type={config.architecture.default_qemu_machine()}"
@@ -1109,6 +1114,16 @@ def run_qemu(args: Args, config: Config) -> None:
                 tag=tree.target.name if tree.target else tree.source.name,
             )
 
+        if config.runtime_home and (p := current_home_dir()):
+            sock = stack.enter_context(start_virtiofsd(config, p))
+            add_virtiofs_mount(
+                sock,
+                Path("/root"),
+                cmdline,
+                credentials,
+                tag="user-home",
+            )
+
         if want_scratch(config) or config.output_format in (OutputFormat.disk, OutputFormat.esp):
             cmdline += ["-device", "virtio-scsi-pci,id=mkosi"]
 
index 7e80cc589b7a440aac9df16c4f9737f4f4efe63e..c78db5268fe136a941a86d5f00ffd5ed3e90c6a5 100644 (file)
@@ -1635,6 +1635,10 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`,
     they were mounted to when running the build script when using `mkosi
     boot` or `mkosi qemu`.
 
+`RuntimeHome=`, `--runtime-home=`
+:   Mount the current home directory from which mkosi is running to
+    `/root` when using `mkosi boot` or `mkosi qemu`.
+
 `UnitProperties=`, `--unit-property=`
 :   Configure systemd unit properties to add to the systemd scopes
     allocated when using `mkosi boot` or `mkosi qemu`. These are passed
index fd660670f99ab776f599c8735541e08e6611c15e..73d15e21110b7240ad2b621f4fbe1f82eae92ac4 100644 (file)
@@ -26,7 +26,7 @@ import mkosi.sandbox
 from mkosi.log import ARG_DEBUG, ARG_DEBUG_SHELL, die
 from mkosi.sandbox import joinpath, umask
 from mkosi.types import _FILE, CompletedProcess, PathString, Popen
-from mkosi.util import flatten, one_zero
+from mkosi.util import current_home_dir, flatten, one_zero
 
 SD_LISTEN_FDS_START = 3
 
@@ -503,23 +503,14 @@ def sandbox_cmd(
             if Path(d).exists():
                 cmdline += ["--bind", d, d]
 
+        path = current_home_dir()
+        if not path and Path.cwd() not in (Path("/"), Path("/home")):
+            path = Path.cwd()
+
         # Either add the home directory we're running from or the current working directory if we're not running from
         # inside a home directory.
-        if Path.cwd() == Path("/"):
-            d = ""
-        if Path.cwd().is_relative_to("/root"):
-            d = "/root"
-        elif Path.cwd() == Path("/home"):
-            d = "/home"
-        elif Path.cwd().is_relative_to("/home"):
-            # `Path.parents` only supports slices and negative indexing from Python 3.10 onwards.
-            # TODO: Remove list() when we depend on Python 3.10 or newer.
-            d = os.fspath(list(Path.cwd().parents)[-2])
-        else:
-            d = os.fspath(Path.cwd())
-
-        if d and not any(Path(d).is_relative_to(dir) for dir in (*dirs, "/usr", "/nix", "/tmp")):
-            cmdline += ["--bind", d, d]
+        if path and not any(path.is_relative_to(dir) for dir in (*dirs, "/usr", "/nix", "/tmp")):
+            cmdline += ["--bind", path, path]
     else:
         cmdline += ["--dir", "/var/tmp", "--unshare-ipc"]
 
@@ -531,9 +522,7 @@ def sandbox_cmd(
         if network and Path("/etc/resolv.conf").exists():
             cmdline += ["--ro-bind", "/etc/resolv.conf", "/etc/resolv.conf"]
 
-    path = "/usr/bin:/usr/sbin" if tools != Path("/") else os.environ["PATH"]
-
-    cmdline += ["--setenv", "PATH", f"/scripts:{path}"]
+    cmdline += ["--setenv", "PATH", f"/scripts:{'/usr/bin:/usr/sbin' if tools != Path('/') else os.environ['PATH']}"]
 
     if scripts:
         cmdline += ["--ro-bind", scripts, "/scripts"]
index e55b54d3bc594f4aa03b19a8b8f0b8899362c06c..1afabdb0afac346294d226d2920730520cc16a07 100644 (file)
@@ -233,3 +233,18 @@ def groupby(seq: Sequence[T], key: Callable[[T], S]) -> list[tuple[S, list[T]]]:
         grouped[k].append(i)
 
     return [(key, group) for key, group in grouped.items()]
+
+
+def current_home_dir() -> Optional[Path]:
+    if Path.cwd() in (Path("/"), Path("/home")):
+        return None
+
+    if Path.cwd().is_relative_to("/root"):
+        return Path("/root")
+
+    if Path.cwd().is_relative_to("/home"):
+        # `Path.parents` only supports slices and negative indexing from Python 3.10 onwards.
+        # TODO: Remove list() when we depend on Python 3.10 or newer.
+        return list(Path.cwd().parents)[-3]
+
+    return None
index 26de1f6aaffe0ab07ace35fec1ff9741a2b7907a..78bbaec4d543d451be43bc61d260bf4138483408 100644 (file)
@@ -21,6 +21,7 @@ from mkosi.qemu import (
 )
 from mkosi.run import run
 from mkosi.types import PathString
+from mkosi.util import current_home_dir
 
 
 def run_vmspawn(args: Args, config: Config) -> None:
@@ -84,6 +85,9 @@ def run_vmspawn(args: Args, config: Config) -> None:
             target = Path("/root/src") / (tree.target or "")
             cmdline += ["--bind", f"{tree.source}:{target}"]
 
+        if config.runtime_home and (p := current_home_dir()):
+            cmdline += ["--bind", f"{p}:/root"]
+
         if kernel:
             cmdline += ["--linux", kernel]
 
index f4236608d120fdc26a8226d78ee109b69661c1ec..72c36a74a21d2e117585243e822c0a91bbf76042 100644 (file)
@@ -268,6 +268,7 @@ def test_config() -> None:
             ],
             "RootShell": "/bin/tcsh",
             "RuntimeBuildSources": true,
+            "RuntimeHome": true,
             "RuntimeNetwork": "interface",
             "RuntimeScratch": "enabled",
             "RuntimeSize": 8589934592,
@@ -473,6 +474,7 @@ def test_config() -> None:
         root_password=("test1234", False),
         root_shell="/bin/tcsh",
         runtime_build_sources=True,
+        runtime_home=True,
         runtime_network=Network.interface,
         runtime_scratch=ConfigFeature.enabled,
         runtime_size=8589934592,