unit: introduce OnFailure dependencies to activate units on failure of other units, as a way to implement an automatic rescue shell
This commit is contained in:
parent
45fb0699c4
commit
5de9682cd6
|
@ -70,6 +70,7 @@
|
|||
" <property name=\"Conflicts\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"Before\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"After\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"OnFailure\" type=\"as\" access=\"read\"/>\n" \
|
||||
" <property name=\"Description\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"LoadState\" type=\"s\" access=\"read\"/>\n" \
|
||||
" <property name=\"ActiveState\" type=\"s\" access=\"read\"/>\n" \
|
||||
|
@ -105,6 +106,7 @@
|
|||
{ "org.freedesktop.systemd1.Unit", "Conflicts", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_CONFLICTS] }, \
|
||||
{ "org.freedesktop.systemd1.Unit", "Before", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_BEFORE] }, \
|
||||
{ "org.freedesktop.systemd1.Unit", "After", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_AFTER] }, \
|
||||
{ "org.freedesktop.systemd1.Unit", "OnFailure", bus_unit_append_dependencies, "as", u->meta.dependencies[UNIT_ON_FAILURE] }, \
|
||||
{ "org.freedesktop.systemd1.Unit", "Description", bus_unit_append_description, "s", u }, \
|
||||
{ "org.freedesktop.systemd1.Unit", "LoadState", bus_unit_append_load_state, "s", &u->meta.load_state }, \
|
||||
{ "org.freedesktop.systemd1.Unit", "ActiveState", bus_unit_append_active_state, "s", u }, \
|
||||
|
|
34
src/unit.c
34
src/unit.c
|
@ -987,9 +987,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
|
|||
else if (UNIT_IS_ACTIVE_OR_RELOADING(os) && !UNIT_IS_ACTIVE_OR_RELOADING(ns))
|
||||
u->meta.active_exit_timestamp = ts;
|
||||
|
||||
if (ns != os && ns == UNIT_MAINTENANCE)
|
||||
log_notice("Unit %s entered maintenance state.", u->meta.id);
|
||||
|
||||
if (UNIT_IS_INACTIVE_OR_MAINTENANCE(ns))
|
||||
cgroup_bonding_trim_list(u->meta.cgroup_bondings, true);
|
||||
|
||||
|
@ -1072,6 +1069,16 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns) {
|
|||
retroactively_stop_dependencies(u);
|
||||
}
|
||||
|
||||
if (ns != os && ns == UNIT_MAINTENANCE) {
|
||||
Iterator i;
|
||||
Unit *other;
|
||||
|
||||
SET_FOREACH(other, u->meta.dependencies[UNIT_ON_FAILURE], i)
|
||||
manager_add_job(u->meta.manager, JOB_START, other, JOB_REPLACE, true, NULL, NULL);
|
||||
|
||||
log_notice("Unit %s entered maintenance state.", u->meta.id);
|
||||
}
|
||||
|
||||
/* Some names are special */
|
||||
if (UNIT_IS_ACTIVE_OR_RELOADING(ns)) {
|
||||
if (unit_has_name(u, SPECIAL_DBUS_SERVICE)) {
|
||||
|
@ -1294,6 +1301,7 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
|
|||
[UNIT_CONFLICTS] = UNIT_CONFLICTS,
|
||||
[UNIT_BEFORE] = UNIT_AFTER,
|
||||
[UNIT_AFTER] = UNIT_BEFORE,
|
||||
[UNIT_ON_FAILURE] = _UNIT_DEPENDENCY_INVALID,
|
||||
[UNIT_REFERENCES] = UNIT_REFERENCED_BY,
|
||||
[UNIT_REFERENCED_BY] = UNIT_REFERENCES
|
||||
};
|
||||
|
@ -1301,7 +1309,6 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
|
|||
|
||||
assert(u);
|
||||
assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX);
|
||||
assert(inverse_table[d] != _UNIT_DEPENDENCY_INVALID);
|
||||
assert(other);
|
||||
|
||||
/* We won't allow dependencies on ourselves. We will not
|
||||
|
@ -1317,10 +1324,13 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((r = set_ensure_allocated(&u->meta.dependencies[d], trivial_hash_func, trivial_compare_func)) < 0 ||
|
||||
(r = set_ensure_allocated(&other->meta.dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0)
|
||||
if ((r = set_ensure_allocated(&u->meta.dependencies[d], trivial_hash_func, trivial_compare_func)) < 0)
|
||||
return r;
|
||||
|
||||
if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
|
||||
if ((r = set_ensure_allocated(&other->meta.dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0)
|
||||
return r;
|
||||
|
||||
if (add_reference)
|
||||
if ((r = set_ensure_allocated(&u->meta.dependencies[UNIT_REFERENCES], trivial_hash_func, trivial_compare_func)) < 0 ||
|
||||
(r = set_ensure_allocated(&other->meta.dependencies[UNIT_REFERENCED_BY], trivial_hash_func, trivial_compare_func)) < 0)
|
||||
|
@ -1329,10 +1339,11 @@ int unit_add_dependency(Unit *u, UnitDependency d, Unit *other, bool add_referen
|
|||
if ((q = set_put(u->meta.dependencies[d], other)) < 0)
|
||||
return q;
|
||||
|
||||
if ((v = set_put(other->meta.dependencies[inverse_table[d]], u)) < 0) {
|
||||
r = v;
|
||||
goto fail;
|
||||
}
|
||||
if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID)
|
||||
if ((v = set_put(other->meta.dependencies[inverse_table[d]], u)) < 0) {
|
||||
r = v;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (add_reference) {
|
||||
if ((w = set_put(u->meta.dependencies[UNIT_REFERENCES], other)) < 0) {
|
||||
|
@ -2097,7 +2108,8 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = {
|
|||
[UNIT_BEFORE] = "Before",
|
||||
[UNIT_AFTER] = "After",
|
||||
[UNIT_REFERENCES] = "References",
|
||||
[UNIT_REFERENCED_BY] = "ReferencedBy"
|
||||
[UNIT_REFERENCED_BY] = "ReferencedBy",
|
||||
[UNIT_ON_FAILURE] = "OnFailure"
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);
|
||||
|
|
|
@ -114,6 +114,9 @@ enum UnitDependency {
|
|||
UNIT_BEFORE, /* inverse of 'before' is 'after' and vice versa */
|
||||
UNIT_AFTER,
|
||||
|
||||
/* On Failure */
|
||||
UNIT_ON_FAILURE,
|
||||
|
||||
/* Reference information for GC logic */
|
||||
UNIT_REFERENCES, /* Inverse of 'references' is 'referenced_by' */
|
||||
UNIT_REFERENCED_BY,
|
||||
|
|
Loading…
Reference in New Issue