diff options
-rw-r--r-- | device.c | 1 | ||||
-rw-r--r-- | job.c | 3 | ||||
-rw-r--r-- | job.h | 1 | ||||
-rw-r--r-- | manager.c | 49 | ||||
-rw-r--r-- | mount.c | 1 | ||||
-rw-r--r-- | systemctl.vala | 17 | ||||
-rw-r--r-- | unit.h | 3 |
7 files changed, 70 insertions, 5 deletions
@@ -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, @@ -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); @@ -65,6 +65,7 @@ enum JobState { enum JobMode { JOB_FAIL, JOB_REPLACE, + JOB_ISOLATE, _JOB_MODE_MAX, _JOB_MODE_INVALID = -1 }; @@ -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; @@ -1462,6 +1462,7 @@ const UnitVTable mount_vtable = { .no_alias = true, .no_instances = true, + .no_isolate = true, .init = mount_init, .load = mount_load, diff --git a/systemctl.vala b/systemctl.vala index a0237bb734..feacdb2b7b 100644 --- a/systemctl.vala +++ b/systemctl.vala @@ -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(); @@ -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]; |