os.environ["PATH"] = ":".join(olds)
+def finalize_tools(args: MkosiArgs, presets: Sequence[MkosiConfig]) -> Sequence[MkosiConfig]:
+ new = []
+
+ for p in presets:
+ if not p.tools_tree or p.tools_tree.name != "default":
+ new.append(p)
+ continue
+
+ distribution = p.tools_tree_distribution or p.distribution.default_tools_tree_distribution()
+ release = p.tools_tree_release or distribution.default_release()
+
+ cmdline = [
+ "--directory", "",
+ "--distribution", str(distribution),
+ "--release", release,
+ "--repository-key-check", str(p.repository_key_check),
+ "--cache-only", str(p.cache_only),
+ "--output-dir", str(p.output_dir),
+ "--workspace-dir", str(p.workspace_dir),
+ *(["--cache-dir", str(p.cache_dir.parent)] if p.cache_dir else []),
+ "--incremental", str(p.incremental),
+ "--acl", str(p.acl),
+ "--format", "directory",
+ *flatten(["--package", package] for package in distribution.tools_tree_packages()),
+ "--output", f"{distribution}-tools",
+ "--bootable", "no",
+ "--manifest-format", "",
+ *(["--source-date-epoch", str(p.source_date_epoch)] if p.source_date_epoch is not None else []),
+ *(["-f"] * args.force),
+ "build",
+ ]
+
+ _, [config] = parse_config(cmdline)
+ config = dataclasses.replace(config, preset=f"{distribution}-tools")
+
+ if config not in new:
+ new.append(config)
+
+ new.append(dataclasses.replace(p, tools_tree=config.output_dir / config.output))
+
+ return new
+
+
def run_verb(args: MkosiArgs, presets: Sequence[MkosiConfig]) -> None:
if args.verb.needs_root() and os.getuid() != 0:
die(f"Must be root to run the {args.verb} command")
if args.verb == Verb.bump:
return bump_image_version()
+ presets = finalize_tools(args, presets)
+
if args.verb == Verb.summary:
text = ""
kernel_command_line_extra: list[str]
acl: bool
tools_tree: Optional[Path]
+ tools_tree_distribution: Optional[Distribution]
+ tools_tree_release: Optional[str]
# QEMU-specific options
qemu_gui: bool
dest="tools_tree",
metavar="PATH",
section="Host",
- parse=config_make_path_parser(required=False, resolve=False),
+ parse=config_make_path_parser(required=False),
paths=("mkosi.tools",),
help="Look up programs to execute inside the given tree",
),
+ MkosiConfigSetting(
+ dest="tools_tree_distribution",
+ metavar="DISTRIBUTION",
+ section="Host",
+ parse=config_make_enum_parser(Distribution),
+ help="Set the distribution to use for the default tools tree",
+ ),
+ MkosiConfigSetting(
+ dest="tools_tree_release",
+ metavar="RELEASE",
+ section="Host",
+ parse=config_parse_string,
+ help="Set the release to use for the default tools tree",
+ ),
)
MATCHES = (
Extra Kernel Command Line: {line_join_list(config.kernel_command_line_extra)}
Use ACLs: {config.acl}
Tools Tree: {config.tools_tree}
+ Tools Tree Distribution: {none_to_none(config.tools_tree_distribution)}
+ Tools Tree Release: {none_to_none(config.tools_tree_release)}
QEMU GUI: {yes_no(config.qemu_gui)}
QEMU CPU Cores: {config.qemu_smp}
def default_release(cls) -> str:
raise NotImplementedError()
+ @classmethod
+ def default_tools_tree_distribution(cls) -> "Distribution":
+ raise NotImplementedError()
+
+ @classmethod
+ def tools_tree_packages(cls) -> list[str]:
+ raise NotImplementedError()
+
class Distribution(StrEnum):
fedora = enum.auto()
def default_release(self) -> str:
return self.installer().default_release()
+ def default_tools_tree_distribution(self) -> "Distribution":
+ return self.installer().default_tools_tree_distribution()
+
+ def tools_tree_packages(self) -> list[str]:
+ return self.installer().tools_tree_packages()
+
def installer(self) -> Type[DistributionInstaller]:
try:
mod = importlib.import_module(f"mkosi.distributions.{self}")
from collections.abc import Sequence
from mkosi.architecture import Architecture
-from mkosi.distributions import DistributionInstaller, PackageType
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
from mkosi.installer.pacman import invoke_pacman, setup_pacman
from mkosi.log import die
from mkosi.state import MkosiState
def default_release(cls) -> str:
return "rolling"
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.arch
+
+ @classmethod
+ def tools_tree_packages(cls) -> list[str]:
+ return [
+ "archlinux-keyring",
+ "base",
+ "bash",
+ "btrfs-progs",
+ "bubblewrap",
+ "coreutils",
+ "cpio",
+ "debian-archive-keyring",
+ "dnf",
+ "dosfstools",
+ "e2fsprogs",
+ "edk2-ovmf",
+ "erofs-utils",
+ "mtools",
+ "openssh",
+ "openssl",
+ "pacman",
+ "python-cryptography",
+ "qemu-base",
+ "sbsigntools",
+ "socat",
+ "squashfs-tools",
+ "strace",
+ "swtpm",
+ "systemd-ukify",
+ "systemd",
+ "tar",
+ "xfsprogs",
+ "xz",
+ "zstd",
+ ]
+
@classmethod
def setup(cls, state: MkosiState) -> None:
setup_pacman(state)
from mkosi.architecture import Architecture
from mkosi.config import MkosiConfig
-from mkosi.distributions import DistributionInstaller, PackageType
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
from mkosi.log import complete_step, die
from mkosi.state import MkosiState
def default_release(cls) -> str:
return "9"
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.fedora
+
+ @classmethod
+ def tools_tree_packages(cls) -> list[str]:
+ return [
+ "bash",
+ "bubblewrap",
+ "coreutils",
+ "cpio",
+ "dnf",
+ "dosfstools",
+ "e2fsprogs",
+ "edk2-ovmf",
+ "mtools",
+ "openssh-clients",
+ "openssl",
+ "python3-cryptography",
+ "qemu-kvm-core",
+ "pesign",
+ "socat",
+ "squashfs-tools",
+ "strace",
+ "swtpm",
+ "systemd-container",
+ "systemd-udev",
+ "systemd",
+ "tar",
+ "xfsprogs",
+ "xz",
+ "zstd",
+ ]
+
@classmethod
def setup(cls, state: MkosiState) -> None:
release = int(state.config.release)
from mkosi.architecture import Architecture
from mkosi.archive import extract_tar
-from mkosi.distributions import DistributionInstaller, PackageType
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
from mkosi.installer.apt import invoke_apt, setup_apt
from mkosi.log import die
from mkosi.run import run
def default_release(cls) -> str:
return "testing"
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.debian
+
+ @classmethod
+ def tools_tree_packages(cls) -> list[str]:
+ return [
+ "apt",
+ "bash",
+ "btrfs-progs",
+ "bubblewrap",
+ "coreutils",
+ "cpio",
+ "debian-archive-keyring",
+ "dnf",
+ "dosfstools",
+ "e2fsprogs",
+ "erofs-utils",
+ "libtss2-dev",
+ "mtools",
+ "openssh-client",
+ "openssl",
+ "ovmf",
+ "pacman-package-manager",
+ "python3-cryptography",
+ "python3-pefile",
+ "qemu-system",
+ "sbsigntool",
+ "socat",
+ "squashfs-tools",
+ "strace",
+ "swtpm",
+ "systemd-boot",
+ "systemd-container",
+ "systemd",
+ "tar",
+ "xfsprogs",
+ "xz-utils",
+ "zstd",
+ "zypper",
+ ]
+
@staticmethod
def repositories(state: MkosiState, local: bool = True) -> list[str]:
assert state.config.mirror
from collections.abc import Sequence
from mkosi.architecture import Architecture
-from mkosi.distributions import DistributionInstaller, PackageType
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
from mkosi.log import die
from mkosi.state import MkosiState
def default_release(cls) -> str:
return "39"
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.fedora
+
+ @classmethod
+ def tools_tree_packages(cls) -> list[str]:
+ return [
+ "apt",
+ "archlinux-keyring",
+ "bash",
+ "btrfs-progs",
+ "bubblewrap",
+ "coreutils",
+ "cpio",
+ "debian-keyring",
+ "dnf5",
+ "dosfstools",
+ "e2fsprogs",
+ "edk2-ovmf",
+ "erofs-utils",
+ "mtools",
+ "openssh-clients",
+ "openssl",
+ "pacman",
+ "python3-cryptography",
+ "qemu-kvm-core",
+ "sbsigntools",
+ "socat",
+ "squashfs-tools",
+ "strace",
+ "swtpm",
+ "systemd-container",
+ "systemd-udev",
+ "systemd-ukify",
+ "systemd",
+ "tar",
+ "xfsprogs",
+ "xz",
+ "zstd",
+ "zypper",
+ ]
+
@classmethod
def setup(cls, state: MkosiState) -> None:
# See: https://fedoraproject.org/security/
from mkosi.architecture import Architecture
from mkosi.archive import extract_tar
-from mkosi.distributions import DistributionInstaller, PackageType
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
from mkosi.log import ARG_DEBUG, complete_step, die
from mkosi.run import apivfs_cmd, bwrap, chroot_cmd, run
from mkosi.state import MkosiState
def default_release(cls) -> str:
return "17.1"
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.gentoo
+
@classmethod
def setup(cls, state: MkosiState) -> None:
pass
from collections.abc import Sequence
from mkosi.architecture import Architecture
-from mkosi.distributions import DistributionInstaller, PackageType
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
from mkosi.log import die
from mkosi.state import MkosiState
def default_release(cls) -> str:
return "cauldron"
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.mageia
+
@classmethod
def setup(cls, state: MkosiState) -> None:
release = state.config.release.strip("'")
from collections.abc import Sequence
from mkosi.architecture import Architecture
-from mkosi.distributions import DistributionInstaller, PackageType
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
from mkosi.log import die
from mkosi.state import MkosiState
def default_release(cls) -> str:
return "cooker"
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.openmandriva
+
@classmethod
def setup(cls, state: MkosiState) -> None:
release = state.config.release.strip("'")
from collections.abc import Sequence
from mkosi.architecture import Architecture
-from mkosi.distributions import DistributionInstaller, PackageType
+from mkosi.distributions import Distribution, DistributionInstaller, PackageType
from mkosi.installer.dnf import Repo, invoke_dnf, setup_dnf
from mkosi.installer.zypper import invoke_zypper, setup_zypper
from mkosi.log import die
def default_release(cls) -> str:
return "tumbleweed"
+ @classmethod
+ def default_tools_tree_distribution(cls) -> Distribution:
+ return Distribution.opensuse
+
+ @classmethod
+ def tools_tree_packages(cls) -> list[str]:
+ return [
+ "bash",
+ "btrfs-progs",
+ "bubblewrap",
+ "coreutils",
+ "cpio",
+ "dnf",
+ "dosfstools",
+ "e2fsprogs",
+ "erofs-utils",
+ "grep",
+ "mtools",
+ "openssh-clients",
+ "openssl",
+ "ovmf",
+ "qemu-headless",
+ "sbsigntools",
+ "socat",
+ "squashfs",
+ "strace",
+ "swtpm",
+ "systemd-boot",
+ "systemd-container",
+ "systemd-experimental",
+ "systemd",
+ "tar",
+ "xfsprogs",
+ "xz",
+ "zstd",
+ "zypper",
+ ]
+
@classmethod
def setup(cls, state: MkosiState) -> None:
release = state.config.release
`--extra-search-path=` are ignored when looking up binaries in the
given tools tree.
+: If set to `default`, mkosi will automatically add an extra tools tree
+ preset and use it as the tools tree.
+
+`ToolsTreeDistribution=`, `--tools-tree-distribution=`
+
+: Set the distribution to use for the default tools tree. By default,
+ the same distribution as the image that's being built is used, except
+ for CentOS and Ubuntu images, in which case Fedora and Debian are used
+ respectively.
+
+`ToolsTreeRelease=`, `--tools-tree-release=`
+
+: Set the distribution release to use for the default tools tree. By
+ default, the hardcoded default release in mkosi for the distribution
+ is used.
+
## Supported distributions
Images may be created containing installations of the following