summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Sekletár <msekleta@redhat.com>2020-04-03 09:13:51 +0200
committerMichal Sekletár <msekleta@redhat.com>2020-04-30 19:02:55 +0200
commitd446ae89c0168f17eed7135ac06df3b294b3fcc6 (patch)
tree61a990d446f359bcc51de7679e27938065f63f11
parentd9e45bc3abb8adf5a1cb20816ba8f2d2aa65b17e (diff)
downloadsystemd-d446ae89c0168f17eed7135ac06df3b294b3fcc6.tar.gz
test: add test for cgroup v2 freezer support
l---------test/TEST-38-FREEZER/Makefile1
-rwxr-xr-xtest/TEST-38-FREEZER/test.sh7
-rw-r--r--test/test-functions1
-rw-r--r--test/units/testsuite-38-sleep.service2
-rw-r--r--test/units/testsuite-38.service6
-rwxr-xr-xtest/units/testsuite-38.sh293
6 files changed, 310 insertions, 0 deletions
diff --git a/test/TEST-38-FREEZER/Makefile b/test/TEST-38-FREEZER/Makefile
new file mode 120000
index 0000000000..e9f93b1104
--- /dev/null
+++ b/test/TEST-38-FREEZER/Makefile
@@ -0,0 +1 @@
+../TEST-01-BASIC/Makefile \ No newline at end of file
diff --git a/test/TEST-38-FREEZER/test.sh b/test/TEST-38-FREEZER/test.sh
new file mode 100755
index 0000000000..3821db9f00
--- /dev/null
+++ b/test/TEST-38-FREEZER/test.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -e
+TEST_DESCRIPTION="test unit freezing and thawing via DBus and systemctl"
+TEST_NO_NSPAWN=1
+. $TEST_BASE_DIR/test-functions
+
+do_test "$@" 38
diff --git a/test/test-functions b/test/test-functions
index 8389623c20..90b6705238 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -101,6 +101,7 @@ BASICTOOLS=(
tar
tee
test
+ timeout
touch
tr
true
diff --git a/test/units/testsuite-38-sleep.service b/test/units/testsuite-38-sleep.service
new file mode 100644
index 0000000000..859f97b360
--- /dev/null
+++ b/test/units/testsuite-38-sleep.service
@@ -0,0 +1,2 @@
+[Service]
+ExecStart=/bin/sleep 3600
diff --git a/test/units/testsuite-38.service b/test/units/testsuite-38.service
new file mode 100644
index 0000000000..c848840ba0
--- /dev/null
+++ b/test/units/testsuite-38.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=TEST-38-FREEZER
+
+[Service]
+ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
+Type=oneshot
diff --git a/test/units/testsuite-38.sh b/test/units/testsuite-38.sh
new file mode 100755
index 0000000000..6fcadb8f8e
--- /dev/null
+++ b/test/units/testsuite-38.sh
@@ -0,0 +1,293 @@
+#!/usr/bin/env bash
+
+set -ex
+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 suffix=
+ suffix="${1##*.}"
+
+ local name="$(echo ${1%.$suffix} | sed s/-/_2d/g)"
+ local object_path="/org/freedesktop/systemd1/unit/${name}_2e${suffix}"
+
+ busctl call \
+ org.freedesktop.systemd1 \
+ "${object_path}" \
+ org.freedesktop.systemd1.Unit \
+ Freeze
+}
+
+dbus_thaw() {
+ local suffix=
+ suffix="${1##*.}"
+
+ local name="$(echo ${1%.$suffix} | sed s/-/_2d/g)"
+ local object_path="/org/freedesktop/systemd1/unit/${name}_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 suffix=
+ suffix="${1##*.}"
+
+ local name="$(echo ${1%.$suffix} | sed s/-/_2d/g)"
+ local object_path="/org/freedesktop/systemd1/unit/${name}_2e${suffix}"
+
+ busctl get-property \
+ org.freedesktop.systemd1 \
+ "${object_path}" \
+ org.freedesktop.systemd1.Unit \
+ CanFreeze
+}
+
+check_freezer_state() {
+ local suffix=
+ suffix="${1##*.}"
+
+ local name="$(echo ${1%.$suffix} | sed s/-/_2d/g)"
+ local object_path="/org/freedesktop/systemd1/unit/${name}_2e${suffix}"
+
+ 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: "
+ echo 1 > /sys/fs/cgroup/"${slice}"/cgroup.freeze
+
+ # 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
+ 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