You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
398 lines
11 KiB
398 lines
11 KiB
From 762959047c1e1a5d4b6a6fe85cfa8a14c622e4da Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= <msekleta@redhat.com>
|
|
Date: Fri, 3 Apr 2020 09:13:51 +0200
|
|
Subject: [PATCH] test: add test for cgroup v2 freezer support
|
|
|
|
(cherry picked from commit d446ae89c0168f17eed7135ac06df3b294b3fcc6)
|
|
|
|
Related: #1830861
|
|
---
|
|
ci/travis-centos-rhel8.sh | 2 +-
|
|
test/TEST-38-FREEZER/Makefile | 1 +
|
|
test/TEST-38-FREEZER/test.sh | 53 ++++++
|
|
test/TEST-38-FREEZER/testsuite.sh | 293 ++++++++++++++++++++++++++++++
|
|
4 files changed, 348 insertions(+), 1 deletion(-)
|
|
create mode 120000 test/TEST-38-FREEZER/Makefile
|
|
create mode 100755 test/TEST-38-FREEZER/test.sh
|
|
create mode 100755 test/TEST-38-FREEZER/testsuite.sh
|
|
|
|
diff --git a/ci/travis-centos-rhel8.sh b/ci/travis-centos-rhel8.sh
|
|
index a1502e15ee..cd0857fd29 100755
|
|
--- a/ci/travis-centos-rhel8.sh
|
|
+++ b/ci/travis-centos-rhel8.sh
|
|
@@ -15,7 +15,7 @@ CONT_NAME="${CONT_NAME:-centos-$CENTOS_RELEASE-$RANDOM}"
|
|
DOCKER_EXEC="${DOCKER_EXEC:-docker exec -it $CONT_NAME}"
|
|
DOCKER_RUN="${DOCKER_RUN:-docker run}"
|
|
REPO_ROOT="${REPO_ROOT:-$PWD}"
|
|
-ADDITIONAL_DEPS=(libasan libubsan net-tools strace nc e2fsprogs quota dnsmasq)
|
|
+ADDITIONAL_DEPS=(libasan libubsan net-tools strace nc e2fsprogs quota dnsmasq diffutils)
|
|
# RHEL8 options
|
|
CONFIGURE_OPTS=(
|
|
-Dsysvinit-path=/etc/rc.d/init.d
|
|
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..0d00754b5c
|
|
--- /dev/null
|
|
+++ b/test/TEST-38-FREEZER/test.sh
|
|
@@ -0,0 +1,53 @@
|
|
+#!/bin/bash
|
|
+set -e
|
|
+TEST_DESCRIPTION="test unit freezing and thawing via DBus and systemctl"
|
|
+TEST_NO_NSPAWN=1
|
|
+. $TEST_BASE_DIR/test-functions
|
|
+
|
|
+test_setup() {
|
|
+ create_empty_image
|
|
+ mkdir -p $TESTDIR/root
|
|
+ mount ${LOOPDEV}p1 $TESTDIR/root
|
|
+
|
|
+ (
|
|
+ LOG_LEVEL=5
|
|
+ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
|
|
+
|
|
+ setup_basic_environment
|
|
+ dracut_install tr cut timeout
|
|
+
|
|
+ # mask some services that we do not want to run in these tests
|
|
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
|
|
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service
|
|
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service
|
|
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket
|
|
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service
|
|
+ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service
|
|
+
|
|
+ # setup the testsuite service
|
|
+ cat >$initdir/etc/systemd/system/testsuite.service <<EOF
|
|
+[Unit]
|
|
+Description=Testsuite service
|
|
+
|
|
+[Service]
|
|
+ExecStart=/bin/bash -x /testsuite.sh
|
|
+Type=oneshot
|
|
+StandardOutput=tty
|
|
+StandardError=tty
|
|
+EOF
|
|
+ cat > $initdir/etc/systemd/system/testsuite-38-sleep.service << EOF
|
|
+[Service]
|
|
+ExecStart=/bin/sleep 3600
|
|
+EOF
|
|
+
|
|
+ cp testsuite.sh $initdir/
|
|
+ setup_testsuite
|
|
+ )
|
|
+ setup_nspawn_root
|
|
+
|
|
+ ddebug "umount $TESTDIR/root"
|
|
+ umount $TESTDIR/root
|
|
+}
|
|
+
|
|
+
|
|
+do_test "$@"
|
|
diff --git a/test/TEST-38-FREEZER/testsuite.sh b/test/TEST-38-FREEZER/testsuite.sh
|
|
new file mode 100755
|
|
index 0000000000..6fcadb8f8e
|
|
--- /dev/null
|
|
+++ b/test/TEST-38-FREEZER/testsuite.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
|