mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
nspawn: always setup machine id
We check /etc/machine-id of the container and if it is already populated we use value from there, possibly ignoring value of --uuid option from the command line. When dealing with R/O image we setup transient machine id. Once we determined machine id of the container, we use this value for registration with systemd-machined and we also export it via container_uuid environment variable. As registration with systemd-machined is done by the main nspawn process we communicate container machine id established by setup_machine_id from outer child to the main process by unix domain socket. Similarly to PID of inner child.
This commit is contained in:
parent
710a8858a9
commit
e01ff70a77
@ -3028,7 +3028,9 @@ 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/loopback-setup.h \
|
||||
src/core/machine-id-setup.c \
|
||||
src/core/machine-id-setup.h
|
||||
|
||||
nodist_systemd_nspawn_SOURCES = \
|
||||
src/nspawn/nspawn-gperf.c
|
||||
|
2
TODO
2
TODO
@ -564,8 +564,6 @@ Features:
|
||||
- to allow "linking" of nspawn containers, extend --network-bridge= so
|
||||
that it can dynamically create bridge interfaces that are refcounted
|
||||
by the containers on them. For each group of containers to link together
|
||||
- refuses to boot containers without /etc/machine-id (OK?), and with empty
|
||||
/etc/machine-id (not OK).
|
||||
- nspawn -x should support ephemeral instances of gpt images
|
||||
- emulate /dev/kmsg using CUSE and turn off the syslog syscall
|
||||
with seccomp. That should provide us with a useful log buffer that
|
||||
|
@ -355,7 +355,9 @@
|
||||
<listitem><para>Set the specified UUID for the container. The
|
||||
init system will initialize
|
||||
<filename>/etc/machine-id</filename> from this if this file is
|
||||
not set yet. </para></listitem>
|
||||
not set yet. Note that this option takes effect only if
|
||||
<filename>/etc/machine-id</filename> in the container is
|
||||
unpopulated.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "hostname-util.h"
|
||||
#include "log.h"
|
||||
#include "loopback-setup.h"
|
||||
#include "machine-id-setup.h"
|
||||
#include "machine-image.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
@ -1375,11 +1376,11 @@ static int setup_hostname(void) {
|
||||
}
|
||||
|
||||
static int setup_journal(const char *directory) {
|
||||
sd_id128_t machine_id, this_id;
|
||||
sd_id128_t this_id;
|
||||
_cleanup_free_ char *b = NULL, *d = NULL;
|
||||
const char *etc_machine_id, *p, *q;
|
||||
const char *p, *q;
|
||||
bool try;
|
||||
char *id;
|
||||
char id[33];
|
||||
int r;
|
||||
|
||||
/* Don't link journals in ephemeral mode */
|
||||
@ -1391,28 +1392,11 @@ static int setup_journal(const char *directory) {
|
||||
|
||||
try = arg_link_journal_try || arg_link_journal == LINK_AUTO;
|
||||
|
||||
etc_machine_id = prefix_roota(directory, "/etc/machine-id");
|
||||
|
||||
r = read_one_line_file(etc_machine_id, &b);
|
||||
if (r == -ENOENT && try)
|
||||
return 0;
|
||||
else if (r < 0)
|
||||
return log_error_errno(r, "Failed to read machine ID from %s: %m", etc_machine_id);
|
||||
|
||||
id = strstrip(b);
|
||||
if (isempty(id) && try)
|
||||
return 0;
|
||||
|
||||
/* Verify validity */
|
||||
r = sd_id128_from_string(id, &machine_id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse machine ID from %s: %m", etc_machine_id);
|
||||
|
||||
r = sd_id128_get_machine(&this_id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to retrieve machine ID: %m");
|
||||
|
||||
if (sd_id128_equal(machine_id, this_id)) {
|
||||
if (sd_id128_equal(arg_uuid, this_id)) {
|
||||
log_full(try ? LOG_WARNING : LOG_ERR,
|
||||
"Host and machine ids are equal (%s): refusing to link journals", id);
|
||||
if (try)
|
||||
@ -1432,6 +1416,8 @@ static int setup_journal(const char *directory) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create /var/log/journal: %m");
|
||||
|
||||
(void) sd_id128_to_string(arg_uuid, id);
|
||||
|
||||
p = strjoina("/var/log/journal/", id);
|
||||
q = prefix_roota(directory, p);
|
||||
|
||||
@ -2201,6 +2187,38 @@ static int mount_device(const char *what, const char *where, const char *directo
|
||||
#endif
|
||||
}
|
||||
|
||||
static int setup_machine_id(const char *directory) {
|
||||
int r;
|
||||
const char *etc_machine_id, *t;
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
etc_machine_id = prefix_roota(directory, "/etc/machine-id");
|
||||
|
||||
r = read_one_line_file(etc_machine_id, &s);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read machine ID from %s: %m", etc_machine_id);
|
||||
|
||||
t = strstrip(s);
|
||||
|
||||
if (!isempty(t)) {
|
||||
r = sd_id128_from_string(t, &arg_uuid);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse machine ID from %s: %m", etc_machine_id);
|
||||
} else {
|
||||
if (sd_id128_is_null(arg_uuid)) {
|
||||
r = sd_id128_randomize(&arg_uuid);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate random machine ID: %m");
|
||||
}
|
||||
}
|
||||
|
||||
r = machine_id_setup(directory, arg_uuid);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to setup machine ID: %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mount_devices(
|
||||
const char *where,
|
||||
const char *root_device, bool root_device_rw,
|
||||
@ -2458,6 +2476,7 @@ static int inner_child(
|
||||
FDSet *fds) {
|
||||
|
||||
_cleanup_free_ char *home = NULL;
|
||||
char as_uuid[37];
|
||||
unsigned n_env = 1;
|
||||
const char *envp[] = {
|
||||
"PATH=" DEFAULT_PATH_SPLIT_USR,
|
||||
@ -2575,12 +2594,10 @@ static int inner_child(
|
||||
(asprintf((char**)(envp + n_env++), "LOGNAME=%s", arg_user ? arg_user : "root") < 0))
|
||||
return log_oom();
|
||||
|
||||
if (!sd_id128_equal(arg_uuid, SD_ID128_NULL)) {
|
||||
char as_uuid[37];
|
||||
assert(!sd_id128_equal(arg_uuid, SD_ID128_NULL));
|
||||
|
||||
if (asprintf((char**)(envp + n_env++), "container_uuid=%s", id128_format_as_uuid(arg_uuid, as_uuid)) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
if (asprintf((char**)(envp + n_env++), "container_uuid=%s", id128_format_as_uuid(arg_uuid, as_uuid)) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (fdset_size(fds) > 0) {
|
||||
r = fdset_cloexec(fds, false);
|
||||
@ -2669,6 +2686,7 @@ static int outer_child(
|
||||
bool interactive,
|
||||
bool secondary,
|
||||
int pid_socket,
|
||||
int uuid_socket,
|
||||
int kmsg_socket,
|
||||
int rtnl_socket,
|
||||
int uid_shift_socket,
|
||||
@ -2682,6 +2700,7 @@ static int outer_child(
|
||||
assert(directory);
|
||||
assert(console);
|
||||
assert(pid_socket >= 0);
|
||||
assert(uuid_socket >= 0);
|
||||
assert(kmsg_socket >= 0);
|
||||
|
||||
cg_unified_flush();
|
||||
@ -2796,6 +2815,10 @@ static int outer_child(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = setup_machine_id(directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = setup_journal(directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2821,6 +2844,7 @@ static int outer_child(
|
||||
return log_error_errno(errno, "Failed to fork inner child: %m");
|
||||
if (pid == 0) {
|
||||
pid_socket = safe_close(pid_socket);
|
||||
uuid_socket = safe_close(uuid_socket);
|
||||
uid_shift_socket = safe_close(uid_shift_socket);
|
||||
|
||||
/* The inner child has all namespaces that are
|
||||
@ -2842,7 +2866,16 @@ static int outer_child(
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
l = send(uuid_socket, &arg_uuid, sizeof(arg_uuid), MSG_NOSIGNAL);
|
||||
if (l < 0)
|
||||
return log_error_errno(errno, "Failed to send machine ID: %m");
|
||||
if (l != sizeof(arg_uuid)) {
|
||||
log_error("Short write while sending machine ID.");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
pid_socket = safe_close(pid_socket);
|
||||
uuid_socket = safe_close(uuid_socket);
|
||||
kmsg_socket = safe_close(kmsg_socket);
|
||||
rtnl_socket = safe_close(rtnl_socket);
|
||||
|
||||
@ -3318,7 +3351,8 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
_cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 }, pid_socket_pair[2] = { -1, -1 }, uid_shift_socket_pair[2] = { -1, -1 };
|
||||
_cleanup_close_pair_ int kmsg_socket_pair[2] = { -1, -1 }, rtnl_socket_pair[2] = { -1, -1 },
|
||||
pid_socket_pair[2] = { -1, -1 }, uuid_socket_pair[2] = { -1, -1 }, uid_shift_socket_pair[2] = { -1, -1 };
|
||||
ContainerStatus container_status;
|
||||
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
|
||||
static const struct sigaction sa = {
|
||||
@ -3353,6 +3387,11 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uuid_socket_pair) < 0) {
|
||||
r = log_error_errno(errno, "Failed to create id socket pair: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (arg_userns)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uid_shift_socket_pair) < 0) {
|
||||
r = log_error_errno(errno, "Failed to create uid shift socket pair: %m");
|
||||
@ -3393,6 +3432,7 @@ int main(int argc, char *argv[]) {
|
||||
kmsg_socket_pair[0] = safe_close(kmsg_socket_pair[0]);
|
||||
rtnl_socket_pair[0] = safe_close(rtnl_socket_pair[0]);
|
||||
pid_socket_pair[0] = safe_close(pid_socket_pair[0]);
|
||||
uuid_socket_pair[0] = safe_close(uuid_socket_pair[0]);
|
||||
uid_shift_socket_pair[0] = safe_close(uid_shift_socket_pair[0]);
|
||||
|
||||
(void) reset_all_signal_handlers();
|
||||
@ -3407,6 +3447,7 @@ int main(int argc, char *argv[]) {
|
||||
interactive,
|
||||
secondary,
|
||||
pid_socket_pair[1],
|
||||
uuid_socket_pair[1],
|
||||
kmsg_socket_pair[1],
|
||||
rtnl_socket_pair[1],
|
||||
uid_shift_socket_pair[1],
|
||||
@ -3424,6 +3465,7 @@ int main(int argc, char *argv[]) {
|
||||
kmsg_socket_pair[1] = safe_close(kmsg_socket_pair[1]);
|
||||
rtnl_socket_pair[1] = safe_close(rtnl_socket_pair[1]);
|
||||
pid_socket_pair[1] = safe_close(pid_socket_pair[1]);
|
||||
uuid_socket_pair[1] = safe_close(uuid_socket_pair[1]);
|
||||
uid_shift_socket_pair[1] = safe_close(uid_shift_socket_pair[1]);
|
||||
|
||||
/* Wait for the outer child. */
|
||||
@ -3448,6 +3490,18 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
/* We also retrieve container UUID in case it was generated by outer child */
|
||||
l = recv(uuid_socket_pair[0], &arg_uuid, sizeof(arg_uuid), 0);
|
||||
if (l < 0) {
|
||||
r = log_error_errno(errno, "Failed to read container machine ID: %m");
|
||||
goto finish;
|
||||
}
|
||||
if (l != sizeof(arg_uuid)) {
|
||||
log_error("Short read while reading container machined ID.");
|
||||
r = EIO;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
log_debug("Init process invoked as PID " PID_FMT, pid);
|
||||
|
||||
if (arg_userns) {
|
||||
|
Loading…
Reference in New Issue
Block a user