universal = enum.auto()
# Passed down to subimages, can be overridden
inherit = enum.auto()
+ # Can only be configured in main image, not passed down anywhere.
+ main = enum.auto()
@dataclasses.dataclass(frozen=True)
section="Config",
parse=config_parse_minimum_version,
help="Specify the minimum required mkosi version",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="configure_scripts",
section="Config",
parse=config_make_list_parser(delimiter=" "),
help="Environment variables to pass to subimages",
+ scope=SettingScope.main,
),
# Distribution section
ConfigSetting(
choices=Distribution.choices(),
default_factory=config_default_tools_tree_distribution,
help="Set the distribution to use for the default tools tree",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_release",
default_factory_depends=("tools_tree_distribution",),
default_factory=lambda ns: d.default_release() if (d := ns.tools_tree_distribution) else None,
help="Set the release to use for the default tools tree",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_profiles",
choices=ToolsTreeProfile.values(),
default=[str(s) for s in ToolsTreeProfile.default()],
help="Which profiles to enable for the default tools tree",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_mirror",
lambda ns: ns.mirror if ns.mirror and ns.distribution == ns.tools_tree_distribution else None
),
help="Set the mirror to use for the default tools tree",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_repositories",
section="Build",
parse=config_make_list_parser(delimiter=","),
help="Repositories to use for the default tools tree",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_sandbox_trees",
section="Build",
parse=config_make_list_parser(delimiter=",", parse=make_tree_parser(required=True)),
help="Sandbox trees for the default tools tree",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_packages",
section="Build",
parse=config_make_list_parser(delimiter=","),
help="Add additional packages to the default tools tree",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_package_directories",
section="Build",
parse=config_make_list_parser(delimiter=",", parse=make_path_parser()),
help="Specify a directory containing extra tools tree packages",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_sync_scripts",
path_suffixes=("tools.sync",),
recursive_path_suffixes=("tools.sync.d/*",),
help="Sync script to run before building the tools tree",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_prepare_scripts",
path_suffixes=("tools.prepare", "tools.prepare.chroot"),
recursive_path_suffixes=("tools.prepare.d/*",),
help="Prepare script to run inside the tools tree before it is cached",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tools_tree_certificates",
section="Build",
parse=config_parse_boolean,
help="Whether mkosi can store information about previous builds",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="build_sources",
help="Set the proxy client key",
scope=SettingScope.universal,
),
- # Host section
+ # Runtime section
ConfigSetting(
dest="nspawn_settings",
name="NSpawnSettings",
parse=config_make_path_parser(),
path_suffixes=("nspawn",),
help="Add in .nspawn settings file",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="ephemeral",
"If specified, the container/VM is run with a temporary snapshot of the output "
"image that is removed immediately when the container/VM terminates"
),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="credentials",
parse=config_make_dict_parser(delimiter=" ", parse=parse_key_value, allow_paths=True, unescape=True),
help="Pass a systemd credential to a systemd-nspawn container or a virtual machine",
path_suffixes=("credentials",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="kernel_command_line_extra",
section="Runtime",
parse=config_make_list_parser(delimiter=" "),
help="Append extra entries to the kernel command line when booting the image",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="runtime_trees",
section="Runtime",
parse=config_make_list_parser(delimiter=",", parse=make_tree_parser(absolute=False)),
help="Additional mounts to add when booting the image",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="runtime_size",
section="Runtime",
parse=config_parse_bytes,
help="Grow disk images to the specified size before booting them",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="runtime_scratch",
section="Runtime",
parse=config_parse_feature,
help="Mount extra scratch space to /var/tmp",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="runtime_network",
choices=Network.choices(),
help="Set networking backend to use when booting the image",
default=Network.user,
+ scope=SettingScope.main,
),
ConfigSetting(
dest="runtime_build_sources",
section="Runtime",
parse=config_parse_boolean,
help="Mount build sources and build directory in /work when booting the image",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="runtime_home",
section="Runtime",
parse=config_parse_boolean,
help="Mount current home directory to /root when booting the image",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="unit_properties",
section="Runtime",
parse=config_make_list_parser(delimiter=" ", unescape=True),
help="Set properties on the scopes spawned by systemd-nspawn or systemd-run",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="ssh_key",
parse=config_make_path_parser(secret=True),
path_suffixes=("key",),
help="Private key for use with mkosi ssh in PEM format",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="ssh_certificate",
parse=config_make_path_parser(),
path_suffixes=("crt",),
help="Certificate for use with mkosi ssh in X509 format",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="vmm",
parse=config_make_enum_parser(Vmm),
default=Vmm.qemu,
help="Set the virtual machine monitor to use for mkosi vm",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="machine",
metavar="NAME",
section="Runtime",
help="Set the machine name to use when booting the image",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="forward_journal",
section="Runtime",
parse=config_make_path_parser(required=False),
help="Set the path used to store forwarded machine journals",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="sysupdate_dir",
parse=config_make_path_parser(),
path_suffixes=("sysupdate",),
help="Directory containing systemd-sysupdate transfer definitions",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="console",
parse=config_make_enum_parser(ConsoleMode),
help="Configure the virtual machine console mode to use",
default=ConsoleMode.native,
+ scope=SettingScope.main,
),
ConfigSetting(
dest="cpus",
help="Configure number of CPUs in virtual machine",
compat_longs=("--qemu-smp",),
compat_names=("QemuSmp",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="ram",
help="Configure guest's RAM size",
compat_longs=("--qemu-mem",),
compat_names=("QemuMem",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="kvm",
help="Configure whether to use KVM or not",
compat_longs=("--qemu-kvm",),
compat_names=("QemuKvm",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="vsock",
help="Configure whether to use vsock or not",
compat_longs=("--qemu-vsock",),
compat_names=("QemuVsock",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="vsock_cid",
help="Specify the vsock connection ID to use",
compat_longs=("--qemu-vsock-cid",),
compat_names=("QemuVsockConnectionId",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="tpm",
help="Configure whether to use a virtual tpm or not",
compat_longs=("--qemu-swtpm",),
compat_names=("QemuSwtpm",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="cdrom",
help="Attach the image as a CD-ROM to the virtual machine",
compat_longs=("--qemu-cdrom",),
compat_names=("QemuCdrom",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="removable",
help="Attach the image as a removable drive to the virtual machine",
compat_longs=("--qemu-removable",),
compat_names=("QemuRemovable",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="firmware",
choices=Firmware.choices(),
compat_longs=("--qemu-firmware",),
compat_names=("QemuFirmware",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="firmware_variables",
help="Set the path to the firmware variables file to use",
compat_longs=("--qemu-firmware-variables",),
compat_names=("QemuFirmwareVariables",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="linux",
help="Specify the kernel to use for direct kernel boot",
compat_longs=("--qemu-kernel",),
compat_names=("QemuKernel",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="drives",
help="Specify drive that mkosi should create and pass to the virtual machine",
compat_longs=("--qemu-drive",),
compat_names=("QemuDrives",),
+ scope=SettingScope.main,
),
ConfigSetting(
dest="qemu_args",
# Suppress the command line option because it's already possible to pass qemu args as normal
# arguments.
help=argparse.SUPPRESS,
+ scope=SettingScope.main,
),
ConfigSetting(
dest="register",
parse=config_parse_feature,
default=ConfigFeature.auto,
help="Register booted vm/container with systemd-machined",
+ scope=SettingScope.main,
),
ConfigSetting(
dest="storage_target_mode",
parse=config_parse_feature,
default=ConfigFeature.auto,
help="Run systemd-storagetm as part of the serve verb",
+ scope=SettingScope.main,
),
]
SETTINGS_LOOKUP_BY_NAME = {name: s for s in SETTINGS for name in [s.name, *s.compat_names]}
if s := SETTINGS_LOOKUP_BY_NAME.get(k):
if not s.match:
- die(f"{k} cannot be used in [{section}]")
+ die(f"{path.absolute()}: {k} cannot be used in [{section}]")
+
+ if s.scope == SettingScope.main and getattr(self.config, "image") != "main":
+ die(f"{path.absolute()}: {k} cannot be matched on outside of the main image")
if k != s.name:
logging.warning(
elif m := MATCH_LOOKUP.get(k):
result = m.match(getattr(self.config, "image"), v)
else:
- die(f"{k} cannot be used in [{section}]")
+ die(f"{path.absolute()}: {k} cannot be used in [{section}]")
if negate:
result = not result
delattr(self.config, s.dest)
for s in SETTINGS:
- if s.scope == SettingScope.universal and (image := getattr(self.config, "image")) != "main":
+ image = getattr(self.config, "image")
+
+ if s.scope in (SettingScope.main, SettingScope.universal) and image != "main":
continue
if self.only_sections and s.section not in self.only_sections:
if not (s := SETTINGS_LOOKUP_BY_NAME.get(name)):
die(f"{path.absolute()}: Unknown setting {name}")
- if s.scope == SettingScope.universal and (image := getattr(self.config, "image")) != "main":
+
+ image = getattr(self.config, "image")
+
+ if s.scope in (SettingScope.main, SettingScope.universal) and image != "main":
die(f"{path.absolute()}: Setting {name} cannot be configured in subimage {image}")
if section != s.section: