[systemd-commits] 4 commits - man/systemd-nspawn.xml src/login src/machine src/nspawn src/shared src/test

Lennart Poettering lennart at kemper.freedesktop.org
Tue Feb 11 08:16:14 PST 2014


 man/systemd-nspawn.xml      |   77 ++++++++++++++++++---
 src/login/sd-login.c        |   27 +++++++
 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 ++++++++++++++++--
 src/nspawn/nspawn.c         |  157 ++++++++++++++++++++++++++++++++++----------
 src/shared/cgroup-util.c    |   37 ++--------
 src/shared/util.c           |   31 ++------
 src/shared/util.h           |    1 
 src/test/test-util.c        |   16 ----
 12 files changed, 341 insertions(+), 150 deletions(-)

New commits:
commit 89f7c8465cd1ab37347dd0c15920bce31e8225df
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Feb 11 17:15:38 2014 +0100

    machined: optionally, allow registration of pre-existing units (scopes
    or services) as machine with machined

diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index 47c3183..9d8db83 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -465,8 +465,8 @@
                                 should be enabled when the container
                                 runs a full Operating System (more
                                 specifically: an init system), and is
-                                useful to ensure the container is
-                                accesible via
+                                useful to ensure that the container is
+                                accessible via
                                 <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
                                 and shown by tools such as
                                 <citerefentry><refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum></citerefentry>. If
@@ -478,6 +478,30 @@
                                 <option>--register=no</option>.
                                 </para></listitem>
                         </varlistentry>
+
+                        <varlistentry>
+                                <term><option>--keep-unit</option></term>
+
+                                <listitem><para>Instead of creating a
+                                transient scope unit to run the
+                                container in, simply register the
+                                service or scope unit
+                                <command>systemd-nspawn</command> has
+                                been invoked in in
+                                <citerefentry><refentrytitle>systemd-machined</refentrytitle><manvolnum>8</manvolnum></citerefentry>. This
+                                has no effect if
+                                <option>--register=no</option> is
+                                used. This switch should be used if
+                                <command>systemd-nspawn</command> is
+                                invoked from within an a service unit,
+                                and the service unit's sole purpose
+                                is to run a single
+                                <command>systemd-nspawn</command>
+                                container. This option is not
+                                available if run from a user
+                                session.</para></listitem>
+                        </varlistentry>
+
                 </variablelist>
 
         </refsect1>
diff --git a/src/login/sd-login.c b/src/login/sd-login.c
index c795765..ef67040 100644
--- a/src/login/sd-login.c
+++ b/src/login/sd-login.c
@@ -630,7 +630,32 @@ _public_ int sd_get_uids(uid_t **users) {
 }
 
 _public_ int sd_get_machine_names(char ***machines) {
-        return get_files_in_directory("/run/systemd/machines/", machines);
+        char **l = NULL, **a, **b;
+        int r;
+
+        r = get_files_in_directory("/run/systemd/machines/", &l);
+        if (r < 0)
+                return r;
+
+        if (l) {
+                r = 0;
+
+                /* Filter out the unit: symlinks */
+                for (a = l, b = l; *a; a++) {
+                        if (startswith(*a, "unit:"))
+                                free(*a);
+                        else {
+                                *b = *a;
+                                b++;
+                                r++;
+                        }
+                }
+
+                *b = NULL;
+        }
+
+        *machines = l;
+        return r;
 }
 
 static inline int MONITOR_TO_FD(sd_login_monitor *m) {
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index 90eb001..df96ccf 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 0791ba8..e45c443 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 62e4b2b..f4aefc5 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 b3a7018..703fb3a 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 7c7293b..4a75c34 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),
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 0a81f97..97ef6c7 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -120,6 +120,7 @@ static char **arg_setenv = NULL;
 static bool arg_quiet = false;
 static bool arg_share_system = false;
 static bool arg_register = true;
