JSON only supports string keys in objects, but D-Bus specification is a
bit more lenient and allows dict entries to have any basic type as key.
Let's stringify allowed non-string keys so that we can represent them as
JSON objects.
Relevant snippet from the D-Bus specification:
A DICT_ENTRY works exactly like a struct, but rather than parentheses
it uses curly braces, and it has more restrictions. The restrictions
are: it occurs only as an array element type; it has exactly two
single complete types inside the curly braces; the first single
complete type (the "key") must be a basic type rather than a container
type. Implementations must not accept dict entries outside of arrays,
must not accept dict entries with zero, one, or more than two fields,
and must not accept dict entries with non-basic-typed keys. A dict
entry is always a key-value pair.
Resolves: #32904
This is a series of commits which adds a feature needed by GNOME OS'
installer. This was show during All Systems Go 2025 talk:
https://cfp.all-systems-go.io/all-systems-go-2025/talk/QRJVL3/
To sum up this PR, this changes first systemd-repart to use BLKPG
partition instead of loop devices when possible. We need then to always
rescan the partitions to try remove partitions if it failed. We allow
encrypted partitions to stay activated and with a chosen name. And we
add a new partition configuration `BtrfsReplace=`.
Note that "replace" comes from the command `btrfs replace`. But in the
case of systemd-repart, maybe "inplace" or "move" would make more sense.
I open to suggestions.
If it is better I can split this into several PRs.
The commits:
## repart: Reuse the backing fd for fdisk
Because fdisk_assign_device tries to open block devices with O_EXCL,
when it does it blocks cryptsetup from using partition block devices for
the same disk.
Since we already have a file descriptor for the device, we can just
share it and use fdisk_assign_device_by_fd instead.
## repart: Use blkpg partitions instead of loop devices when possible
We will want to allow future features to keep some devices mounted or
active. So in order to avoid leaving a mess of many loop devices, we can
just already use the partition block device already.
## repart: Rescan disk on failure if we create blkpg partitions on the
fly
Since we did not write the partition table, then the created partitions
should get removed on error.
## repart: Allow keeping luks2 volumes opened
## repart: Add BtrfsReplace=
BtrfsReplace=/mntpnt will move the btrfs filesystem from mount point to
the partition created. After moving, it will resize to take the whole
partition.
This is useful for OS installers that move a live system into a disk and
do not require a reboot.
## repart: Add VolumeName=
When a luks2 device mapper is to be kept alive after execution of
systemd-cryptsetup, the name of the volume will be taken from this
value.
## test: Add test for repart's BtrfsReplace
Even after switching the wait loop to a polling `journalctl --grep`, the
test still fails intermittently because the very first messages emitted by
the freshly-spawned systemd-networkd-wait-online process can carry stale
journald metadata. journald associates `_SYSTEMD_UNIT=` (and friends) with
each entry by reading `/proc/$pid/cgroup` of the originating PID; if those
messages are produced before journald notices the cgroup migration into the
new service, they get tagged with `_SYSTEMD_UNIT=init.scope`. The
`-u $unit` filter then fails to match them.
Capture a journal cursor before launching the unit, and grep using
`--after-cursor=` plus `SYSLOG_IDENTIFIER=systemd-networkd-wait-online`
instead of `-u $unit`. SYSLOG_IDENTIFIER is set by the program itself, so
it's not subject to the cgroup-discovery race. The cursor bounds the search
to entries produced by this invocation, so prior wait-online runs in
earlier testcases don't interfere.
Logs from the failing run showing the messages exist but are tagged with
the wrong unit:
[ 2570.948554] TEST-75-RESOLVED.sh[2178]: + unit=wait-online-dns-ede81407-b93b-459d-8e5d-69292b42d2ae.service
[ 2571.023162] TEST-75-RESOLVED.sh[2178]: + systemd-run -u wait-online-dns-ede81407-b93b-459d-8e5d-69292b42d2ae.service ...
[ 2571.049189] TEST-75-RESOLVED.sh[2178]: + timeout 30 bash -c 'until journalctl -b -u wait-online-dns-ede81407-b93b-459d-8e5d-69292b42d2ae.service --grep ...'
[ 2571.964986] systemd-networkd-wait-online[2190]: dns0: No DNS server is accessible.
[ 2601.051088] TEST-75-RESOLVED.sh[2178]: ++ cleanup
And for that 2571.964986 entry:
_SYSTEMD_CGROUP=/init.scope
_SYSTEMD_UNIT=init.scope
_EXE=/usr/lib/systemd/systemd-executor
_CMDLINE=/usr/lib/systemd/systemd-executor --deserialize 68 ...
SYSLOG_IDENTIFIER=systemd-networkd-wait-online
MESSAGE=dns0: No DNS server is accessible.
Follow-up for d4bc62713e
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
If a unit has active jobs, when it gets serialized there are job
subsections, each with their own empty line marker. The skipping
function ignores this and skips until the marker, but then leaves
the job in place, breaking deserialization.
Consume jobs subsections too.
This shows up now that there's TEST-07-PID1.alias-corruption,
which occasionally fails when the aliased unit happens to
still have a job when the reexec happens.
```
[ 967.551630] TEST-07-PID1.sh[179]: + echo 'Testing with: systemctl daemon-reexec'
[ 967.551630] TEST-07-PID1.sh[179]: Testing with: systemctl daemon-reexec
[ 968.405274] TEST-07-PID1.sh[179]: + echo '--- Attempt 1/3 ---'
[ 968.405274] TEST-07-PID1.sh[179]: --- Attempt 1/3 ---
[ 968.698641] TEST-07-PID1.sh[179]: + echo 'Running daemon-reexec...'
[ 968.698641] TEST-07-PID1.sh[179]: Running daemon-reexec...
[ 969.130261] TEST-07-PID1.sh[179]: + echo 'legit.service PID remains 1282. Attempt 1 passed.'
[ 969.130261] TEST-07-PID1.sh[179]: legit.service PID remains 1282. Attempt 1 passed.
[ 970.870456] TEST-07-PID1.sh[179]: + echo '--- Attempt 2/3 ---'
[ 970.870456] TEST-07-PID1.sh[179]: --- Attempt 2/3 ---
[ 971.267205] TEST-07-PID1.sh[179]: + echo 'Running daemon-reexec...'
[ 971.267205] TEST-07-PID1.sh[179]: Running daemon-reexec...
[ 971.715743] TEST-07-PID1.sh[179]: + echo 'legit.service PID changed from 1282 to 1643!'
[ 971.715743] TEST-07-PID1.sh[179]: legit.service PID changed from 1282 to 1643!
```
https://github.com/systemd/systemd/actions/runs/25376867873/job/74414201255
SUSE uses a different preset, so don't just assert in the test,
instead just start the socket in case it is not enabled
TEST-74-AUX-UTILS.sh[1594]: ++ systemctl is-enabled systemd-report-basic.socket
TEST-74-AUX-UTILS.sh[1540]: + [[ disabled == enabled ]]
TEST-74-AUX-UTILS.sh[120]: + echo 'Subtest /usr/lib/systemd/tests/testdata/units/TEST-74-AUX-UTILS.report.sh failed'
Follow-up for 4409e52494
In https://github.com/systemd/systemd/pull/41688 we merged metrics
and facts for systemd-report. However while some metric sources
are enabled by default (like `io.systemd.{Manager,Network}`) the
`io.systemd.Basic` service is not enabled by default.
This commit changes this and enables it by default.
We could also enable the systemd-report-cgroup.socket but that sends
a lot more data not sure that is a good default.
The test occasionally fails on GHA CI when formatting with xxhash64
because dm-integrity's crypto_alloc_shash() -> request_module() path
flakily fails to load the algorithm:
[ 29.172664] TEST-67-INTEGRITY.sh[447]: + for a in crc32c crc32 xxhash64 sha1 sha256
[ 29.172664] TEST-67-INTEGRITY.sh[447]: + [[ xxhash64 == crc32 ]]
[ 29.172664] TEST-67-INTEGRITY.sh[447]: + test_one xxhash64 0
[ 29.172664] TEST-67-INTEGRITY.sh[447]: + integritysetup format /dev/loop0 --batch-mode -I xxhash64 ''
[ 29.223383] TEST-67-INTEGRITY.sh[1220]: device-mapper: reload ioctl on temporary-cryptsetup-fa8bebe3-1d87-4796-91e8-abc02c487bb5 (254:0) failed: No such file or directory
[ 29.226916] kernel: device-mapper: table: 254:0: integrity: Invalid internal hash (-ENOENT)
[ 29.227415] kernel: device-mapper: ioctl: error adding target to table
[ 29.231586] TEST-67-INTEGRITY.sh[1220]: Cannot format integrity for device /dev/loop0.
Preload each algorithm's crypto module before use, and skip algorithms
that are not registered in /proc/crypto.
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
Replace `grep -v null` with jq's `// empty` alternative operator when filtering unit IDs. With `set -o pipefail`, `grep` returns 1 when no lines match, which aborts the script before conditional guards can run. The `// empty` operator suppresses null output directly in jq without risking a pipeline failure.
Add varlink context and runtime builders for .timer units:
TimerContext: MonotonicTimers (with MonotonicTimerBase enum), CalendarTimers, Unit, OnClockChange, OnTimezoneChange, AccuracyUSec, RandomizedDelayUSec, RandomizedOffsetUSec, FixedRandomDelay, Persistent, WakeSystem, RemainAfterElapse, DeferReactivation
TimerRuntime: Result (TimerResult enum), NextElapseUSecRealtime, NextElapseUSecMonotonic, LastTriggerUSec
MonotonicTimerSpec and CalendarTimerSpec are separate types since they have different value types (int vs string). MonotonicTimerBase and TimerResult are proper varlink enum types.
Compared to the old io-systemd-Unit-List branch, this adds RandomizedOffsetUSec and DeferReactivation (both present in D-Bus but previously missing), and adds full runtime fields.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add varlink context and runtime builders for .swap units:
SwapContext: What, Priority, Options, TimeoutUSec, ExecActivate, ExecDeactivate
SwapRuntime: ControlPID, Result, CleanResult, UID, GID (SwapResult enum)
SwapResult is exposed as a proper varlink enum type. Runtime follows the same pattern as MountRuntime (ControlPID, Result, CleanResult, ref UID/GID).
The integration test is conditional since swap units may not be present on all systems.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add varlink context and runtime builders for .scope units:
ScopeContext: OOMPolicy (enum), RuntimeMaxUSec, RuntimeRandomizedExtraUSec, TimeoutStopUSec
ScopeRuntime: Result (ScopeResult enum)
Both OOMPolicy and ScopeResult are exposed as proper varlink enum types.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Add varlink context and runtime builders for .path units:
PathContext: Paths (array of PathType enum + path specs), Unit, MakeDirectory, DirectoryMode, TriggerLimit
PathRuntime: Result (PathResult enum)
Both PathType and PathResult are exposed as proper varlink enum types.
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
The test is flaky under sanitizers as the timeouts seem to be too short,
bump them like we do in other tests to try and make it more robust when
running with sanitizers
The socket's SubState transitions from 'running' to 'listening' shortly
after the triggered service becomes inactive, so the assert can race and
observe the stale 'running' state:
[ 1882.425335] systemd[1]: TEST-07-PID1-socket-defer-23279.service: Changed dead -> running
[ 1882.495150] TEST-07-PID1.sh[20535]: ++ systemctl show TEST-07-PID1-socket-defer-23279.socket -P SubState
[ 1882.514239] TEST-07-PID1.sh[20509]: + assert_eq running listening
[ 1882.510529] systemd[1]: TEST-07-PID1-socket-defer-23279.socket: Flushing socket before listening.
[ 1882.510559] systemd[1]: TEST-07-PID1-socket-defer-23279.socket: Changed running -> listening
Poll for 30s instead of directly asserting to try and make it more robust
The restart-trigger subtest occasionally fails on CI with:
+ assert_eq 0 1
FAIL: expected: '1' actual: '0'
even though the timer fires correctly and the echo message is in fact
written to the journal. The failure happens because the test relies on
`journalctl --unit=$UNIT_NAME` to find the message, and that filter is
based on the cgroup journald looks up for the writer PID at the time
the stdout message is received.
For very short-lived processes spawned via systemd-executor (like
`echo`), that lookup is racy: the writer's `/proc/$PID/cgroup` can
still resolve to `/init.scope` (systemd-executor's own cgroup) rather
than the service's cgroup, so the message ends up attributed to
`init.scope` and `--unit=` filtering misses it.
__CURSOR=s=6f90ff5b6a0e47c3a527a9b4892af965;i=f8ed;b=3dad0cc689a04781879e4dd846d24432;m=17703dc;t=6513be1be2506;x=8d3009a687724b5e
__REALTIME_TIMESTAMP=1778167492519174
__MONOTONIC_TIMESTAMP=24576988
__SEQNUM=63725
__SEQNUM_ID=6f90ff5b6a0e47c3a527a9b4892af965
_BOOT_ID=3dad0cc689a04781879e4dd846d24432
_HOSTNAME=H
PRIORITY=6
SYSLOG_FACILITY=3
_UID=0
_GID=0
_CAP_EFFECTIVE=1ffffffffff
_SYSTEMD_CGROUP=/init.scope
_SYSTEMD_UNIT=init.scope
_SYSTEMD_SLICE=-.slice
_EXE=/usr/lib/systemd/systemd-executor
_TRANSPORT=stdout
_COMM=18
_MACHINE_ID=89ef83adc0bc4a33a83a227201b57203
_RUNTIME_SCOPE=system
_PID=816
_CMDLINE=/usr/lib/systemd/systemd-executor --deserialize 50 --log-level debug,console:info --log-target journal-or-kmsg
_STREAM_ID=8e8e4166c99e40afaa58bcd04a50a7f4
SYSLOG_IDENTIFIER=echo
MESSAGE=Hello from timer 29581
Note _SYSTEMD_UNIT=init.scope / _SYSTEMD_CGROUP=/init.scope on the
echo output: this is what causes `--unit=timer-restart-14362` to
return 0 hits. The test failure logs from the same run confirm this:
+ JOURNAL_TS=1778160292
+ journalctl -p info --since=@1778160292 --unit=timer-restart-14362 '--grep=Hello from timer 29581'
-- No entries --
+ systemctl restart timer-restart-14362.timer
...
+ date '--set=+2 hours'
Thu May 7 15:24:52 UTC 2026
+ sleep 1
...
echo[816]: Hello from timer 29581
...
++ journalctl -q -p info --since=@1778160292 --unit=timer-restart-14362 '--grep=Hello from timer 29581'
++ wc -l
+ assert_eq 0 1
FAIL: expected: '1' actual: '0'
For comparison, in a passing local run the same message is attributed
correctly to the service unit (_SYSTEMD_UNIT=timer-restart-24147.service),
so `--unit=` matches.
Work around the underlying journald race in the test by setting an
explicit `SyslogIdentifier=` on the service and matching with `-t` plus
the unique grep pattern: `SyslogIdentifier` is carried over the stdout
stream protocol and is not affected by the cgroup lookup race.
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
The test occasionally fails because lsns returns empty output for the
transient unit, even though the process is running. e.g.:
```
[ 1843.556046] TEST-07-PID1.sh[8560]: + systemd-run --unit=newservice --property=Type=exec --property=UserNamespacePath=/proc/8608/ns/user --property=NetworkNamespacePath=/proc/8608/ns/net sleep 3600
[ 1844.205927] TEST-07-PID1.sh[8616]: ++ systemctl show newservice -p MainPID
[ 1844.221425] TEST-07-PID1.sh[8618]: ++ lsns -p 8608 -o NS -t net -n
[ 1844.229653] TEST-07-PID1.sh[8619]: ++ lsns -p 8614 -o NS -t net -n
[ 1844.235563] TEST-07-PID1.sh[8620]: FAIL: expected: '' actual: '4026532522'
```
This could be a race, so switch to Type=notify to try and make it more
robust.
eg:
https://github.com/systemd/systemd/actions/runs/25485775345/job/74780837128?pr=41974
The test occasionally fails because lsns returns empty output for
the transient unit, even though the process is running. e.g.:
[ 1843.556046] TEST-07-PID1.sh[8560]: + systemd-run --unit=newservice --property=Type=exec --property=UserNamespacePath=/proc/8608/ns/user --property=NetworkNamespacePath=/proc/8608/ns/net sleep 3600
[ 1844.205927] TEST-07-PID1.sh[8616]: ++ systemctl show newservice -p MainPID
[ 1844.221425] TEST-07-PID1.sh[8618]: ++ lsns -p 8608 -o NS -t net -n
[ 1844.229653] TEST-07-PID1.sh[8619]: ++ lsns -p 8614 -o NS -t net -n
[ 1844.235563] TEST-07-PID1.sh[8620]: FAIL: expected: '' actual: '4026532522'
This could be a race, so switch to Type=notify to try and make it more robust.
The basic idea is that --chain should stop option parsing. But
previously this didn't work, so --chain could be specified anywhere
in the command line. To maintain with compatibility with that,
allow --chain to be specified anywhere until the first positional
arg or option in the command string. This allows options to be passed
in the expected fashion:
userdbctl --chain ssh-authorized-keys user cmd --opt1 --opt2
userdbctl --chain ssh-authorized-keys user -- cmd --opt1 --opt2
but also allows the invocations which worked previously:
userdbctl ssh-authorized-keys user --chain cmd
userdbctl ssh-authorized-keys user cmd --chain
Fixes 8072a7e6a9.
The error messages are extended a bit. "binary path" is misleading:
we support all kinds of executables, not only compiled programs.
The io.systemd.JournalAccess server occasionally returns NoEntries for a
unit-filter query right after the unit logged its message, e.g. from a
failing CI run:
[ 1204.967910] TEST-04-JOURNAL.sh[15025]: ++ varlinkctl call --more /run/systemd/io.systemd.JournalAccess io.systemd.JournalAccess.GetEntries '{"units": ["test-journalctl-varlink-1-13583.service", "test-journalctl-varlink-2-25039.service"]}'
[ 1205.017361] journalctl[15026]: varlink-3-3: Received message: {"method":"io.systemd.JournalAccess.GetEntries","parameters":{"units":["test-journalctl-varlink-1-13583.service","test-journalctl-varlink-2-25039.service"]},"more":true}
[ 1205.017498] journalctl[15026]: Failed to open journal file /var/log/journal/ce54feb228124e639f3b7779beeaff60/system.journal: No data available
[ 1205.017823] journalctl[15026]: varlink-3-3: Sending message: {"error":"io.systemd.JournalAccess.NoEntries"}
[ 1205.017936] TEST-04-JOURNAL.sh[15025]: Method call failed: io.systemd.JournalAccess.NoEntries
[ 1205.499083] TEST-04-JOURNAL.sh[146]: Subtest /usr/lib/systemd/tests/testdata/units/TEST-04-JOURNAL.journalctl-varlink.sh failed
Wrap the calls that expect data in a helper that retries up to 3 times on
NoEntries, syncing the journal between attempts.
Follow-up for a109189fab
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
The test used `timeout 30 bash -c "journalctl -b -u $unit -f | grep -m1 ..."`
to wait for systemd-networkd-wait-online to log that no DNS server is
accessible. The expected message is actually emitted ~1s after the unit
starts, but `grep -m1` exiting doesn't tear down `journalctl -f`: journalctl
only notices the closed pipe on its next write, which may never happen for
an otherwise idle unit. The pipeline therefore hangs until the 30s timeout
fires, eventually causing the test to fail.
Replace the follow+pipe with a polling `journalctl --grep` loop, which
exits cleanly as soon as the message lands in the journal.
Logs from the failing run:
[ 2650.871441] systemd-networkd-wait-online[2190]: dns0: No DNS configuration yet
[ 2651.723180] systemd-networkd-wait-online[2190]: dns0: No DNS server is accessible.
[ 2680.909048] systemd-networkd-wait-online[2190]: json-stream: Got POLLHUP from socket.
[ 2680.909092] systemd-networkd-wait-online[2190]: DNS configuration monitor disconnected, reconnecting...
[ 2680.914368] systemd-networkd-wait-online[2190]: Failed to connect to io.systemd.Resolve.Monitor: Connection refused
[ 2681.966674] systemd-networkd-wait-online[2190]: dns0: No DNS server is accessible.
[ 2681.969527] systemd-networkd-wait-online[2190]: Failed to connect to io.systemd.Resolve.Monitor: Connection refused
[ 2682.077032] systemd[1]: Stopping wait-online-dns-0f9e4f6d-8b34-4cff-b2da-03612ca731e8.service - [systemd-run] /usr/lib/systemd/systemd-networkd-wait-online --timeout=0 --dns --interface=dns0...
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
The existing alias-corruption subtest only intermittently caught the
regression where unit_deserialize_state_skip() stopped at the first
empty line and thus failed to consume embedded "job" subsections
(written by job_serialize() when u->job or u->nop_job is non-NULL).
This same skip routine is also used by the pre-scan that builds the set
of serialized unit names (added in a77c7a8224 to detect stale alias
state). When skip terminates early at a job's end marker, the scan
desyncs and every subsequent unit name is dropped from the set,
silently bypassing the alias-corruption protection for those units.
Whether the bug fired depended on:
1. Whether any unit happened to carry a pending job at the moment of
reload/reexec (mostly chance, depends on timers, transient units,
load, etc.).
2. Hashmap iteration order during serialization (per-boot randomized
siphash seed) determining if a job-bearing unit was written before
a sus-NN.service alias.
To try and make the regression deterministic, add a "with_pending_jobs" mode
that creates 50 Type=oneshot services and starts them with
systemctl --no-block. Each remains in "activating" state with u->job
set forever, guaranteeing the serialized stream contains many embedded
job subsections regardless of hashmap order, and that at least one of
them precedes the sus units. Without the fix, the desync drops the
sus-NN entries from the set, the alias-corruption check
set_contains(serialized_units, u->id) returns false for every alias,
and legit.service's MainPID is overwritten on every run.
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
- Document the new --bind-volume= option in systemd-vmspawn(1) and
the new bind-volume / unbind-volume verbs in machinectl(1).
- Add an integration test
(TEST-87-AUX-UTILS-VM.bind-volume.sh) covering boot-time attach
via --bind-volume, runtime attach via 'machinectl bind-volume',
runtime detach via 'machinectl unbind-volume', the StorageImmutable
rejection of attempts to detach boot-time volumes, and the
NoSuchStorage rejection of detach on unknown names.
- Strike "hook-up in systemd-vmspawn" from TODO.md; the nspawn and
service-manager hookups remain.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
We removed the concept of facts, so we need to update the existing
io.systemd.Basic facts provider to metrics. This commit does just
that. Its mostly mechanical.
This also means that facts.{c,h} and varlink-io.systemd.Facts.{c,h}
are gone now.
Two new verbs are added: "generate" and "upload". The first one just
creates a "report", i.e. puts the metrics into a structured JSON object
that in the future is intended to carry additional data like a
signature:
$ build/systemd-report generate io.systemd.Manager.UnitsTotal
{
"mediaType" : "application/vnd.io.systemd.report",
"timestamp" : "Tue 2026-04-28 22:30:09 UTC",
"metrics" : [
{
"name" : "io.systemd.Manager.UnitsTotal",
"value" : 520
}
]
}
The second verb can be used to upload or otherwise process the report.
It builds on the code added in 0a8560eed8.
In /run/systemd/metrics-upload/ we expect a set of sockets. We'll call
out to each one of them. This allows the data to be processed in custom
ways, incl. writing to storage or sending over the network.
Each socket must provide a single interface:
io.systemd.Metrics.Upload {"report":$data}
This test is sometimes flaky under sanitizers, and it does repeated
calls with the same parameters to run through different greps, and
the second one sometimes fails.
Store the result and grep it twice instead to try and reduce
flakiness.
[ 2089.891152] TEST-04-JOURNAL.sh[22392]: + systemd-run --unit=test-journalctl-varlink-2-18237.service --wait bash -c 'echo hello-from-varlink-test-2'
[ 2090.066050] TEST-04-JOURNAL.sh[22460]: + varlinkctl call --more /run/systemd/io.systemd.JournalAccess io.systemd.JournalAccess.GetEntries '{"units": ["test-journalctl-varlink-1-22690.service"]}'
[ 2090.067075] TEST-04-JOURNAL.sh[22461]: + grep -q hello-from-varlink-test-1
[ 2090.384551] TEST-04-JOURNAL.sh[22466]: + varlinkctl call --more /run/systemd/io.systemd.JournalAccess io.systemd.JournalAccess.GetEntries '{"units": ["test-journalctl-varlink-1-22690.service"]}'
[ 2090.385373] TEST-04-JOURNAL.sh[22467]: + grep hello-from-varlink-test-2
[ 2090.723461] TEST-04-JOURNAL.sh[22474]: + grep -q hello-from-varlink-test-1
[ 2090.724294] TEST-04-JOURNAL.sh[22473]: + varlinkctl call --more /run/systemd/io.systemd.JournalAccess io.systemd.JournalAccess.GetEntries '{"units": ["test-journalctl-varlink-1-22690.service", "test-journalctl-varlink-2-18237.service"]}'
[ 2091.135655] TEST-04-JOURNAL.sh[22480]: + varlinkctl call --more /run/systemd/io.systemd.JournalAccess io.systemd.JournalAccess.GetEntries '{"units": ["test-journalctl-varlink-1-22690.service", "test-journalctl-varlink-2-18237.service"]}'
[ 2091.136605] TEST-04-JOURNAL.sh[22481]: + grep -q hello-from-varlink-test-2
[ 2091.479930] TEST-04-JOURNAL.sh[22480]: Method call failed: io.systemd.JournalAccess.NoEntries
This is a reiteration of #38764, but this time on top of "bootctl link"
for installing a kernel, i.e. #41543, instead of "kernel-install".
It's the same as #41543, only adds three new commits on top.
The LUKS subtest in testcase_btrfs_basic leaves stale LUKS headers on
the underlying SCSI devices, so if the VM is rebooted the test fails
because the LUKS signature is still there and blkid finds it.
[ 7.683] + udevadm lock ... mkfs.btrfs -f -L btrfs_root -U deadbeef-dead-dead-beef-000000000000 /dev/disk/by-id/scsi-0systemd_foobar_deadbeefbtrfs0
[ 7.729] Label: btrfs_root
[ 7.729] UUID: deadbeef-dead-dead-beef-000000000000
[ 7.743] + udevadm wait --settle --timeout=30 /dev/disk/by-id/scsi-0systemd_foobar_deadbeefbtrfs0 /dev/disk/by-uuid/deadbeef-dead-dead-beef-000000000000 /dev/disk/by-label/btrfs_root
[ 7.788] sda: ... SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}": Added device node symlink "disk/by-label/encdisk0".
[ 37.998] Timed out for waiting devices being initialized.
[ 38.002] TEST-64-UDEV-STORAGE-btrfs_basic.service: Main process exited, code=exited, status=1/FAILURE
Likewise for the BTRFS UUID:
ERROR: non-unique UUID: deadbeef-dead-dead-beef-000000000001
So wipe that too.
systemd-dissect --mtree calls io.systemd.PCRExtend over Varlink to extend
the verity NvPCR after activation, and the test then diffs the measure
log to find the new entry. But systemd-pcrextend.socket has
ConditionSecurity=measured-os, which fails when the firmware did not
initialize PCRs, so the test fails.
[ 10.056930] systemd[1]: systemd-pcrextend.socket - TPM PCR Measurements skipped, unmet condition check ConditionSecurity=measured-os
Follow-up for 521a523ce0
Add ReloadCount to the io.systemd.Metrics family table so it can be
queried alongside other manager-level metrics via systemd-report.
Also extend the existing integration test to cross-check the value
returned by systemd-report against the D-Bus and Varlink transports
on every assertion.
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Simon Lucido <simonlucido@meta.com>
A segfault is observed when both key_file and tpm2-device are
simultaneously passed to systemd-cryptsetup, e.g.:
systemd-cryptsetup attach test_data /vol /my-pass tpm2-device=auto
The crash appears after commit 5c6aad9 but the flaw in the logic was
pre-existing.
Fixes#41867
TEST-06-SELINUX occasionally fails because repeated nspawn invocations use
the same machine name and scope:
TEST-06-SELINUX.sh[598]: Failed to allocate scope: Unit H.scope was already loaded or has a fragment file.
Use a different machine name/scope for each invocation in the test
case to avoid hitting this issue
The dditest block calls systemd-repart with Encrypt=tpm2 but without
--tpm2-public-key-pcrs=. Since systemd-stub drops
/run/systemd/tpm2-pcr-public-key.pem when booting from a signed UKI
systemd-repart auto-loads it and enrolls a signed PCR policy, and
then systemd-cryptsetup tpm2-device=auto has no matching signature file,
so unlock fails.
--tpm2-public-key= is not enough as the default kicks in then.
Follow-up for cd18656d47
mdadm --zero-superblock only wipes the MD metadata on the underlying
disks, not the LVM PV header that lives in the array data area. When
the VM is restarted and the test re-creates the array with the same
UUID, /dev/md127 exposes the old data including the LVM PV header, so
udev's 69-lvm.rules auto-triggers lvm-activate-mdlvm_vg.service which
races with the test's own pvcreate for exclusive access on /dev/md127.
Wipe the LVM signature off the MD device (and the underlying disks as
a belt-and-braces measure) to avoid the race on re-run, fixing failures
when the VM is rebooted instead of shut down.
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
write_to_journal() was called via $(...) command substitution, so
SERVICE_COUNTER++ ran in a subshell and never incremented in the
parent:
[ 1492.668302] TEST-04-JOURNAL.sh[15064]: + local service=test-0-18493.service
[ 1492.725882] TEST-04-JOURNAL.sh[15064]: + local service=test-0-18009.service
[ 1492.739643] TEST-04-JOURNAL.sh[15064]: + local service=test-0-18493.service
[ 1492.774586] TEST-04-JOURNAL.sh[15064]: + local service=test-0-25540.service
[ 1492.815664] TEST-04-JOURNAL.sh[15064]: + local service=test-0-15916.service
[ 1492.867067] TEST-04-JOURNAL.sh[15064]: + local service=test-0-20327.service
[ 1492.899077] TEST-04-JOURNAL.sh[15064]: + local service=test-0-86.service
[ 1497.289715] TEST-04-JOURNAL.sh[15064]: + local service=test-0-10849.service
[ 1497.335791] TEST-04-JOURNAL.sh[15064]: + local service=test-0-18009.service
With 99999 possible unit names collisions are rare but not impossible,
so every now and then a CI run fails.
Have write_to_journal() set a global SERVICE_NAME variable instead and
call it directly so SERVICE_COUNTER actually goes up through the test.
When key_file is passed along with tpm2-device= to systemd-cryptsetup, the
logic is to try the blob as a TPM blob first, and then fall back to trying the
file as a regular key file. Check that this fallback works.
When qemu reboots instead of shutting down after the last iteration,
the profile is already set to profile2 but the /root/encrypted.raw is
gone so the test fails. Reset the default boot entry at the end of the
test to make it robust against reruns.
Fixes https://github.com/systemd/systemd/issues/39553
The test leaves a lot of state around, and when the test is re-run,
for example due to the qemu bug that makes a VM reboot instead of
shutting down, it fails.
Do more cleanups in the traps.
[ 162.642175] TEST-70-TPM2.sh[2815]: Calculated public key name: 000b2b66edc3a466e81059286aaf38d09ea42a7a9dcdf6ba3b664c62f0cae4ce4f66
[ 162.642628] TEST-70-TPM2.sh[2815]: PolicyAuthorize calculated digest: 2caa740101f65734d50395d6abc64fa46015d40d1f5de239434578544e592a92
[ 162.643681] TEST-70-TPM2.sh[2815]: Calculated NV index name: 000b439cfa1534815bbe8d33b80c56f5a8d17d36fe94a7782b23a37b50def5fc5eaa
[ 162.645111] TEST-70-TPM2.sh[2815]: PolicyAuthorizeNV calculated digest: 69ee0e89fafe6b9df2cd6a5defbf74aa46cf6d92703e645d463549da4ba5e1a4
[ 162.645407] TEST-70-TPM2.sh[2815]: Combined signed PCR policies and pcrlock policies cannot be calculated offline, currently.
[ 162.649576] TEST-70-TPM2.sh[2815]: Releasing crypt device /dev/loop0 context.
[ 162.652433] TEST-70-TPM2.sh[2815]: Releasing device-mapper backend.
[ 162.653518] TEST-70-TPM2.sh[2815]: Closing read only fd for /dev/loop0.
[ 162.654359] TEST-70-TPM2.sh[2815]: Closing read write fd for /dev/loop0.
[ 162.654786] TEST-70-TPM2.sh[2815]: Failed to encrypt device: Operation not supported
Fixes https://github.com/systemd/systemd/issues/38241