summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-07-17 00:58:47 +0200
committerLennart Poettering <lennart@poettering.net>2010-07-17 00:58:47 +0200
commit5de9682cd647f07f043254fde70e62e1aa837476 (patch)
treebe788640f3b80c89da3a39f75884b3bf8469878d
parent45fb0699c45d2e042e04a53e3ea00501e3f65f59 (diff)
unit: introduce OnFailure dependencies to activate units on failure of other units, as a way to implement an automatic rescue shell
-rw-r--r--src/dbus-unit.h2
-rw-r--r--src/unit.c34
-rw-r--r--src/unit.h3
3 files changed, 28 insertions, 11 deletions
diff --git a/src/dbus-unit.h b/src/dbus-unit.h
index d4af5a8b23..e93d65892a 100644
--- a/src/dbus-unit.h
+++ b/src/dbus-unit.h
@@ -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 }, \
diff --git a/src/unit.c b/src/unit.c
index e46182adad..44dc811630 100644
--- a/src/unit.c
+++ b/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);
diff --git a/src/unit.h b/src/unit.h
index d3a00797f9..55fe0fa60e 100644
--- a/src/unit.h
+++ b/src/unit.h
@@ -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,