diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-07-21 18:53:40 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-07-22 12:59:36 +0200 |
commit | 317feb4d9f84cf177aa71496b214bcbbf9682750 (patch) | |
tree | 40baa7349ee28eb8adf570cd82106d7447117c56 | |
parent | 2a6736ddd080674170e9b9fe225009a0476c68e1 (diff) |
nspawn: rework /etc/machine-id handling
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
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | src/nspawn/nspawn.c | 55 |
2 files changed, 30 insertions, 29 deletions
diff --git a/Makefile.am b/Makefile.am index f7288f6df7..d5a70780a7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index d971cded5e..4c1d79418d 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -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; } |