feature to honor first shutdown request to completion

Create unit tests per established norm at position 52

check in_set first before getting unit
This commit is contained in:
Jay Burger 2020-04-10 16:38:42 -05:00 committed by Zbigniew Jędrzejewski-Szmek
parent 7bf6babfa2
commit a1ba8c5b71
9 changed files with 109 additions and 11 deletions

View File

@ -12,6 +12,18 @@
#include "terminal-util.h"
#include "virt.h"
static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
[EMERGENCY_ACTION_NONE] = "none",
[EMERGENCY_ACTION_REBOOT] = "reboot",
[EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
[EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
[EMERGENCY_ACTION_POWEROFF] = "poweroff",
[EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
[EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
[EMERGENCY_ACTION_EXIT] = "exit",
[EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
};
static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) {
log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason);
if (warn)
@ -28,10 +40,22 @@ void emergency_action(
int exit_status,
const char *reason) {
Unit *u;
assert(m);
assert(action >= 0);
assert(action < _EMERGENCY_ACTION_MAX);
/* Is the special shutdown target active or queued? If so, we are in shutdown state */
if (IN_SET(action, EMERGENCY_ACTION_REBOOT, EMERGENCY_ACTION_POWEROFF, EMERGENCY_ACTION_EXIT)) {
u = manager_get_unit(m, SPECIAL_SHUTDOWN_TARGET);
if (u && unit_active_or_pending(u)) {
log_notice("Shutdown is already active. Skipping emergency action request %s.",
emergency_action_table[action]);
return;
}
}
if (action == EMERGENCY_ACTION_NONE)
return;
@ -126,17 +150,6 @@ void emergency_action(
}
}
static const char* const emergency_action_table[_EMERGENCY_ACTION_MAX] = {
[EMERGENCY_ACTION_NONE] = "none",
[EMERGENCY_ACTION_REBOOT] = "reboot",
[EMERGENCY_ACTION_REBOOT_FORCE] = "reboot-force",
[EMERGENCY_ACTION_REBOOT_IMMEDIATE] = "reboot-immediate",
[EMERGENCY_ACTION_POWEROFF] = "poweroff",
[EMERGENCY_ACTION_POWEROFF_FORCE] = "poweroff-force",
[EMERGENCY_ACTION_POWEROFF_IMMEDIATE] = "poweroff-immediate",
[EMERGENCY_ACTION_EXIT] = "exit",
[EMERGENCY_ACTION_EXIT_FORCE] = "exit-force",
};
DEFINE_STRING_TABLE_LOOKUP(emergency_action, EmergencyAction);
int parse_emergency_action(

View File

@ -0,0 +1,16 @@
BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
all setup run clean clean-again:
@basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
# finish option is used to run checks that can only be run outside of
# the test execution. Example case, honor first shutdown, proof is obtained
# from the console output as the image shuts down. This does not show up in
# the journal so the output from the do_test is captured in a file in /tmp.
# Without the use of finish the test will still pass because if it fails
# the test will loop and will be terminated via a command timeout.
# This just provides concrete confirmation.
finish:
@basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./fini.sh --$@
.PHONY: all setup run clean clean-again

View File

@ -0,0 +1,10 @@
#!/bin/bash
TEST_DESCRIPTION="test honor first shutdown"
if grep -q "Shutdown is already active. Skipping emergency action request" /tmp/honorfirstshutdown.log; then
echo "$TEST_DESCRIPTION [pass]"
exit 0
else
echo "$TEST_DESCRIPTION [fail]"
exit 1
fi

View File

@ -0,0 +1,19 @@
#!/bin/bash
set -e
. $TEST_BASE_DIR/test-functions
TEST_REQUIRE_INSTALL_TESTS=0
TEST_DESCRIPTION="testing honor first shutdown"
#INTERACTIVE_DEBUG=1
TEST_NO_QEMU=1
#Using timeout because if the test fails it can loop.
# The reason is because the poweroff executed by end.service
# could turn into a reboot if the test fails.
NSPAWN_TIMEOUT=20
#Remove this file if it exists. this is used along with
# the make target "finish". Since concrete confirmaion is
# only found from the console during the poweroff.
rm -f /tmp/honorfirstshutdown.log >/dev/null
do_test "$@" 52 > /tmp/honorfirstshutdown.log

View File

@ -28,6 +28,8 @@ install_subdir('testsuite-28.units',
install_dir : testdata_dir)
install_subdir('testsuite-30.units',
install_dir : testdata_dir)
install_subdir('testsuite-52.units',
install_dir : testdata_dir)
testsuite08_dir = testdata_dir + '/testsuite-08.units'
install_data('testsuite-08.units/-.mount',

View File

@ -0,0 +1,6 @@
[Unit]
Description=Testsuite service
[Service]
ExecStart=/usr/lib/systemd/tests/testdata/%N.units/%N.sh
Type=oneshot

View File

@ -0,0 +1,18 @@
#!/bin/bash
set -ex
set -o pipefail
if ! test -x /usr/lib/systemd/tests/testdata/units/test-honor-first-shutdown.sh ; then
echo "honor-first-shutdown script not found - FAIL" > /testok
exit 0
fi
systemd-analyze log-level debug
systemd-analyze log-target console
systemctl enable test-honor-first-shutdown.service
systemctl start test-honor-first-shutdown.service
echo OK > /testok
exit 0

View File

@ -0,0 +1,11 @@
[Unit]
Description=Honor First Shutdown feature
After=multi-user.target
[Service]
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
ExecStop=sh -c 'kill -SIGKILL $MAINPID'
FailureAction=reboot
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,3 @@
#!/bin/bash
echo "Honor first shutdown test script"
sleep infinity;