From: Lennart Poettering Date: Thu, 16 Nov 2017 14:18:01 +0000 (+0100) Subject: core: introduce SuccessAction= as unit file property X-Git-Tag: v236~159^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e7dfbb4e7414fdea57fd0ff7ad20585295b6e1b0;p=platform%2Fupstream%2Fsystemd.git core: introduce SuccessAction= as unit file property SuccessAction= is similar to FailureAction= but declares what to do on success of a unit, rather than on failure. This is useful for running commands in qemu/nspawn images, that shall power down on completion. We frequently see "ExecStopPost=/usr/bin/systemctl poweroff" or so in unit files like this. Offer a simple, more declarative alternative for this. While we are at it, hook up failure action with unit_dump() and transient units too. --- diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 6e9cdae..9c40562 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -879,10 +879,12 @@ FailureAction= - Configure the action to take when the unit enters the failed state. Takes the same values as - the setting StartLimitAction= setting and executes the same actions (see - systemd.unit5). Defaults to - . + SuccessAction= + Configure the action to take when the unit stops and enters a failed state or inactive + state. Takes the same values as the setting StartLimitAction= setting and executes the same + actions (see + systemd.unit5). Both options + default to . diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 5344183..d4bdf17 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -799,6 +799,7 @@ const sd_bus_vtable bus_unit_vtable[] = { 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("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("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), @@ -1471,6 +1472,30 @@ static int bus_unit_set_transient_property( 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")) { int b; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 5fc3371..716145a 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -224,6 +224,7 @@ Unit.StartLimitInterval, config_parse_sec, 0, Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst) 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.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) diff --git a/src/core/unit.c b/src/core/unit.c index 07656c1..386238a 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -1181,6 +1181,11 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { STRV_FOREACH(j, u->dropin_paths) 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) fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0)); @@ -2506,6 +2511,8 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su 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); diff --git a/src/core/unit.h b/src/core/unit.h index d3403cb..ae3dcfa 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -250,6 +250,7 @@ struct Unit { EmergencyAction start_limit_action; EmergencyAction failure_action; + EmergencyAction success_action; char *reboot_arg; /* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */ diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index a607233..78b9a68 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -408,7 +408,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "RootDirectory", "SyslogIdentifier", "ProtectSystem", "ProtectHome", "SELinuxContext", "Restart", "RootImage", "NotifyAccess", "RuntimeDirectoryPreserve", "Personality", - "KeyringMode", "CollectMode")) + "KeyringMode", "CollectMode", "FailureAction", "SuccessAction")) r = sd_bus_message_append(m, "v", "s", eq); else if (streq(field, "StandardInputData")) {