Merge pull request #7363 from poettering/success-action
Generalize FailureAction=, and add SuccessAction=
This commit is contained in:
commit
0b0c55fafd
8
TODO
8
TODO
|
@ -82,6 +82,14 @@ Features:
|
||||||
the quota of a the user indicated in User= via unit file settings, like the
|
the quota of a the user indicated in User= via unit file settings, like the
|
||||||
other resource management concepts. Would mix nicely with DynamicUser=1
|
other resource management concepts. Would mix nicely with DynamicUser=1
|
||||||
|
|
||||||
|
* Introduce "exit" as an EmergencyAction value, and allow to configure a
|
||||||
|
per-unit success/failure exit code to configure. This would be useful for
|
||||||
|
running commands inside of services inside of containers, which could then
|
||||||
|
propagate their failure state all the way up.
|
||||||
|
|
||||||
|
* In DynamicUser= mode: before selecting a UID, use disk quota APIs on relevant
|
||||||
|
disks to see if the UID is already in use.
|
||||||
|
|
||||||
* add dissect_image_warn() as a wrapper around dissect_image() that prints
|
* add dissect_image_warn() as a wrapper around dissect_image() that prints
|
||||||
friendly log messages for the returned errors, so that we don't have to
|
friendly log messages for the returned errors, so that we don't have to
|
||||||
duplicate that in nspawn, systemd-dissect and PID 1.
|
duplicate that in nspawn, systemd-dissect and PID 1.
|
||||||
|
|
|
@ -893,14 +893,6 @@
|
||||||
effect.</para></listitem>
|
effect.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><varname>FailureAction=</varname></term>
|
|
||||||
<listitem><para>Configure the action to take when the service enters a failed state. Takes the same values as
|
|
||||||
the unit setting <varname>StartLimitAction=</varname> and executes the same actions (see
|
|
||||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>). Defaults to
|
|
||||||
<option>none</option>. </para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>FileDescriptorStoreMax=</varname></term>
|
<term><varname>FileDescriptorStoreMax=</varname></term>
|
||||||
<listitem><para>Configure how many file descriptors may be stored in the service manager for the service using
|
<listitem><para>Configure how many file descriptors may be stored in the service manager for the service using
|
||||||
|
|
|
@ -877,11 +877,21 @@
|
||||||
semantics. Defaults to <option>none</option>.</para></listitem>
|
semantics. Defaults to <option>none</option>.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>FailureAction=</varname></term>
|
||||||
|
<term><varname>SuccessAction=</varname></term>
|
||||||
|
<listitem><para>Configure the action to take when the unit stops and enters a failed state or inactive
|
||||||
|
state. Takes the same values as the setting <varname>StartLimitAction=</varname> setting and executes the same
|
||||||
|
actions (see
|
||||||
|
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>). Both options
|
||||||
|
default to <option>none</option>.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>RebootArgument=</varname></term>
|
<term><varname>RebootArgument=</varname></term>
|
||||||
<listitem><para>Configure the optional argument for the
|
<listitem><para>Configure the optional argument for the
|
||||||
<citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call if
|
<citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call if
|
||||||
<varname>StartLimitAction=</varname> or a service's <varname>FailureAction=</varname> is a reboot action. This
|
<varname>StartLimitAction=</varname> or <varname>FailureAction=</varname> is a reboot action. This
|
||||||
works just like the optional argument to <command>systemctl reboot</command> command.</para></listitem>
|
works just like the optional argument to <command>systemctl reboot</command> command.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,6 @@ const sd_bus_vtable bus_service_vtable[] = {
|
||||||
SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
|
BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
|
||||||
SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Service, emergency_action), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
||||||
SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
|
@ -82,6 +81,7 @@ const sd_bus_vtable bus_service_vtable[] = {
|
||||||
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
||||||
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
||||||
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
||||||
|
SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
||||||
SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
|
||||||
SD_BUS_VTABLE_END
|
SD_BUS_VTABLE_END
|
||||||
};
|
};
|
||||||
|
|
|
@ -798,6 +798,8 @@ const sd_bus_vtable bus_unit_vtable[] = {
|
||||||
SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
|
SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
|
SD_BUS_PROPERTY("SuccessAction", "s", property_get_emergency_action, offsetof(Unit, success_action), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0),
|
SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0),
|
||||||
SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
|
SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
|
||||||
|
@ -1470,6 +1472,30 @@ static int bus_unit_set_transient_property(
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
} else if (STR_IN_SET(name, "FailureAction", "SuccessAction")) {
|
||||||
|
EmergencyAction action;
|
||||||
|
const char *s;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "s", &s);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
action = emergency_action_from_string(s);
|
||||||
|
if (action < 0)
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid emergency action: %s", s);
|
||||||
|
|
||||||
|
if (mode != UNIT_CHECK) {
|
||||||
|
|
||||||
|
if (streq(name, "FailureAction"))
|
||||||
|
u->failure_action = action;
|
||||||
|
else
|
||||||
|
u->success_action = action;
|
||||||
|
|
||||||
|
unit_write_drop_in_format(u, mode, name, "%s=%s", name, emergency_action_to_string(action));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
} else if (streq(name, "AddRef")) {
|
} else if (streq(name, "AddRef")) {
|
||||||
|
|
||||||
int b;
|
int b;
|
||||||
|
|
|
@ -223,6 +223,8 @@ m4_dnl The following is a legacy alias name for compatibility
|
||||||
Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
||||||
Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
|
Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
|
||||||
Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
|
Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
|
||||||
|
Unit.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action)
|
||||||
|
Unit.SuccessAction, config_parse_emergency_action, 0, offsetof(Unit, success_action)
|
||||||
Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
|
Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
|
||||||
Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
|
Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions)
|
||||||
Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
|
Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions)
|
||||||
|
@ -281,12 +283,12 @@ Service.TimeoutStartSec, config_parse_service_timeout, 0,
|
||||||
Service.TimeoutStopSec, config_parse_service_timeout, 0, 0
|
Service.TimeoutStopSec, config_parse_service_timeout, 0, 0
|
||||||
Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
|
Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec)
|
||||||
Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
|
Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec)
|
||||||
m4_dnl The following three only exist for compatibility, they moved into Unit, see above
|
m4_dnl The following five only exist for compatibility, they moved into Unit, see above
|
||||||
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval)
|
||||||
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
|
Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst)
|
||||||
Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
|
Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action)
|
||||||
|
Service.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action)
|
||||||
Service.RebootArgument, config_parse_unit_path_printf, 0, offsetof(Unit, reboot_arg)
|
Service.RebootArgument, config_parse_unit_path_printf, 0, offsetof(Unit, reboot_arg)
|
||||||
Service.FailureAction, config_parse_emergency_action, 0, offsetof(Service, emergency_action)
|
|
||||||
Service.Type, config_parse_service_type, 0, offsetof(Service, type)
|
Service.Type, config_parse_service_type, 0, offsetof(Service, type)
|
||||||
Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
|
Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart)
|
||||||
Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only)
|
Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only)
|
||||||
|
|
|
@ -1532,9 +1532,6 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
||||||
|
|
||||||
service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD);
|
service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD);
|
||||||
|
|
||||||
if (s->result != SERVICE_SUCCESS)
|
|
||||||
emergency_action(UNIT(s)->manager, s->emergency_action, UNIT(s)->reboot_arg, "service failed");
|
|
||||||
|
|
||||||
if (allow_restart && service_shall_restart(s)) {
|
if (allow_restart && service_shall_restart(s)) {
|
||||||
|
|
||||||
r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec));
|
r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec));
|
||||||
|
|
|
@ -174,8 +174,6 @@ struct Service {
|
||||||
char *status_text;
|
char *status_text;
|
||||||
int status_errno;
|
int status_errno;
|
||||||
|
|
||||||
EmergencyAction emergency_action;
|
|
||||||
|
|
||||||
UnitRef accept_socket;
|
UnitRef accept_socket;
|
||||||
|
|
||||||
sd_event_source *timer_event_source;
|
sd_event_source *timer_event_source;
|
||||||
|
|
|
@ -1181,6 +1181,11 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
||||||
STRV_FOREACH(j, u->dropin_paths)
|
STRV_FOREACH(j, u->dropin_paths)
|
||||||
fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
|
fprintf(f, "%s\tDropIn Path: %s\n", prefix, *j);
|
||||||
|
|
||||||
|
if (u->failure_action != EMERGENCY_ACTION_NONE)
|
||||||
|
fprintf(f, "%s\tFailure Action: %s\n", prefix, emergency_action_to_string(u->failure_action));
|
||||||
|
if (u->success_action != EMERGENCY_ACTION_NONE)
|
||||||
|
fprintf(f, "%s\tSuccess Action: %s\n", prefix, emergency_action_to_string(u->success_action));
|
||||||
|
|
||||||
if (u->job_timeout != USEC_INFINITY)
|
if (u->job_timeout != USEC_INFINITY)
|
||||||
fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
|
fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
|
||||||
|
|
||||||
|
@ -2503,6 +2508,11 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su
|
||||||
* units go directly from starting to inactive,
|
* units go directly from starting to inactive,
|
||||||
* without ever entering started.) */
|
* without ever entering started.) */
|
||||||
unit_check_binds_to(u);
|
unit_check_binds_to(u);
|
||||||
|
|
||||||
|
if (os != UNIT_FAILED && ns == UNIT_FAILED)
|
||||||
|
(void) emergency_action(u->manager, u->failure_action, u->reboot_arg, "unit failed");
|
||||||
|
else if (!UNIT_IS_INACTIVE_OR_FAILED(os) && ns == UNIT_INACTIVE)
|
||||||
|
(void) emergency_action(u->manager, u->success_action, u->reboot_arg, "unit succeeded");
|
||||||
}
|
}
|
||||||
|
|
||||||
unit_add_to_dbus_queue(u);
|
unit_add_to_dbus_queue(u);
|
||||||
|
|
|
@ -248,6 +248,9 @@ struct Unit {
|
||||||
/* Put a ratelimit on unit starting */
|
/* Put a ratelimit on unit starting */
|
||||||
RateLimit start_limit;
|
RateLimit start_limit;
|
||||||
EmergencyAction start_limit_action;
|
EmergencyAction start_limit_action;
|
||||||
|
|
||||||
|
EmergencyAction failure_action;
|
||||||
|
EmergencyAction success_action;
|
||||||
char *reboot_arg;
|
char *reboot_arg;
|
||||||
|
|
||||||
/* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */
|
/* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */
|
||||||
|
|
|
@ -408,7 +408,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
||||||
"RootDirectory", "SyslogIdentifier", "ProtectSystem",
|
"RootDirectory", "SyslogIdentifier", "ProtectSystem",
|
||||||
"ProtectHome", "SELinuxContext", "Restart", "RootImage",
|
"ProtectHome", "SELinuxContext", "Restart", "RootImage",
|
||||||
"NotifyAccess", "RuntimeDirectoryPreserve", "Personality",
|
"NotifyAccess", "RuntimeDirectoryPreserve", "Personality",
|
||||||
"KeyringMode", "CollectMode"))
|
"KeyringMode", "CollectMode", "FailureAction", "SuccessAction"))
|
||||||
r = sd_bus_message_append(m, "v", "s", eq);
|
r = sd_bus_message_append(m, "v", "s", eq);
|
||||||
|
|
||||||
else if (streq(field, "StandardInputData")) {
|
else if (streq(field, "StandardInputData")) {
|
||||||
|
|
4
test/TEST-18-FAILUREACTION/Makefile
Normal file
4
test/TEST-18-FAILUREACTION/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
include ../Makefile.guess
|
||||||
|
|
||||||
|
all setup clean run:
|
||||||
|
@basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
|
42
test/TEST-18-FAILUREACTION/test.sh
Executable file
42
test/TEST-18-FAILUREACTION/test.sh
Executable file
|
@ -0,0 +1,42 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
||||||
|
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||||
|
set -e
|
||||||
|
TEST_DESCRIPTION="FailureAction= operation"
|
||||||
|
|
||||||
|
. $TEST_BASE_DIR/test-functions
|
||||||
|
QEMU_TIMEOUT=180
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
cp testsuite.sh $initdir/
|
||||||
|
|
||||||
|
setup_testsuite
|
||||||
|
) || return 1
|
||||||
|
setup_nspawn_root
|
||||||
|
|
||||||
|
ddebug "umount $TESTDIR/root"
|
||||||
|
umount $TESTDIR/root
|
||||||
|
}
|
||||||
|
|
||||||
|
do_test "$@"
|
18
test/TEST-18-FAILUREACTION/testsuite.sh
Executable file
18
test/TEST-18-FAILUREACTION/testsuite.sh
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
|
||||||
|
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||||
|
set -ex
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
systemd-run --wait -p FailureAction=poweroff true
|
||||||
|
! systemd-run --wait -p SuccessAction=poweroff false
|
||||||
|
|
||||||
|
if test -f /firstphase ; then
|
||||||
|
echo OK > /firstphase
|
||||||
|
systemd-run --wait -p SuccessAction=reboot true
|
||||||
|
else
|
||||||
|
echo OK > /testok
|
||||||
|
systemd-run --wait -p FailureAction=poweroff false
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep infinity
|
|
@ -21,7 +21,7 @@ if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
|
||||||
ROOTLIBDIR=/usr/lib/systemd
|
ROOTLIBDIR=/usr/lib/systemd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
BASICTOOLS="sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm"
|
BASICTOOLS="sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false"
|
||||||
DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find"
|
DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find"
|
||||||
|
|
||||||
STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))"
|
STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))"
|
||||||
|
|
Loading…
Reference in a new issue