unshare,
userns_has_single_user,
)
+from mkosi.sysupdate import run_sysupdate
from mkosi.tree import copy_tree, make_tree, move_tree, rmtree
from mkosi.types import PathString
from mkosi.user import INVOKING_USER
if verb == Verb.qemu and config.vmm == Vmm.vmspawn:
check_systemd_tool(config, "systemd-vmspawn", version="256", reason="boot images with vmspawn")
+ if verb == Verb.sysupdate:
+ check_systemd_tool(
+ config,
+ "systemd-sysupdate",
+ "/usr/lib/systemd/systemd-sysupdate",
+ version="257~devel",
+ reason="Update the host system with systemd-sysupdate",
+ )
+
def configure_ssh(context: Context) -> None:
if not context.config.ssh:
Verb.qemu: run_vm,
Verb.serve: run_serve,
Verb.burn: run_burn,
+ Verb.sysupdate: run_sysupdate,
}[args.verb](args, last)
burn = enum.auto()
dependencies = enum.auto()
completion = enum.auto()
+ sysupdate = enum.auto()
def supports_cmdline(self) -> bool:
return self in (
Verb.burn,
Verb.completion,
Verb.documentation,
+ Verb.sysupdate,
)
def needs_build(self) -> bool:
Verb.qemu,
Verb.serve,
Verb.burn,
+ Verb.sysupdate,
)
def needs_root(self) -> bool:
image_version: Optional[str]
split_artifacts: bool
repart_dirs: list[Path]
+ sysupdate_dir: Optional[Path]
sector_size: Optional[int]
overlay: bool
seed: uuid.UUID
parse=config_make_path_parser(required=False),
help="Set the path used to store forwarded machine journals",
),
+ ConfigSetting(
+ dest="sysupdate_dir",
+ long="--sysupdate-dir",
+ metavar="PATH",
+ name="SysupdateDirectory",
+ section="Host",
+ parse=config_make_path_parser(),
+ paths=("mkosi.sysupdate",),
+ help="Directory containing systemd-sysupdate transfer definitions",
+ ),
ConfigSetting(
dest="qemu_gui",
metavar="BOOL",
`mkosi [options…] coredumpctl [command line…]`
+`mkosi [options…] sysupdate [command line…]`
+
`mkosi [options…] clean`
`mkosi [options…] serve`
forwarded journal instead of the image. Note that this requires
configuring systemd-coredump to store coredumps in the journal.
+`sysupdate`
+: Invokes `systemd-sysupdate` with the `--transfer-source=` option set
+ to the output directory and the `--definitions=` option set to the
+ directory configured with `SysupdateDirectory=`. Any arguments
+ specified after the `sysupdate` verb are passed directly to
+ `systemd-sysupdate` invocation.
+
`clean`
: Remove build artifacts generated on a previous build. If combined
with `-f`, also removes incremental build cache images. If `-f` is
of file if your workload produces more than `4G` worth of journal
data.
+`SysupdateDirectory=`, `--sysupdate-dir=`
+: Path to a directory containing systemd-sysupdate transfer definition
+ files that are used by `mkosi sysupdate`. If `mkosi.sysupdate/`
+ exists in the local directory, it will be used for this purpose as
+ well.
+
+ Note that `mkosi sysupdate` invokes `systemd-sysupdate` with
+ `--transfer-source=` set to the mkosi output directory. To make use
+ of this in a transfer definition file, set `PathRelativeTo=explicit`
+ to have the `Path=` setting for the transfer source be interpreted
+ relative to the mkosi output directory. Generally, configuring
+ `PathRelativeTo=explicit` and `Path=/` for the transfer source is
+ sufficient for the match pattern to be interpreted relative to the
+ mkosi output directory.
+
### [Match] Section.
`Profile=`
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+import os
+import sys
+from pathlib import Path
+
+from mkosi.config import Args, Config
+from mkosi.log import die
+from mkosi.run import run
+from mkosi.types import PathString
+
+
+def run_sysupdate(args: Args, config: Config) -> None:
+ if not config.split_artifacts:
+ die("SplitArtifacts= must be enabled to be able to use mkosi sysupdate")
+
+ if not config.sysupdate_dir:
+ die("No sysupdate definitions directory specified",
+ hint="Specify a directory containing systemd-sysupdate transfer definitions with SysupdateDirectory=")
+
+ 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,
+ ]
+
+ 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,
+ options=[
+ *(["--bind", "/boot", "/boot"] if Path("/boot").exists() else []),
+ *(["--bind", "/efi", "/efi"] if Path("/efi").exists() else []),
+ ]
+ ),
+ )
"SyncScripts": [
"/sync"
],
+ "SysupdateDirectory": "/sysupdate",
"Timezone": null,
"ToolsTree": null,
"ToolsTreeCertificates": true,
ssh_certificate=Path("/path/to/cert"),
ssh_key=None,
sync_scripts=[Path("/sync")],
+ sysupdate_dir=Path("/sysupdate"),
timezone=None,
tools_tree=None,
tools_tree_certificates=True,