mirror of
https://github.com/systemd/systemd.git
synced 2024-11-01 09:21:26 +03:00
907300c3c3
When checking the unit state after `systemctl freeze|thaw` we can be "too fast" and get the intermediate state (freezing/thawing) which we're not interested in. Let's wait a bit and try to get the state again in such cases to avoid unnecessary flakiness. ``` [ 29.390203] testsuite-38.sh[218]: + state=thawing [ 29.390203] testsuite-38.sh[218]: + '[' thawing = running ']' [ 29.390203] testsuite-38.sh[218]: + echo 'error: unexpected freezer state, expected: running, actual: thawing' [ 29.390203] testsuite-38.sh[218]: error: unexpected freezer state, expected: running, actual: thawing [ 29.390203] testsuite-38.sh[218]: + exit 1 ```
305 lines
7.6 KiB
Bash
Executable File
305 lines
7.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -eux
|
|
set -o pipefail
|
|
|
|
systemd-analyze log-level debug
|
|
systemd-analyze log-target console
|
|
|
|
unit=testsuite-38-sleep.service
|
|
|
|
start_test_service() {
|
|
systemctl daemon-reload
|
|
systemctl start "${unit}"
|
|
}
|
|
|
|
dbus_freeze() {
|
|
local name object_path suffix
|
|
|
|
suffix="${1##*.}"
|
|
name="${1%.$suffix}"
|
|
object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
|
|
|
|
busctl call \
|
|
org.freedesktop.systemd1 \
|
|
"${object_path}" \
|
|
org.freedesktop.systemd1.Unit \
|
|
Freeze
|
|
}
|
|
|
|
dbus_thaw() {
|
|
local name object_path suffix
|
|
|
|
suffix="${1##*.}"
|
|
name="${1%.$suffix}"
|
|
object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
|
|
|
|
busctl call \
|
|
org.freedesktop.systemd1 \
|
|
"${object_path}" \
|
|
org.freedesktop.systemd1.Unit \
|
|
Thaw
|
|
}
|
|
|
|
dbus_freeze_unit() {
|
|
busctl call \
|
|
org.freedesktop.systemd1 \
|
|
/org/freedesktop/systemd1 \
|
|
org.freedesktop.systemd1.Manager \
|
|
FreezeUnit \
|
|
s \
|
|
"$1"
|
|
}
|
|
|
|
dbus_thaw_unit() {
|
|
busctl call \
|
|
org.freedesktop.systemd1 \
|
|
/org/freedesktop/systemd1 \
|
|
org.freedesktop.systemd1.Manager \
|
|
ThawUnit \
|
|
s \
|
|
"$1"
|
|
}
|
|
|
|
dbus_can_freeze() {
|
|
local name object_path suffix
|
|
|
|
suffix="${1##*.}"
|
|
name="${1%.$suffix}"
|
|
object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
|
|
|
|
busctl get-property \
|
|
org.freedesktop.systemd1 \
|
|
"${object_path}" \
|
|
org.freedesktop.systemd1.Unit \
|
|
CanFreeze
|
|
}
|
|
|
|
check_freezer_state() {
|
|
local name object_path suffix
|
|
|
|
suffix="${1##*.}"
|
|
name="${1%.$suffix}"
|
|
object_path="/org/freedesktop/systemd1/unit/${name//-/_2d}_2e${suffix}"
|
|
|
|
for _ in {0..10}; do
|
|
state=$(busctl get-property \
|
|
org.freedesktop.systemd1 \
|
|
"${object_path}" \
|
|
org.freedesktop.systemd1.Unit \
|
|
FreezerState | cut -d " " -f2 | tr -d '"')
|
|
|
|
# Ignore the intermediate freezing & thawing states in case we check
|
|
# the unit state too quickly
|
|
[[ "$state" =~ ^(freezing|thawing)$ ]] || break
|
|
sleep .5
|
|
done
|
|
|
|
[ "$state" = "$2" ] || {
|
|
echo "error: unexpected freezer state, expected: $2, actual: $state" >&2
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
check_cgroup_state() {
|
|
grep -q "frozen $2" /sys/fs/cgroup/system.slice/"$1"/cgroup.events
|
|
}
|
|
|
|
test_dbus_api() {
|
|
echo "Test that DBus API works:"
|
|
echo -n " - Freeze(): "
|
|
dbus_freeze "${unit}"
|
|
check_freezer_state "${unit}" "frozen"
|
|
check_cgroup_state "$unit" 1
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - Thaw(): "
|
|
dbus_thaw "${unit}"
|
|
check_freezer_state "${unit}" "running"
|
|
check_cgroup_state "$unit" 0
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - FreezeUnit(): "
|
|
dbus_freeze_unit "${unit}"
|
|
check_freezer_state "${unit}" "frozen"
|
|
check_cgroup_state "$unit" 1
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - ThawUnit(): "
|
|
dbus_thaw_unit "${unit}"
|
|
check_freezer_state "${unit}" "running"
|
|
check_cgroup_state "$unit" 0
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - CanFreeze(): "
|
|
output=$(dbus_can_freeze "${unit}")
|
|
[ "$output" = "b true" ]
|
|
echo "[ OK ]"
|
|
|
|
echo
|
|
}
|
|
|
|
test_jobs() {
|
|
local pid_before=
|
|
local pid_after=
|
|
echo "Test that it is possible to apply jobs on frozen units:"
|
|
|
|
systemctl start "${unit}"
|
|
dbus_freeze "${unit}"
|
|
check_freezer_state "${unit}" "frozen"
|
|
|
|
echo -n " - restart: "
|
|
pid_before=$(systemctl show -p MainPID "${unit}" --value)
|
|
systemctl restart "${unit}"
|
|
pid_after=$(systemctl show -p MainPID "${unit}" --value)
|
|
[ "$pid_before" != "$pid_after" ] && echo "[ OK ]"
|
|
|
|
dbus_freeze "${unit}"
|
|
check_freezer_state "${unit}" "frozen"
|
|
|
|
echo -n " - stop: "
|
|
timeout 5s systemctl stop "${unit}"
|
|
echo "[ OK ]"
|
|
|
|
echo
|
|
}
|
|
|
|
test_systemctl() {
|
|
echo "Test that systemctl freeze/thaw verbs:"
|
|
|
|
systemctl start "$unit"
|
|
|
|
echo -n " - freeze: "
|
|
systemctl freeze "$unit"
|
|
check_freezer_state "${unit}" "frozen"
|
|
check_cgroup_state "$unit" 1
|
|
# Freezing already frozen unit should be NOP and return quickly
|
|
timeout 3s systemctl freeze "$unit"
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - thaw: "
|
|
systemctl thaw "$unit"
|
|
check_freezer_state "${unit}" "running"
|
|
check_cgroup_state "$unit" 0
|
|
# Likewise thawing already running unit shouldn't block
|
|
timeout 3s systemctl thaw "$unit"
|
|
echo "[ OK ]"
|
|
|
|
systemctl stop "$unit"
|
|
|
|
echo
|
|
}
|
|
|
|
test_systemctl_show() {
|
|
echo "Test systemctl show integration:"
|
|
|
|
systemctl start "$unit"
|
|
|
|
echo -n " - FreezerState property: "
|
|
state=$(systemctl show -p FreezerState --value "$unit")
|
|
[ "$state" = "running" ]
|
|
systemctl freeze "$unit"
|
|
state=$(systemctl show -p FreezerState --value "$unit")
|
|
[ "$state" = "frozen" ]
|
|
systemctl thaw "$unit"
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - CanFreeze property: "
|
|
state=$(systemctl show -p CanFreeze --value "$unit")
|
|
[ "$state" = "yes" ]
|
|
echo "[ OK ]"
|
|
|
|
systemctl stop "$unit"
|
|
echo
|
|
}
|
|
|
|
test_recursive() {
|
|
local slice="bar.slice"
|
|
local unit="baz.service"
|
|
|
|
systemd-run --unit "$unit" --slice "$slice" sleep 3600 >/dev/null 2>&1
|
|
|
|
echo "Test recursive freezing:"
|
|
|
|
echo -n " - freeze: "
|
|
systemctl freeze "$slice"
|
|
check_freezer_state "${slice}" "frozen"
|
|
check_freezer_state "${unit}" "frozen"
|
|
grep -q "frozen 1" /sys/fs/cgroup/"${slice}"/cgroup.events
|
|
grep -q "frozen 1" /sys/fs/cgroup/"${slice}"/"${unit}"/cgroup.events
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - thaw: "
|
|
systemctl thaw "$slice"
|
|
check_freezer_state "${unit}" "running"
|
|
check_freezer_state "${slice}" "running"
|
|
grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/cgroup.events
|
|
grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/"${unit}"/cgroup.events
|
|
echo "[ OK ]"
|
|
|
|
systemctl stop "$unit"
|
|
systemctl stop "$slice"
|
|
|
|
echo
|
|
}
|
|
|
|
test_preserve_state() {
|
|
local slice="bar.slice"
|
|
local unit="baz.service"
|
|
|
|
systemd-run --unit "$unit" --slice "$slice" sleep 3600 >/dev/null 2>&1
|
|
|
|
echo "Test that freezer state is preserved when recursive freezing is initiated from outside (e.g. by manager up the tree):"
|
|
|
|
echo -n " - freeze from outside: "
|
|
echo 1 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
|
|
# Give kernel some time to freeze the slice
|
|
sleep 1
|
|
|
|
# Our state should not be affected
|
|
check_freezer_state "${slice}" "running"
|
|
check_freezer_state "${unit}" "running"
|
|
|
|
# However actual kernel state should be frozen
|
|
grep -q "frozen 1" /sys/fs/cgroup/"${slice}"/cgroup.events
|
|
grep -q "frozen 1" /sys/fs/cgroup/"${slice}"/"${unit}"/cgroup.events
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - thaw from outside: "
|
|
echo 0 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
|
|
sleep 1
|
|
|
|
check_freezer_state "${unit}" "running"
|
|
check_freezer_state "${slice}" "running"
|
|
grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/cgroup.events
|
|
grep -q "frozen 0" /sys/fs/cgroup/"${slice}"/"${unit}"/cgroup.events
|
|
echo "[ OK ]"
|
|
|
|
echo -n " - thaw from outside while inner service is frozen: "
|
|
systemctl freeze "$unit"
|
|
check_freezer_state "${unit}" "frozen"
|
|
echo 1 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
|
|
echo 0 >/sys/fs/cgroup/"${slice}"/cgroup.freeze
|
|
check_freezer_state "${slice}" "running"
|
|
check_freezer_state "${unit}" "frozen"
|
|
echo "[ OK ]"
|
|
|
|
systemctl stop "$unit"
|
|
systemctl stop "$slice"
|
|
|
|
echo
|
|
}
|
|
|
|
test -e /sys/fs/cgroup/system.slice/cgroup.freeze && {
|
|
start_test_service
|
|
test_dbus_api
|
|
test_systemctl
|
|
test_systemctl_show
|
|
test_jobs
|
|
test_recursive
|
|
test_preserve_state
|
|
}
|
|
|
|
echo OK >/testok
|
|
exit 0
|