2023-05-03 16:05:12 +03:00
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -ex
set -o pipefail
2023-11-26 03:25:22 +03:00
# shellcheck source=test/units/util.sh
. " $( dirname " $0 " ) " /util.sh
2023-09-29 23:07:12 +03:00
at_exit( ) {
# Since the soft-reboot drops the enqueued end.service, we won't shutdown
# the test VM if the test fails and have to wait for the watchdog to kill
# us (which may take quite a long time). Let's just forcibly kill the machine
# instead to save CI resources.
if [ [ $? -ne 0 ] ] ; then
echo >& 2 "Test failed, shutting down the machine..."
systemctl poweroff -ff
fi
}
trap at_exit EXIT
2024-08-02 17:25:03 +03:00
# Because this test tests soft-reboot, we have to get rid of the symlink we put at
# /run/nextroot to allow rebooting into the previous snapshot if the test fails for
# the duration of the test. However, let's make sure we put the symlink back in place
# if the test fails.
if [ [ -L /run/nextroot ] ] ; then
at_error( ) {
mountpoint -q /run/nextroot && umount -R /run/nextroot
rm -rf /run/nextroot
ln -sf /snapshot /run/nextroot
}
trap at_error ERR
rm -f /run/nextroot
fi
2023-05-03 16:05:12 +03:00
systemd-analyze log-level debug
export SYSTEMD_LOG_LEVEL = debug
2024-05-11 20:17:13 +03:00
if [ -f /run/TEST-82-SOFTREBOOT.touch3 ] ; then
2023-05-03 16:05:12 +03:00
echo "This is the fourth boot!"
systemd-notify --status= "Fourth Boot"
2024-03-27 03:30:45 +03:00
test " $( busctl -j get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SoftRebootsCount | jq -r '.data' ) " -eq 3
2024-05-11 20:17:13 +03:00
rm /run/TEST-82-SOFTREBOOT.touch3
2023-05-03 16:05:12 +03:00
mount
rmdir /original-root /run/nextroot
# Check that the fdstore entry still exists
test " $LISTEN_FDS " -eq 3
read -r x <& 5
test " $x " = "oinkoink"
2023-09-23 19:52:03 +03:00
# Check that the surviving services are still around
2024-05-11 20:17:13 +03:00
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-survive.service) " = "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-survive-argv.service) " = "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-nosurvive-sigterm.service) " != "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-nosurvive.service) " != "active"
2023-05-03 16:05:12 +03:00
2024-05-14 14:34:11 +03:00
[ [ ! -e /run/credentials/TEST-82-SOFTREBOOT-nosurvive.service ] ]
assert_eq " $( cat /run/credentials/TEST-82-SOFTREBOOT-survive-argv.service/preserve) " "yay"
2024-05-19 01:12:48 +03:00
# There may be huge amount of pending messages in sockets. Processing them may cause journal rotation and
# removal of old archived journal files. If a journal file is removed during journalctl reading it,
# the command may fail. To mitigate such, sync before reading journals. Workaround for #32834.
journalctl --sync
2023-11-26 03:25:22 +03:00
# Check journals
journalctl -o short-monotonic --no-hostname --grep '(will soft-reboot|KILL|corrupt)'
assert_eq " $( journalctl -q -o short-monotonic -u systemd-journald.service --grep 'corrupt' ) " ""
2023-05-03 16:05:12 +03:00
# All succeeded, exit cleanly now
2024-05-11 20:17:13 +03:00
elif [ -f /run/TEST-82-SOFTREBOOT.touch2 ] ; then
2023-05-03 16:05:12 +03:00
echo "This is the third boot!"
systemd-notify --status= "Third Boot"
2024-03-27 03:30:45 +03:00
test " $( busctl -j get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SoftRebootsCount | jq -r '.data' ) " -eq 2
2024-05-11 20:17:13 +03:00
rm /run/TEST-82-SOFTREBOOT.touch2
2023-05-03 16:05:12 +03:00
# Check that the fdstore entry still exists
test " $LISTEN_FDS " -eq 2
read -r x <& 4
test " $x " = "miaumiau"
# Upload another entry
T = " /dev/shm/fdstore. $RANDOM "
echo "oinkoink" >" $T "
systemd-notify --fd= 3 --pid= parent 3<" $T "
rm " $T "
2023-09-23 19:52:03 +03:00
# Check that the surviving services are still around
2024-05-11 20:17:13 +03:00
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-survive.service) " = "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-survive-argv.service) " = "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-nosurvive-sigterm.service) " != "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-nosurvive.service) " != "active"
2023-05-03 16:05:12 +03:00
# Test that we really are in the new overlayfs root fs
read -r x </lower
test " $x " = "miep"
2023-08-14 00:29:25 +03:00
cmp /etc/os-release /run/systemd/propagate/.os-release-stage/os-release
2023-07-18 17:44:27 +03:00
grep -q MARKER = 1 /etc/os-release
2023-05-03 16:05:12 +03:00
# Switch back to the original root, away from the overlayfs
mount --bind /original-root /run/nextroot
mount
2023-07-28 01:14:31 +03:00
# Restart the unit that is not supposed to survive
2024-05-11 20:17:13 +03:00
systemd-run --collect --service-type= exec --unit= TEST-82-SOFTREBOOT-nosurvive.service sleep infinity
2023-07-28 01:14:31 +03:00
2023-05-03 16:05:12 +03:00
# Now issue the soft reboot. We should be right back soon.
2024-05-11 20:17:13 +03:00
touch /run/TEST-82-SOFTREBOOT.touch3
2023-05-03 16:05:12 +03:00
systemctl --no-block soft-reboot
# Now block until the soft-boot killing spree kills us
exec sleep infinity
2024-05-11 20:17:13 +03:00
elif [ -f /run/TEST-82-SOFTREBOOT.touch ] ; then
2023-05-03 16:05:12 +03:00
echo "This is the second boot!"
systemd-notify --status= "Second Boot"
2024-03-27 03:30:45 +03:00
test " $( busctl -j get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SoftRebootsCount | jq -r '.data' ) " -eq 1
2023-05-03 16:05:12 +03:00
# Clean up what we created earlier
2024-05-11 20:17:13 +03:00
rm /run/TEST-82-SOFTREBOOT.touch
2023-05-03 16:05:12 +03:00
# Check that the fdstore entry still exists
test " $LISTEN_FDS " -eq 1
read -r x <& 3
test " $x " = "wuffwuff"
2023-08-30 21:51:13 +03:00
# Check that we got a PrepareForShutdownWithMetadata signal with the right type
2024-05-11 20:17:13 +03:00
cat /run/TEST-82-SOFTREBOOT.signal
test " $( jq -r '.payload.data[1].type.data' </run/TEST-82-SOFTREBOOT.signal) " = "soft-reboot"
2023-08-30 21:51:13 +03:00
2024-05-14 11:25:33 +03:00
# Check that the system credentials survived the soft reboot.
test " $( systemd-creds cat --system kernelcmdlinecred) " = "uff"
2023-05-03 16:05:12 +03:00
# Upload another entry
T = " /dev/shm/fdstore. $RANDOM "
echo "miaumiau" >" $T "
systemd-notify --fd= 3 --pid= parent 3<" $T "
rm " $T "
2023-09-23 19:52:03 +03:00
# Check that the surviving services are still around
2024-05-11 20:17:13 +03:00
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-survive.service) " = "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-survive-argv.service) " = "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-nosurvive-sigterm.service) " != "active"
test " $( systemctl show -P ActiveState TEST-82-SOFTREBOOT-nosurvive.service) " != "active"
2023-05-03 16:05:12 +03:00
# This time we test the /run/nextroot/ root switching logic. (We synthesize a new rootfs from the old via overlayfs)
mkdir -p /run/nextroot /tmp/nextroot-lower /original-root
mount -t tmpfs tmpfs /tmp/nextroot-lower
echo miep >/tmp/nextroot-lower/lower
2023-07-18 17:44:27 +03:00
# Copy os-release away, so that we can manipulate it and check that it is updated in the propagate
2023-08-11 16:42:02 +03:00
# directory across soft reboots. Try to cover corner cases by truncating it.
2024-10-18 17:02:03 +03:00
mkdir -p /tmp/nextroot-lower/etc
grep ID /etc/os-release >/tmp/nextroot-lower/etc/os-release
echo MARKER = 1 >>/tmp/nextroot-lower/etc/os-release
2023-08-14 00:29:25 +03:00
cmp /etc/os-release /run/systemd/propagate/.os-release-stage/os-release
2023-07-18 17:44:27 +03:00
( ! grep -q MARKER = 1 /etc/os-release)
mount -t overlay nextroot /run/nextroot -o lowerdir = /tmp/nextroot-lower:/,ro
2023-05-03 16:05:12 +03:00
# Bind our current root into the target so that we later can return to it
mount --bind / /run/nextroot/original-root
2023-07-28 01:14:31 +03:00
# Restart the unit that is not supposed to survive
2024-05-11 20:17:13 +03:00
systemd-run --collect --service-type= exec --unit= TEST-82-SOFTREBOOT-nosurvive.service sleep infinity
2023-07-28 01:14:31 +03:00
2024-03-28 00:14:15 +03:00
# Now ensure there are no naming clashes and a bunch of transient units all succeed
for _ in $( seq 1 25) ; do
systemd-run --wait true
done
2023-10-19 15:58:03 +03:00
# Now issue the soft reboot. We should be right back soon. Given /run/nextroot exists, we should
# automatically do a softreboot instead of normal reboot.
2024-05-11 20:17:13 +03:00
touch /run/TEST-82-SOFTREBOOT.touch2
2023-10-19 15:58:03 +03:00
systemctl --no-block reboot
2023-05-03 16:05:12 +03:00
# Now block until the soft-boot killing spree kills us
exec sleep infinity
else
# This is the first boot
systemd-notify --status= "First Boot"
2024-03-27 03:30:45 +03:00
test " $( busctl -j get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager SoftRebootsCount | jq -r '.data' ) " -eq 0
2023-06-15 21:37:55 +03:00
# Let's upload an fd to the fdstore, so that we can verify fdstore passing works correctly
2023-05-03 16:05:12 +03:00
T = " /dev/shm/fdstore. $RANDOM "
echo "wuffwuff" >" $T "
systemd-notify --fd= 3 --pid= parent 3<" $T "
rm " $T "
2023-09-23 19:52:03 +03:00
survive_sigterm = " /dev/shm/survive-sigterm- $RANDOM .sh "
cat >" $survive_sigterm " <<EOF
#!/bin/bash
trap "" TERM
systemd-notify --ready
rm " $survive_sigterm "
exec sleep infinity
EOF
chmod +x " $survive_sigterm "
survive_argv = " /dev/shm/survive-argv- $RANDOM .sh "
cat >" $survive_argv " <<EOF
#!/bin/bash
systemd-notify --ready
rm " $survive_argv "
exec -a @sleep sleep infinity
EOF
chmod +x " $survive_argv "
# This sets DefaultDependencies=no so that they remain running until the very end, and
# IgnoreOnIsolate=yes so that they aren't stopped via the "testsuite.target" isolation we do on next boot,
# and will be killed by the final sigterm/sigkill spree.
2024-05-11 20:17:13 +03:00
systemd-run --collect --service-type= notify -p DefaultDependencies = no -p IgnoreOnIsolate = yes --unit= TEST-82-SOFTREBOOT-nosurvive-sigterm.service " $survive_sigterm "
2024-05-14 14:34:11 +03:00
systemd-run --collect --service-type= exec -p DefaultDependencies = no -p IgnoreOnIsolate = yes -p SetCredential = gone:hoge --unit= TEST-82-SOFTREBOOT-nosurvive.service sleep infinity
2023-09-23 19:52:03 +03:00
2023-11-28 02:32:31 +03:00
# Ensure that the unit doesn't get deactivated by dependencies on the source file. Given it's a verity
# image that is already open, even if the tmpfs with the image goes away, the file will be pinned by the
# kernel and will keep working.
cp /usr/share/minimal_0.* /tmp/
2023-09-23 19:52:03 +03:00
# Configure these transient units to survive the soft reboot - they will not conflict with shutdown.target
# and it will be ignored on the isolate that happens in the next boot. The first will use argv[0][0] =
# '@', and the second will use SurviveFinalKillSignal=yes. Both should survive.
2024-05-31 18:40:12 +03:00
# By writing to stdout, which is connected to the journal, we also ensure logging doesn't break across
# soft reboots due to journald being temporarily stopped.
2024-05-11 20:17:13 +03:00
systemd-run --service-type= notify --unit= TEST-82-SOFTREBOOT-survive-argv.service \
2023-09-23 19:52:03 +03:00
--property SurviveFinalKillSignal = no \
--property IgnoreOnIsolate = yes \
--property DefaultDependencies = no \
--property After = basic.target \
--property "Conflicts=reboot.target kexec.target poweroff.target halt.target emergency.target rescue.target" \
--property "Before=reboot.target kexec.target poweroff.target halt.target emergency.target rescue.target" \
2024-05-14 14:34:11 +03:00
--property SetCredential = preserve:yay \
2023-09-23 19:52:03 +03:00
" $survive_argv "
2024-05-31 18:40:12 +03:00
# shellcheck disable=SC2016
2024-05-11 20:17:13 +03:00
systemd-run --service-type= exec --unit= TEST-82-SOFTREBOOT-survive.service \
2023-11-28 02:32:31 +03:00
--property TemporaryFileSystem = "/run /tmp /var" \
--property RootImage = /tmp/minimal_0.raw \
2023-07-28 01:14:31 +03:00
--property SurviveFinalKillSignal = yes \
--property IgnoreOnIsolate = yes \
--property DefaultDependencies = no \
--property After = basic.target \
--property "Conflicts=reboot.target kexec.target poweroff.target halt.target emergency.target rescue.target" \
--property "Before=reboot.target kexec.target poweroff.target halt.target emergency.target rescue.target" \
2024-05-31 18:40:12 +03:00
bash -c 'count=0; while echo "$count"; do count=$[$count +1]; sleep 1; done'
2023-05-03 16:05:12 +03:00
2023-08-30 21:51:13 +03:00
# Check that we can set up an inhibitor, and that busctl monitor sees the
# PrepareForShutdownWithMetadata signal and that it says 'soft-reboot'.
2024-05-11 20:17:13 +03:00
systemd-run --unit busctl.service --service-type= exec --property StandardOutput = file:/run/TEST-82-SOFTREBOOT.signal \
2023-08-30 21:51:13 +03:00
busctl monitor --json= pretty --match 'sender=org.freedesktop.login1,path=/org/freedesktop/login1,interface=org.freedesktop.login1.Manager,member=PrepareForShutdownWithMetadata,type=signal'
2023-10-03 17:38:35 +03:00
systemd-run --unit inhibit.service --service-type= exec \
2023-08-30 21:51:13 +03:00
systemd-inhibit --what= shutdown --who= test --why= test --mode= delay \
sleep infinity
2024-03-28 00:14:15 +03:00
# Enqueue a bunch of failing units to try and trigger the transient name clash that happens due to D-Bus
# being restarted and the "unique" bus IDs not being unique across restarts
for _ in $( seq 1 25) ; do
# Use --wait to ensure we connect to the system bus instead of the private bus (otherwise a UUID is
# used instead of the bus ID)
systemd-run --wait false || true
done
2023-05-03 16:05:12 +03:00
# Now issue the soft reboot. We should be right back soon.
2024-05-11 20:17:13 +03:00
touch /run/TEST-82-SOFTREBOOT.touch
2023-08-30 21:51:13 +03:00
systemctl --no-block --check-inhibitors= yes soft-reboot
2023-05-03 16:05:12 +03:00
2024-08-05 01:47:29 +03:00
# Ensure the property works too
type = " $( busctl --json= short get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager PreparingForShutdownWithMetadata | jq -r '.data.type.data' ) "
test " $type " = "soft-reboot"
2023-05-03 16:05:12 +03:00
# Now block until the soft-boot killing spree kills us
exec sleep infinity
fi
systemd-analyze log-level info
2023-07-12 16:49:55 +03:00
touch /testok
2024-04-29 17:28:21 +03:00
systemctl --no-block exit 123