+static bool arg_keep_unit = false;
 
 static int help(void) {
 
@@ -152,6 +153,8 @@ static int help(void) {
                "     --bind-ro=PATH[:PATH]  Similar, but creates a read-only bind mount\n"
                "     --setenv=NAME=VALUE    Pass an environment variable to PID 1\n"
                "     --register=BOOLEAN     Register container as machine\n"
+               "     --keep-unit            Do not register a scope for the machine, reuse\n"
+               "                            the service unit nspawn is running in\n"
                "  -q --quiet                Do not show status information\n",
                program_invocation_short_name);
 
@@ -172,7 +175,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_BIND_RO,
                 ARG_SETENV,
                 ARG_SHARE_SYSTEM,
-                ARG_REGISTER
+                ARG_REGISTER,
+                ARG_KEEP_UNIT
         };
 
         static const struct option options[] = {
@@ -197,6 +201,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "quiet",                 no_argument,       NULL, 'q'                 },
                 { "share-system",          no_argument,       NULL, ARG_SHARE_SYSTEM    },
                 { "register",              required_argument, NULL, ARG_REGISTER        },
+                { "keep-unit",             no_argument,       NULL, ARG_KEEP_UNIT       },
                 {}
         };
 
@@ -410,6 +415,10 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_register = r;
                         break;
 
+                case ARG_KEEP_UNIT:
+                        arg_keep_unit = true;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -426,6 +435,11 @@ static int parse_argv(int argc, char *argv[]) {
                 return -EINVAL;
         }
 
+        if (arg_keep_unit && cg_pid_get_owner_uid(0, NULL) >= 0) {
+                log_error("--keep-unit may not be used when invoked from a user session.");
+                return -EINVAL;
+        }
+
         return 1;
 }
 
