From 89f7c8465cd1ab37347dd0c15920bce31e8225df Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 11 Feb 2014 17:15:38 +0100 Subject: machined: optionally, allow registration of pre-existing units (scopes or services) as machine with machined --- src/machine/machine-dbus.c | 3 +- src/machine/machine.c | 57 +++++++++++++++++++++++++++----------- src/machine/machine.h | 2 +- src/machine/machinectl.c | 16 +++++------ src/machine/machined-dbus.c | 67 +++++++++++++++++++++++++++++++++++++++------ 5 files changed, 110 insertions(+), 35 deletions(-) (limited to 'src/machine') diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index 90eb001bb1..df96ccf9d4 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -132,7 +132,8 @@ const sd_bus_vtable machine_vtable[] = { SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, scope), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/machine/machine.c b/src/machine/machine.c index 0791ba8a9a..e45c443495 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -76,9 +76,9 @@ void machine_free(Machine *m) { if (m->in_gc_queue) LIST_REMOVE(gc_queue, m->manager->machine_gc_queue, m); - if (m->scope) { - hashmap_remove(m->manager->machine_units, m->scope); - free(m->scope); + if (m->unit) { + hashmap_remove(m->manager->machine_units, m->unit); + free(m->unit); } free(m->scope_job); @@ -123,8 +123,8 @@ int machine_save(Machine *m) { "NAME=%s\n", m->name); - if (m->scope) - fprintf(f, "SCOPE=%s\n", m->scope); + if (m->unit) + fprintf(f, "SCOPE=%s\n", m->unit); /* We continue to call this "SCOPE=" because it is internal only, and we want to stay compatible with old files */ if (m->scope_job) fprintf(f, "SCOPE_JOB=%s\n", m->scope_job); @@ -159,6 +159,16 @@ int machine_save(Machine *m) { unlink(temp_path); } + if (m->unit) { + char *sl; + + /* Create a symlink from the unit name to the machine + * name, so that we can quickly find the machine for + * each given unit */ + sl = strappenda("/run/systemd/machines/unit:", m->unit); + symlink(m->name, sl); + } + finish: if (r < 0) log_error("Failed to save machine data %s: %s", m->state_file, strerror(-r)); @@ -166,6 +176,21 @@ finish: return r; } +static void machine_unlink(Machine *m) { + assert(m); + + if (m->unit) { + + char *sl; + + sl = strappenda("/run/systemd/machines/unit:", m->unit); + unlink(sl); + } + + if (m->state_file) + unlink(m->state_file); +} + int machine_load(Machine *m) { _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *id = NULL, *leader = NULL, *class = NULL; int r; @@ -173,7 +198,7 @@ int machine_load(Machine *m) { assert(m); r = parse_env_file(m->state_file, NEWLINE, - "SCOPE", &m->scope, + "SCOPE", &m->unit, "SCOPE_JOB", &m->scope_job, "SERVICE", &m->service, "ROOT", &m->root_directory, @@ -225,7 +250,7 @@ static int machine_start_scope(Machine *m, sd_bus_message *properties, sd_bus_er assert(m); - if (!m->scope) { + if (!m->unit) { _cleanup_free_ char *escaped = NULL; char *scope, *description, *job; @@ -245,15 +270,15 @@ static int machine_start_scope(Machine *m, sd_bus_message *properties, sd_bus_er free(scope); return r; } else { - m->scope = scope; + m->unit = scope; free(m->scope_job); m->scope_job = job; } } - if (m->scope) - hashmap_put(m->manager->machine_units, m->scope, m); + if (m->unit) + hashmap_put(m->manager->machine_units, m->unit, m); return r; } @@ -302,10 +327,10 @@ static int machine_stop_scope(Machine *m) { assert(m); - if (!m->scope) + if (!m->unit) return 0; - r = manager_stop_unit(m->manager, m->scope, &error, &job); + r = manager_stop_unit(m->manager, m->unit, &error, &job); if (r < 0) { log_error("Failed to stop machine scope: %s", bus_error_message(&error, r)); return r; @@ -334,7 +359,7 @@ int machine_stop(Machine *m) { if (k < 0) r = k; - unlink(m->state_file); + machine_unlink(m); machine_add_to_gc_queue(m); if (m->started) @@ -354,7 +379,7 @@ bool machine_check_gc(Machine *m, bool drop_not_started) { if (m->scope_job && manager_job_is_active(m->manager, m->scope_job)) return true; - if (m->scope && manager_unit_is_active(m->manager, m->scope)) + if (m->unit && manager_unit_is_active(m->manager, m->unit)) return true; return false; @@ -382,10 +407,10 @@ MachineState machine_get_state(Machine *s) { int machine_kill(Machine *m, KillWho who, int signo) { assert(m); - if (!m->scope) + if (!m->unit) return -ESRCH; - return manager_kill_unit(m->manager, m->scope, who, signo, NULL); + return manager_kill_unit(m->manager, m->unit, who, signo, NULL); } static const char* const machine_class_table[_MACHINE_CLASS_MAX] = { diff --git a/src/machine/machine.h b/src/machine/machine.h index 62e4b2b340..f4aefc550f 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -63,7 +63,7 @@ struct Machine { char *service; char *root_directory; - char *scope; + char *unit; char *scope_job; pid_t leader; diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index b3a70188a4..703fb3a3a0 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -107,7 +107,7 @@ static int list_machines(sd_bus *bus, char **args, unsigned n) { return 0; } -static int show_scope_cgroup(sd_bus *bus, const char *unit, pid_t leader) { +static int show_unit_cgroup(sd_bus *bus, const char *unit, pid_t leader) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *path = NULL; @@ -129,7 +129,7 @@ static int show_scope_cgroup(sd_bus *bus, const char *unit, pid_t leader) { bus, "org.freedesktop.systemd1", path, - "org.freedesktop.systemd1.Scope", + endswith(unit, ".scope") ? "org.freedesktop.systemd1.Scope" : "org.freedesktop.systemd1.Service", "ControlGroup", &error, &reply, @@ -168,7 +168,7 @@ typedef struct MachineStatusInfo { sd_id128_t id; char *class; char *service; - char *scope; + char *unit; char *root_directory; pid_t leader; usec_t timestamp; @@ -219,9 +219,9 @@ static void print_machine_status_info(sd_bus *bus, MachineStatusInfo *i) { if (i->root_directory) printf("\t Root: %s\n", i->root_directory); - if (i->scope) { - printf("\t Unit: %s\n", i->scope); - show_scope_cgroup(bus, i->scope, i->leader); + if (i->unit) { + printf("\t Unit: %s\n", i->unit); + show_unit_cgroup(bus, i->unit, i->leader); } } @@ -231,7 +231,7 @@ static int show_info(const char *verb, sd_bus *bus, const char *path, bool *new_ { "Name", "s", NULL, offsetof(MachineStatusInfo, name) }, { "Class", "s", NULL, offsetof(MachineStatusInfo, class) }, { "Service", "s", NULL, offsetof(MachineStatusInfo, service) }, - { "Scope", "s", NULL, offsetof(MachineStatusInfo, scope) }, + { "Unit", "s", NULL, offsetof(MachineStatusInfo, unit) }, { "RootDirectory", "s", NULL, offsetof(MachineStatusInfo, root_directory) }, { "Leader", "u", NULL, offsetof(MachineStatusInfo, leader) }, { "Timestamp", "t", NULL, offsetof(MachineStatusInfo, timestamp) }, @@ -264,7 +264,7 @@ static int show_info(const char *verb, sd_bus *bus, const char *path, bool *new_ free(info.name); free(info.class); free(info.service); - free(info.scope); + free(info.unit); free(info.root_directory); return r; diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 7c7293b29d..4a75c34dd0 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -169,9 +169,8 @@ static int method_list_machines(sd_bus *bus, sd_bus_message *message, void *user return sd_bus_send(bus, reply, NULL); } -static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { +static int method_create_or_register_machine(Manager *manager, sd_bus_message *message, Machine **_m, sd_bus_error *error) { const char *name, *service, *class, *root_directory; - Manager *manager = userdata; MachineClass c; uint32_t leader; sd_id128_t id; @@ -180,9 +179,9 @@ static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *use size_t n; int r; - assert(bus); - assert(message); assert(manager); + assert(message); + assert(_m); r = sd_bus_message_read(message, "s", &name); if (r < 0) @@ -218,10 +217,6 @@ static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *use if (!isempty(root_directory) && !path_is_absolute(root_directory)) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root directory must be empty or an absolute path"); - r = sd_bus_message_enter_container(message, 'a', "(sv)"); - if (r < 0) - return r; - if (leader == 0) { _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; @@ -263,17 +258,70 @@ static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *use } } + *_m = m; + + return 1; + +fail: + machine_add_to_gc_queue(m); + return r; +} + +static int method_create_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *manager = userdata; + Machine *m = NULL; + int r; + + r = method_create_or_register_machine(manager, message, &m, error); + if (r < 0) + return r; + + r = sd_bus_message_enter_container(message, 'a', "(sv)"); + if (r < 0) + goto fail; + r = machine_start(m, message, error); if (r < 0) goto fail; m->create_message = sd_bus_message_ref(message); - return 1; fail: machine_add_to_gc_queue(m); + return r; +} + +static int method_register_machine(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *manager = userdata; + _cleanup_free_ char *p = NULL; + Machine *m = NULL; + int r; + + r = method_create_or_register_machine(manager, message, &m, error); + if (r < 0) + return r; + + r = cg_pid_get_unit(m->leader, &m->unit); + if (r < 0) { + r = sd_bus_error_set_errnof(error, r, "Failed to determine unit of process "PID_FMT" : %s", m->leader, strerror(-r)); + goto fail; + } + r = machine_start(m, NULL, error); + if (r < 0) + goto fail; + + p = machine_bus_path(m); + if (!p) { + r = -ENOMEM; + goto fail; + } + + return sd_bus_reply_method_return(message, "o", p); + +fail: + machine_add_to_gc_queue(m); return r; } @@ -347,6 +395,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0), + SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine, 0), SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), SD_BUS_SIGNAL("MachineNew", "so", 0), -- cgit v1.2.3-54-g00ecf