chiark / gitweb /
manager: introduce 'isolate' job mode which kills all units but the requested one
authorLennart Poettering <lennart@poettering.net>
Thu, 22 Apr 2010 00:42:59 +0000 (02:42 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 22 Apr 2010 00:42:59 +0000 (02:42 +0200)
device.c
job.c
job.h
manager.c
mount.c
systemctl.vala
unit.h

index a65d417..520cbdb 100644 (file)
--- a/device.c
+++ b/device.c
@@ -433,6 +433,7 @@ const UnitVTable device_vtable = {
         .no_requires = true,
         .no_instances = true,
         .no_snapshots = true,
+        .no_isolate = true,
 
         .load = unit_load_fragment_and_dropin_optional,
         .done = device_done,
diff --git a/job.c b/job.c
index 3210bb4..f35c91c 100644 (file)
--- a/job.c
+++ b/job.c
@@ -577,7 +577,8 @@ DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
 
 static const char* const job_mode_table[_JOB_MODE_MAX] = {
         [JOB_FAIL] = "fail",
-        [JOB_REPLACE] = "replace"
+        [JOB_REPLACE] = "replace",
+        [JOB_ISOLATE] = "isolate"
 };
 
 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
diff --git a/job.h b/job.h
index e8857ed..1ae97b7 100644 (file)
--- a/job.h
+++ b/job.h
@@ -65,6 +65,7 @@ enum JobState {
 enum JobMode {
         JOB_FAIL,
         JOB_REPLACE,
+        JOB_ISOLATE,
         _JOB_MODE_MAX,
         _JOB_MODE_INVALID = -1
 };
index 5cb5c3d..3ac0177 100644 (file)
--- a/manager.c
+++ b/manager.c
@@ -1004,7 +1004,7 @@ static void transaction_collect_garbage(Manager *m) {
         } while (again);
 }
 
-static int transaction_is_destructive(Manager *m, JobMode mode) {
+static int transaction_is_destructive(Manager *m) {
         Iterator i;
         Job *j;
 
@@ -1083,7 +1083,7 @@ static void transaction_minimize_impact(Manager *m) {
         } while (again);
 }
 
-static int transaction_apply(Manager *m, JobMode mode) {
+static int transaction_apply(Manager *m) {
         Iterator i;
         Job *j;
         int r;
@@ -1203,13 +1203,13 @@ static int transaction_activate(Manager *m, JobMode mode) {
 
         /* Ninth step: check whether we can actually apply this */
         if (mode == JOB_FAIL)
-                if ((r = transaction_is_destructive(m, mode)) < 0) {
+                if ((r = transaction_is_destructive(m)) < 0) {
                         log_debug("Requested transaction contradicts existing jobs: %s", strerror(-r));
                         goto rollback;
                 }
 
         /* Tenth step: apply changes */
-        if ((r = transaction_apply(m, mode)) < 0) {
+        if ((r = transaction_apply(m)) < 0) {
                 log_debug("Failed to apply transaction: %s", strerror(-r));
                 goto rollback;
         }
@@ -1383,6 +1383,38 @@ fail:
         return r;
 }
 
+static int transaction_add_isolate_jobs(Manager *m) {
+        Iterator i;
+        Unit *u;
+        char *k;
+        int r;
+
+        assert(m);
+
+        HASHMAP_FOREACH_KEY(u, k, m->units, i) {
+
+                /* ignore aliases */
+                if (u->meta.id != k)
+                        continue;
+
+                if (UNIT_VTABLE(u)->no_isolate)
+                        continue;
+
+                /* No need to stop inactive jobs */
+                if (unit_active_state(u) == UNIT_INACTIVE)
+                        continue;
+
+                /* Is there already something listed for this? */
+                if (hashmap_get(m->transaction_jobs, u))
+                        continue;
+
+                if ((r = transaction_add_job_and_dependencies(m, JOB_STOP, u, NULL, true, false, NULL)) < 0)
+                        log_warning("Cannot add isolate job for unit %s, ignoring: %s", u->meta.id, strerror(-r));
+        }
+
+        return 0;
+}
+
 int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool override, Job **_ret) {
         int r;
         Job *ret;
@@ -1392,6 +1424,9 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove
         assert(unit);
         assert(mode < _JOB_MODE_MAX);
 
+        if (mode == JOB_ISOLATE && type != JOB_START)
+                return -EINVAL;
+
         log_debug("Trying to enqueue job %s/%s", unit->meta.id, job_type_to_string(type));
 
         if ((r = transaction_add_job_and_dependencies(m, type, unit, NULL, true, override, &ret)) < 0) {
@@ -1399,6 +1434,12 @@ int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, bool ove
                 return r;
         }
 
+        if (mode == JOB_ISOLATE)
+                if ((r = transaction_add_isolate_jobs(m)) < 0) {
+                        transaction_abort(m);
+                        return r;
+                }
+
         if ((r = transaction_activate(m, mode)) < 0)
                 return r;
 
diff --git a/mount.c b/mount.c
index 15cce6f..3cb4cf2 100644 (file)
--- a/mount.c
+++ b/mount.c
@@ -1462,6 +1462,7 @@ const UnitVTable mount_vtable = {
 
         .no_alias = true,
         .no_instances = true,
+        .no_isolate = true,
 
         .init = mount_init,
         .load = mount_load,
index a0237bb..feacdb2 100644 (file)
@@ -81,6 +81,7 @@ int main (string[] args) {
                         "  cancel [JOB...]     Cancel one or more jobs\n" +
                         "  start [NAME...]     Start on or more units\n" +
                         "  stop [NAME...]      Stop on or more units\n" +
+                        "  enter [NAME]        Start one unit and stop all others\n" +
                         "  restart [NAME...]   Restart on or more units\n" +
                         "  reload [NAME...]    Reload on or more units\n" +
                         "  monitor             Monitor unit/job changes\n" +
@@ -214,6 +215,22 @@ int main (string[] args) {
                                         u.reload(mode);
                         }
 
+                } else if (args[1] == "isolate") {
+
+                        if (args.length != 3) {
+                                stderr.printf("Missing argument.\n");
+                                return 1;
+                        }
+
+                        ObjectPath p = manager.get_unit(args[2]);
+
+                        Unit u = bus.get_object(
+                                        "org.freedesktop.systemd1",
+                                        p,
+                                        "org.freedesktop.systemd1.Unit") as Unit;
+
+                        u.start("isolate");
+
                 } else if (args[1] == "monitor") {
 
                         manager.subscribe();
diff --git a/unit.h b/unit.h
index 9155b2e..21627ef 100644 (file)
--- a/unit.h
+++ b/unit.h
@@ -306,6 +306,9 @@ struct UnitVTable {
 
         /* Exclude from automatic gc */
         bool no_gc:1;
+
+        /* Exclude from isolation requests */
+        bool no_isolate:1;
 };
 
 extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];