@@ -1086,22 +1100,41 @@ static int register_machine(pid_t pid) {
                 return r;
         }
 
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.machine1",
-                        "/org/freedesktop/machine1",
-                        "org.freedesktop.machine1.Manager",
-                        "CreateMachine",
-                        &error,
-                        NULL,
-                        "sayssusa(sv)",
-                        arg_machine,
-                        SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
-                        "nspawn",
-                        "container",
-                        (uint32_t) pid,
-                        strempty(arg_directory),
-                        !isempty(arg_slice), "Slice", "s", arg_slice);
+        if (arg_keep_unit) {
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.machine1",
+                                "/org/freedesktop/machine1",
+                                "org.freedesktop.machine1.Manager",
+                                "RegisterMachine",
+                                &error,
+                                NULL,
+                                "sayssus",
+                                arg_machine,
+                                SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
+                                "nspawn",
+                                "container",
+                                (uint32_t) pid,
+                                strempty(arg_directory));
+        } else {
+                r = sd_bus_call_method(
+                                bus,
+                                "org.freedesktop.machine1",
+                                "/org/freedesktop/machine1",
+                                "org.freedesktop.machine1.Manager",
+                                "CreateMachine",
+                                &error,
+                                NULL,
+                                "sayssusa(sv)",
+                                arg_machine,
+                                SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
+                                "nspawn",
+                                "container",
+                                (uint32_t) pid,
+                                strempty(arg_directory),
+                                !isempty(arg_slice), "Slice", "s", arg_slice);
+        }
+
         if (r < 0) {
                 log_error("Failed to register machine: %s", bus_error_message(&error, r));
                 return r;
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c
index e6ceb99..9692a07 100644
--- a/src/shared/cgroup-util.c
+++ b/src/shared/cgroup-util.c
@@ -1282,39 +1282,18 @@ int cg_pid_get_user_unit(pid_t pid, char **unit) {
 }
 
 int cg_path_get_machine_name(const char *path, char **machine) {
-        const char *e, *n, *x;
-        char *s, *r;
-        size_t l;
-
-        assert(path);
-        assert(machine);
-
-        /* Skip slices, if there are any */
-        e = skip_slices(path);
-
-        n = strchrnul(e, '/');
-        if (e == n)
-                return -ENOENT;
-
-        s = strndupa(e, n - e);
-        s = cg_unescape(s);
-
-        x = startswith(s, "machine-");
-        if (!x)
-                return -ENOENT;
-        if (!endswith(x, ".scope"))
-                return -ENOENT;
+        _cleanup_free_ char *u = NULL, *sl = NULL;
+        int r;
 
-        l = strlen(x);
-        if (l <= 6)
-                return -ENOENT;
+        r = cg_path_get_unit(path, &u);
+        if (r < 0)
+                return r;
 
-        r = strndup(x, l - 6);
-        if (!r)
+        sl = strjoin("/run/systemd/machines/unit:", u, NULL);
+        if (!sl)
                 return -ENOMEM;
 
-        *machine = r;
-        return 0;
+        return readlink_malloc(sl, machine);
 }
 
 int cg_pid_get_machine_name(pid_t pid, char **machine) {

commit 2d2ebd6b8f0775b93480bf05464865a0c78a9390
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Feb 11 16:45:35 2014 +0100

    util: modernize readlink_malloc() a bit

diff --git a/src/shared/util.c b/src/shared/util.c
index 21edd3a..9be11f5 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -761,28 +761,31 @@ char *strappend(const char *s, const char *suffix) {
         return strnappend(s, suffix, suffix ? strlen(suffix) : 0);
 }
 
-int readlink_malloc(const char *p, char **r) {
+int readlink_malloc(const char *p, char **ret) {
         size_t l = 100;
+        int r;
 
         assert(p);
-        assert(r);
+        assert(ret);
 
         for (;;) {
                 char *c;
                 ssize_t n;
 
-                if (!(c = new(char, l)))
+                c = new(char, l);
+                if (!c)
                         return -ENOMEM;
 
-                if ((n = readlink(p, c, l-1)) < 0) {
-                        int ret = -errno;
+                n = readlink(p, c, l-1);
+                if (n < 0) {
+                        r = -errno;
                         free(c);
-                        return ret;
+                        return r;
                 }
 
                 if ((size_t) n < l-1) {
                         c[n] = 0;
-                        *r = c;
+                        *ret = c;
                         return 0;
                 }
 

commit c50e4f95d8cfcd21bde2b0d1ff24b4de8fef4976
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Feb 11 16:45:15 2014 +0100

    util: drop parse_user_at_host() since its unused now

diff --git a/src/shared/util.c b/src/shared/util.c
index f76ed6f..21edd3a 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -5838,20 +5838,6 @@ bool id128_is_valid(const char *s) {
         return true;
 }
 
-void parse_user_at_host(char *arg, char **user, char **host) {
-        assert(arg);
-        assert(user);
-        assert(host);
-
-        *host = strchr(arg, '@');
-        if (*host == NULL)
-                *host = arg;
-        else {
-                *host[0]++ = '\0';
-                *user = arg;
-        }
-}
-
 int split_pair(const char *s, const char *sep, char **l, char **r) {
         char *x, *a, *b;
 
diff --git a/src/shared/util.h b/src/shared/util.h
index 219e489..9aea3a4 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -833,7 +833,6 @@ static inline void _reset_locale_(struct _locale_struct_ *s) {
              _saved_locale_.quit = true)
 
 bool id128_is_valid(const char *s) _pure_;
-void parse_user_at_host(char *arg, char **user, char **host);
 
 int split_pair(const char *s, const char *sep, char **l, char **r);
 
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 9d6f4be..cbd60d6 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -490,21 +490,6 @@ static void test_strrep(void) {
         assert_se(streq(zero, ""));
 }
 
-static void test_parse_user_at_host(void) {
-        _cleanup_free_ char *both = strdup("waldo at waldoscomputer");
-        _cleanup_free_ char *onlyhost = strdup("mikescomputer");
-        char *user = NULL, *host = NULL;
-
-        parse_user_at_host(both, &user, &host);
-        assert_se(streq(user, "waldo"));
-        assert_se(streq(host, "waldoscomputer"));
-
-        user = host = NULL;
-        parse_user_at_host(onlyhost, &user, &host);
-        assert_se(user == NULL);
-        assert_se(streq(host, "mikescomputer"));
-}
-
 static void test_split_pair(void) {
         _cleanup_free_ char *a = NULL, *b = NULL;
 
@@ -635,7 +620,6 @@ int main(int argc, char *argv[]) {
         test_parse_bytes();
         test_strextend();
         test_strrep();
-        test_parse_user_at_host();
         test_split_pair();
         test_fstab_node_to_udev_node();
         test_get_files_in_directory();

commit eb91eb187b7491e05fb95215b77cb62061f41d08
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Feb 10 15:36:32 2014 +0100

    nspawn: add --register=yes|no switch to optionally disable registration of the container with machined

diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml
index ca99da4..47c3183 100644
--- a/man/systemd-nspawn.xml
+++ b/man/systemd-nspawn.xml
@@ -204,9 +204,12 @@
                                 <listitem><para>Automatically search
                                 for an init binary and invoke it
                                 instead of a shell or a user supplied
-                                program. If this option is used, arguments
-                                specified on the command line are used
-                                as arguments for the init binary.
+                                program. If this option is used,
+                                arguments specified on the command
+                                line are used as arguments for the
+                                init binary. This option may not be
+                                combined with
+                                <option>--share-system</option>.
                                 </para></listitem>
                         </varlistentry>
 
@@ -424,8 +427,7 @@
                                 output by the tool itself. When this
                                 switch is used, then the only output
                                 by nspawn will be the console output
-                                of the container OS
-                                itself.</para></listitem>
+                                of the container OS itself.</para></listitem>
                         </varlistentry>
 
                         <varlistentry>
@@ -440,15 +442,42 @@
                                 interact more easily with processes
                                 outside of the container. Note that
                                 using this option makes it impossible
-                                to start up a full Operating System in the
-                                container, as an init system cannot
-                                operate in this mode. It is only
-                                useful to run specific programs or
-                                applications this way, without
-                                involving an init
-                                system in the container.</para></listitem>
+                                to start up a full Operating System in
+                                the container, as an init system
+                                cannot operate in this mode. It is
+                                only useful to run specific programs
+                                or applications this way, without
+                                involving an init system in the
+                                container. This option implies
+                                <option>--register=no</option>. This
+                                option may not be combined with
+                                <option>--boot</option>.</para></listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term><option>--register=</option></term>
+
+                                <listitem><para>Controls whether the
+                                container is registered with
+                                <citerefentry><refentrytitle>systemd-machined</refentrytitle><manvolnum>8</manvolnum></citerefentry>. Takes
+                                a boolean argument, defaults to
+                                <literal>yes</literal>. This option
+                                should be enabled when the container
+                                runs a full Operating System (more
+                                specifically: an init system), and is
+                                useful to ensure the container is
+                                accesible via
+                                <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+                                and shown by tools such as
+                                <citerefentry><refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum></citerefentry>. If
+                                the container does not run an init
+                                system it is recommended to set this
+                                option to <literal>no</literal>. Note
+                                that <option>--share-system</option>
+                                implies
+                                <option>--register=no</option>.
+                                </para></listitem>
+                        </varlistentry>
                 </variablelist>
 
         </refsect1>
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 759f9c1..0a81f97 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -119,6 +119,7 @@ static char **arg_bind_ro = NULL;
 static char **arg_setenv = NULL;
 static bool arg_quiet = false;
 static bool arg_share_system = false;
+static bool arg_register = true;
 
 static int help(void) {
 
@@ -150,6 +151,7 @@ static int help(void) {
                "                            the container\n"
                "     --bind-ro=PATH[:PATH]  Similar, but creates a read-only bind mount\n"
                "     --setenv=NAME=VALUE    Pass an environment variable to PID 1\n"
+               "     --register=BOOLEAN     Register container as machine\n"
                "  -q --quiet                Do not show status information\n",
                program_invocation_short_name);
 
@@ -169,7 +171,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_BIND,
                 ARG_BIND_RO,
                 ARG_SETENV,
-                ARG_SHARE_SYSTEM
+                ARG_SHARE_SYSTEM,
+                ARG_REGISTER
         };
 
         static const struct option options[] = {
@@ -193,6 +196,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "selinux-apifs-context", required_argument, NULL, 'L'                 },
                 { "quiet",                 no_argument,       NULL, 'q'                 },
                 { "share-system",          no_argument,       NULL, ARG_SHARE_SYSTEM    },
+                { "register",              required_argument, NULL, ARG_REGISTER        },
                 {}
         };
 
@@ -255,17 +259,23 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'M':
-                        if (!hostname_is_valid(optarg)) {
-                                log_error("Invalid machine name: %s", optarg);
-                                return -EINVAL;
-                        }
+                        if (isempty(optarg)) {
+                                free(arg_machine);
+                                arg_machine = NULL;
+                        } else {
 
-                        free(arg_machine);
-                        arg_machine = strdup(optarg);
-                        if (!arg_machine)
-                                return log_oom();
+                                if (!hostname_is_valid(optarg)) {
+                                        log_error("Invalid machine name: %s", optarg);
+                                        return -EINVAL;
+                                }
 
-                        break;
+                                free(arg_machine);
+                                arg_machine = strdup(optarg);
+                                if (!arg_machine)
+                                        return log_oom();
+
+                                break;
+                        }
 
                 case 'Z':
                         arg_selinux_context = optarg;
@@ -390,6 +400,16 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_share_system = true;
                         break;
 
+                case ARG_REGISTER:
+                        r = parse_boolean(optarg);
+                        if (r < 0) {
+                                log_error("Failed to parse --register= argument: %s", optarg);
+                                return r;
+                        }
+
+                        arg_register = r;
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -398,6 +418,14 @@ static int parse_argv(int argc, char *argv[]) {
                 }
         }
 
+        if (arg_share_system)
+                arg_register = false;
+
+        if (arg_boot && arg_share_system) {
+                log_error("--boot and --share-system may not be combined.");
+                return -EINVAL;
+        }
+
         return 1;
 }
 
@@ -636,6 +664,9 @@ static int setup_boot_id(const char *dest) {
 
         assert(dest);
 
+        if (arg_share_system)
+                return 0;
+
         /* Generate a new randomized boot ID, so that each boot-up of
          * the container gets a new one */
 
@@ -861,6 +892,9 @@ static int setup_kmsg(const char *dest, int kmsg_socket) {
 
 static int setup_hostname(void) {
 
+        if (arg_share_system)
+                return 0;
+
         if (sethostname(arg_machine, strlen(arg_machine)) < 0)
                 return -errno;
 
@@ -1043,6 +1077,9 @@ static int register_machine(pid_t pid) {
         _cleanup_bus_unref_ sd_bus *bus = NULL;
         int r;
 
+        if (!arg_register)
+                return 0;
+
         r = sd_bus_default_system(&bus);
         if (r < 0) {
                 log_error("Failed to open system bus: %s", strerror(-r));
@@ -1080,6 +1117,9 @@ static int terminate_machine(pid_t pid) {
         const char *path;
         int r;
 
+        if (!arg_register)
+                return 0;
+
         r = sd_bus_default_system(&bus);
         if (r < 0) {
                 log_error("Failed to open system bus: %s", strerror(-r));
@@ -1146,7 +1186,6 @@ int main(int argc, char *argv[]) {
         _cleanup_close_pipe_ int kmsg_socket_pair[2] = { -1, -1 };
         _cleanup_fdset_free_ FDSet *fds = NULL;
         _cleanup_free_ char *kdbus_domain = NULL;
-        const char *ns;
 
         log_parse_environment();
         log_open();
@@ -1248,12 +1287,26 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        ns = strappenda("machine-", arg_machine);
-        kdbus_fd = bus_kernel_create_domain(ns, &kdbus_domain);
-        if (r < 0)
-                log_debug("Failed to create kdbus domain: %s", strerror(-r));
-        else
-                log_debug("Successfully created kdbus domain as %s", kdbus_domain);
+
+        if (access("/dev/kdbus/control", F_OK) >= 0) {
+
+                if (arg_share_system) {
+                        kdbus_domain = strdup("/dev/kdbus");
+                        if (!kdbus_domain) {
+                                log_oom();
+                                goto finish;
+                        }
+                } else {
+                        const char *ns;
+
+                        ns = strappenda("machine-", arg_machine);
+                        kdbus_fd = bus_kernel_create_domain(ns, &kdbus_domain);
+                        if (r < 0)
+                                log_debug("Failed to create kdbus domain: %s", strerror(-r));
+                        else
+                                log_debug("Successfully created kdbus domain as %s", kdbus_domain);
+                }
+        }
 
         if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
                 log_error("Failed to create kmsg socket pair: %m");
@@ -1438,7 +1491,8 @@ int main(int argc, char *argv[]) {
 
                         umask(0022);
 
-                        loopback_setup();
+                        if (arg_private_network)
+                                loopback_setup();
 
                         if (drop_capabilities() < 0) {
                                 log_error("drop_capabilities() failed: %m");
@@ -1644,7 +1698,7 @@ int main(int argc, char *argv[]) {
                 } else if (status.si_code == CLD_KILLED ||
                            status.si_code == CLD_DUMPED) {
 
-                        log_error("Container %s terminated by signal %s.", arg_machine,  signal_to_string(status.si_status));
+                        log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status));
                         r = EXIT_FAILURE;
                         break;
                 } else {



More information about the systemd-commits mailing list