2020-04-03 10:13:51 +03:00
#!/usr/bin/env bash
2021-04-09 20:39:41 +03:00
set -eux
2020-04-03 10:13:51 +03:00
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( ) {
2021-04-09 20:56:12 +03:00
local name object_path suffix
2020-04-03 10:13:51 +03:00
2021-04-09 20:56:12 +03:00
suffix = " ${ 1 ##*. } "
name = " ${ 1 %. $suffix } "
object_path = " /org/freedesktop/systemd1/unit/ ${ name //-/_2d } _2e ${ suffix } "
2020-04-03 10:13:51 +03:00
busctl call \
org.freedesktop.systemd1 \
" ${ object_path } " \
org.freedesktop.systemd1.Unit \
Freeze
}
dbus_thaw( ) {
2021-04-09 20:56:12 +03:00
local name object_path suffix
2020-04-03 10:13:51 +03:00
2021-04-09 20:56:12 +03:00
suffix = " ${ 1 ##*. } "
name = " ${ 1 %. $suffix } "
object_path = " /org/freedesktop/systemd1/unit/ ${ name //-/_2d } _2e ${ suffix } "
2020-04-03 10:13:51 +03:00
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( ) {
2021-04-09 20:56:12 +03:00
local name object_path suffix
2020-04-03 10:13:51 +03:00
2021-04-09 20:56:12 +03:00
suffix = " ${ 1 ##*. } "
name = " ${ 1 %. $suffix } "
object_path = " /org/freedesktop/systemd1/unit/ ${ name //-/_2d } _2e ${ suffix } "
2020-04-03 10:13:51 +03:00
busctl get-property \
org.freedesktop.systemd1 \
" ${ object_path } " \
org.freedesktop.systemd1.Unit \
CanFreeze
}
check_freezer_state( ) {
2021-04-09 20:56:12 +03:00
local name object_path suffix
2020-04-03 10:13:51 +03:00
2021-04-09 20:56:12 +03:00
suffix = " ${ 1 ##*. } "
name = " ${ 1 %. $suffix } "
object_path = " /org/freedesktop/systemd1/unit/ ${ name //-/_2d } _2e ${ suffix } "
2020-04-03 10:13:51 +03:00
state = $( busctl get-property \
org.freedesktop.systemd1 \
" ${ object_path } " \
org.freedesktop.systemd1.Unit \
FreezerState | cut -d " " -f2 | tr -d '"' )
[ " $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: "
2021-04-08 01:09:55 +03:00
echo 1 >/sys/fs/cgroup/" ${ slice } " /cgroup.freeze
2020-06-05 12:35:01 +03:00
# Give kernel some time to freeze the slice
sleep 1
2020-04-03 10:13:51 +03:00
# 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: "
2021-04-08 01:09:55 +03:00
echo 0 >/sys/fs/cgroup/" ${ slice } " /cgroup.freeze
2020-06-05 12:35:01 +03:00
sleep 1
2020-04-03 10:13:51 +03:00
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"
2021-04-08 01:09:55 +03:00
echo 1 >/sys/fs/cgroup/" ${ slice } " /cgroup.freeze
echo 0 >/sys/fs/cgroup/" ${ slice } " /cgroup.freeze
2020-04-03 10:13:51 +03:00
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
}
2021-04-08 01:09:55 +03:00
echo OK >/testok
2020-04-03 10:13:51 +03:00
exit 0