]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: rework /etc/machine-id handling
authorLennart Poettering <lennart@poettering.net>
Thu, 21 Jul 2016 16:53:40 +0000 (18:53 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Jul 2016 10:59:36 +0000 (12:59 +0200)
With this change we'll no longer write to /etc/machine-id from nspawn, as that
breaks the --volatile= operation, as it ensures the image is never considered
in "first boot", since that's bound to the pre-existance of /etc/machine-id.

The new logic works like this:

- If /etc/machine-id already exists in the container, it is read by nspawn and
  exposed in "machinectl status" and friends.

- If the file doesn't exist yet, but --uuid= is passed on the nspawn cmdline,
  this UUID is passed in $container_uuid to PID 1, and PID 1 is then expected
  to persist this to /etc/machine-id for future boots (which systemd already
  does).

- If the file doesn#t exist yet, and no --uuid= is passed a random UUID is
  generated and passed via $container_uuid.

The result is that /etc/machine-id is never initialized by nspawn itself, thus
unbreaking the volatile mode. However still the machine ID configured in the
machine always matches nspawn's and thus machined's idea of it.

Fixes: #3611
Makefile.am
src/nspawn/nspawn.c

index f7288f6df7f346a187e7e0c2b6c213c7378b0147..d5a70780a7b062629033bf306cb54fb6ee235575 100644 (file)
@@ -3075,9 +3075,7 @@ systemd_nspawn_SOURCES = \
        src/core/mount-setup.c \
        src/core/mount-setup.h \
        src/core/loopback-setup.c \
-       src/core/loopback-setup.h \
-       src/core/machine-id-setup.c \
-       src/core/machine-id-setup.h
+       src/core/loopback-setup.h
 
 nodist_systemd_nspawn_SOURCES = \
        src/nspawn/nspawn-gperf.c
index d971cded5ee5ceaf12e436f166ddf8aca4d14454..4c1d79418dff683b5b850ed87e5cec095eb62335 100644 (file)
@@ -64,7 +64,6 @@
 #include "id128-util.h"
 #include "log.h"
 #include "loopback-setup.h"
-#include "machine-id-setup.h"
 #include "machine-image.h"
 #include "macro.h"
 #include "missing.h"
@@ -595,9 +594,12 @@ static int parse_argv(int argc, char *argv[]) {
 
                 case ARG_UUID:
                         r = sd_id128_from_string(optarg, &arg_uuid);
-                        if (r < 0) {
-                                log_error("Invalid UUID: %s", optarg);
-                                return r;
+                        if (r < 0)
+                                return log_error_errno(r, "Invalid UUID: %s", optarg);
+
+                        if (sd_id128_is_null(arg_uuid)) {
+                                log_error("Machine UUID may not be all zeroes.");
+                                return -EINVAL;
                         }
 
                         arg_settings_mask |= SETTING_MACHINE_ID;
@@ -2219,37 +2221,38 @@ static int mount_device(const char *what, const char *where, const char *directo
 #endif
 }
 
-static int machine_id_read(const char *directory, sd_id128_t *ret) {
+static int setup_machine_id(const char *directory) {
         const char *etc_machine_id;
         sd_id128_t id;
         int r;
 
+        /* If the UUID in the container is already set, then that's what counts, and we use. If it isn't set, and the
+         * caller passed --uuid=, then we'll pass it in the $container_uuid env var to PID 1 of the container. The
+         * assumption is that PID 1 will then write it to /etc/machine-id to make it persistent. If --uuid= is not
+         * passed we generate a random UUID, and pass it via $container_uuid. In effect this means that /etc/machine-id
+         * in the container and our idea of the container UUID will always be in sync (at least if PID 1 in the
+         * container behaves nicely). */
+
         etc_machine_id = prefix_roota(directory, "/etc/machine-id");
 
         r = id128_read(etc_machine_id, ID128_PLAIN, &id);
-        if (r < 0)
-                return r;
-
-        if (sd_id128_is_null(id))
-                return -EINVAL;
-
-        *ret = id;
-        return 0;
-}
-
-static int setup_machine_id(const char *directory) {
-        int r;
+        if (r < 0) {
+                if (!IN_SET(r, -ENOENT, -ENOMEDIUM)) /* If the file is missing or empty, we don't mind */
+                        return log_error_errno(r, "Failed to read machine ID from container image: %m");
 
-        /* Try to set up the machine ID, if it isn't set up yet. Use a transient one, if necessary. Use the the UUID we
-         * were configured for if possible for initialization. */
-        r = machine_id_setup(directory, arg_uuid);
-        if (r < 0)
-                return log_error_errno(r, "Failed to setup machine ID: %m");
+                if (sd_id128_is_null(arg_uuid)) {
+                        r = sd_id128_randomize(&arg_uuid);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to acquire randomized machine UUID: %m");
+                }
+        } else {
+                if (sd_id128_is_null(id)) {
+                        log_error("Machine ID in container image is zero, refusing.");
+                        return -EINVAL;
+                }
 
-        /* Read back what was actually set. */
-        r = machine_id_read(directory, &arg_uuid);
-        if (r < 0)
-                return log_error_errno(r, "Failed to read machine ID: %m");
+                arg_uuid = id;
+        }
 
         return 0;
 }