From: Daan De Meyer Date: Sat, 2 Nov 2024 17:57:31 +0000 (+0100) Subject: Add sandbox verb X-Git-Tag: v25~188^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=72082a27cf4f7171fad98c84595df9f7abb97aa1;p=thirdparty%2Fmkosi.git Add sandbox verb In systemd, to run the integration tests, we need to run meson on the host which will itself invoke mkosi to run the integration tests. This means all the dependencies to run meson need to be installed on the host. This doesn't just mean meson needs to be installed, but also a compiler and various required build dependencies of systemd to allow building tools invoked by mkosi to build the image. To avoid having to install these dependencies on the host system, let's introduce a sandbox verb which runs a command in the mkosi sandbox that's also used by other verbs such as boot, qemu and shell. This then allows extra required tools to be installed in the tools tree via ToolsTreePackages= to allow running these commands without having to install them on the host system. --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index abda7e3d0..6970926d5 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -3750,6 +3750,31 @@ def build_image(context: Context) -> None: print_output_size(context.config.output_dir_or_cwd() / context.config.output_with_compression) +def run_sandbox(args: Args, config: Config) -> None: + cmdline = args.cmdline or [os.getenv("SHELL", "bash")] + options: list[PathString] = ["--same-dir"] + + # If we're not using tools tree certificates we don't have to do anything since the relaxed sandbox will + # already have /etc and /var from the host so we don't need to do anything extra. + if config.tools_tree_certificates: + options += finalize_crypto_mounts(config) + + run( + cmdline, + stdin=sys.stdin, + stdout=sys.stdout, + env=os.environ | {"MKOSI_IN_SANDBOX": "1"}, + log=False, + sandbox=config.sandbox( + binary=cmdline[0], + devices=True, + network=True, + relaxed=True, + options=options, + ), + ) + + def run_shell(args: Args, config: Config) -> None: opname = "acquire shell in" if args.verb == Verb.shell else "boot" if config.output_format in (OutputFormat.tar, OutputFormat.cpio): @@ -4597,7 +4622,7 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: logging.info(f"Output path {output} exists already. (Use --force to rebuild.)") return - if args.verb != Verb.build and not args.force and not output.exists(): + if args.verb not in (Verb.build, Verb.sandbox) and not args.force and not output.exists(): die( f"Image '{last.name()}' has not been built yet", hint="Make sure to build the image first with 'mkosi build' or use '--force'", @@ -4605,7 +4630,7 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: check_workspace_directory(last) - if last.incremental == Incremental.strict: + if args.verb != Verb.sandbox and last.incremental == Incremental.strict: if args.force > 1: die( "Cannot remove incremental caches when building with Incremental=strict", @@ -4636,7 +4661,7 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: # First, process all directory removals because otherwise if different images share directories # a later image build could end up deleting the output generated by an earlier image build. - if needs_build(args, last) or args.wipe_build_dir: + if args.verb != Verb.sandbox and (needs_build(args, last) or args.wipe_build_dir): for config in images: run_clean(args, config, resources=resources) @@ -4652,6 +4677,9 @@ def run_verb(args: Args, images: Sequence[Config], *, resources: Path) -> None: sync_repository_metadata(args, [tools], resources=resources, dst=Path(metadata_dir)) fork_and_wait(run_build, args, tools, resources=resources, metadata_dir=Path(metadata_dir)) + if args.verb == Verb.sandbox: + return run_sandbox(args, last) + for i, config in enumerate(images): with prepend_to_environ_path(config): check_tools(config, args.verb) diff --git a/mkosi/config.py b/mkosi/config.py index 7788b309e..644244c6e 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -77,6 +77,7 @@ class Verb(StrEnum): dependencies = enum.auto() completion = enum.auto() sysupdate = enum.auto() + sandbox = enum.auto() def supports_cmdline(self) -> bool: return self in ( @@ -91,6 +92,7 @@ class Verb(StrEnum): Verb.completion, Verb.documentation, Verb.sysupdate, + Verb.sandbox, ) def needs_build(self) -> bool: @@ -102,6 +104,7 @@ class Verb(StrEnum): Verb.serve, Verb.burn, Verb.sysupdate, + Verb.sandbox, ) def needs_config(self) -> bool: @@ -3013,7 +3016,13 @@ SETTINGS = ( dest="tools_tree", metavar="PATH", section="Build", - parse=config_make_path_parser(constants=("default",)), + parse=( + # If we're running inside of mkosi sandbox, the tools tree is already in place so don't pick it + # up again. + config_make_path_parser(constants=("default",)) + if not os.getenv("MKOSI_IN_SANDBOX") + else lambda value, old: None + ), paths=("mkosi.tools",), help="Look up programs to execute inside the given tree", nargs="?", @@ -3615,6 +3624,7 @@ def create_argument_parser(chdir: bool = True) -> argparse.ArgumentParser: mkosi [options…] {b}journalctl{e} [command line…] mkosi [options…] {b}coredumpctl{e} [command line…] mkosi [options…] {b}sysupdate{e} [command line…] + mkosi [options…] {b}sandbox{e} [command line…] mkosi [options…] {b}clean{e} mkosi [options…] {b}serve{e} mkosi [options…] {b}burn{e} [device] diff --git a/mkosi/resources/man/mkosi.1.md b/mkosi/resources/man/mkosi.1.md index 069787a5a..d89c6af31 100644 --- a/mkosi/resources/man/mkosi.1.md +++ b/mkosi/resources/man/mkosi.1.md @@ -28,6 +28,8 @@ mkosi — Build Bespoke OS Images `mkosi [options…] sysupdate [command line…]` +`mkosi [options…] sandbox [command line …]` + `mkosi [options…] clean` `mkosi [options…] serve` @@ -135,6 +137,13 @@ The following command line verbs are known: specified after the `sysupdate` verb are passed directly to `systemd-sysupdate` invocation. +`sandbox` +: Run arbitrary commands inside of the same sandbox used to execute + other verbs such as `boot`, `shell`, `qemu` and more. This means + `/usr` will be replaced by `/usr` from the tools tree if one is used + while everything else will remain in place. If no command is provided, + `$SHELL` will be executed or `bash` if `$SHELL` is not set. + `clean` : Remove build artifacts generated on a previous build. If combined with `-f`, also removes incremental build cache images. If `-f` is diff --git a/mkosi/resources/mkosi-tools/mkosi.conf b/mkosi/resources/mkosi-tools/mkosi.conf index 4a744c59e..3dda76643 100644 --- a/mkosi/resources/mkosi-tools/mkosi.conf +++ b/mkosi/resources/mkosi-tools/mkosi.conf @@ -10,6 +10,7 @@ BuildSources= [Content] Bootable=no +SELinuxRelabel=no Packages= acl attr @@ -38,5 +39,5 @@ Packages= tar util-linux xfsprogs + zsh zstd -SELinuxRelabel=no diff --git a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-arch.conf b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-arch.conf index f44c33a23..c7937c533 100644 --- a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-arch.conf +++ b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-arch.conf @@ -14,6 +14,7 @@ Packages= dpkg edk2-ovmf erofs-utils + fish git grub openssh diff --git a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-centos/mkosi.conf.d/20-epel-packages.conf b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-centos/mkosi.conf.d/20-epel-packages.conf index a13ecea7d..a36244371 100644 --- a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-centos/mkosi.conf.d/20-epel-packages.conf +++ b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-centos/mkosi.conf.d/20-epel-packages.conf @@ -9,6 +9,7 @@ Packages= archlinux-keyring debian-keyring distribution-gpg-keys + fish pacman sbsigntools ubu-keyring diff --git a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-debian-kali-ubuntu/mkosi.conf b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-debian-kali-ubuntu/mkosi.conf index bde44e73b..6874d84e7 100644 --- a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-debian-kali-ubuntu/mkosi.conf +++ b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-debian-kali-ubuntu/mkosi.conf @@ -20,6 +20,7 @@ Packages= createrepo-c debian-archive-keyring erofs-utils + fish git-core grub-common libarchive-tools diff --git a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-fedora/mkosi.conf b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-fedora/mkosi.conf index 25f37e66f..13137fae9 100644 --- a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-fedora/mkosi.conf +++ b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-fedora/mkosi.conf @@ -13,6 +13,7 @@ Packages= dnf5 dnf5-plugins erofs-utils + fish pacman qemu-system-aarch64-core qemu-system-ppc-core diff --git a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-opensuse.conf b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-opensuse.conf index 585f84a6f..7e6c54c71 100644 --- a/mkosi/resources/mkosi-tools/mkosi.conf.d/10-opensuse.conf +++ b/mkosi/resources/mkosi-tools/mkosi.conf.d/10-opensuse.conf @@ -13,6 +13,7 @@ Packages= dnf5 dnf5-plugins erofs-utils + fish git-core glibc-gconv-modules-extra grep