mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
nspawn: register containers in both user and system machined if applicable (#39145)
This commit is contained in:
@@ -131,30 +131,25 @@ static int can_set_coredump_receive(sd_bus *bus) {
|
||||
return r >= 0;
|
||||
}
|
||||
|
||||
static int create_or_register_machine_ex(
|
||||
static int register_machine_ex(
|
||||
sd_bus *bus,
|
||||
const char *machine_name,
|
||||
const PidRef *pid,
|
||||
const char *directory,
|
||||
sd_id128_t uuid,
|
||||
int local_ifindex,
|
||||
const char *slice,
|
||||
CustomMount *mounts,
|
||||
unsigned n_mounts,
|
||||
int kill_signal,
|
||||
char **properties,
|
||||
sd_bus_message *properties_message,
|
||||
const char *service,
|
||||
StartMode start_mode,
|
||||
sd_bus_error *error,
|
||||
bool keep_unit) {
|
||||
sd_bus_error *error) {
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(machine_name);
|
||||
assert(service);
|
||||
assert(error);
|
||||
|
||||
r = bus_message_new_method_call(bus, &m, bus_machine_mgr, keep_unit ? "RegisterMachineEx" : "CreateMachineEx");
|
||||
r = bus_message_new_method_call(bus, &m, bus_machine_mgr, "RegisterMachineEx");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
@@ -209,45 +204,6 @@ static int create_or_register_machine_ex(
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
if (!keep_unit) {
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
if (!isempty(slice)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = append_controller_property(bus, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = append_machine_properties(
|
||||
m,
|
||||
mounts,
|
||||
n_mounts,
|
||||
kill_signal,
|
||||
start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (properties_message) {
|
||||
r = sd_bus_message_copy(m, properties_message, true);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
return sd_bus_call(bus, m, 0, error, NULL);
|
||||
}
|
||||
|
||||
@@ -258,117 +214,45 @@ int register_machine(
|
||||
const char *directory,
|
||||
sd_id128_t uuid,
|
||||
int local_ifindex,
|
||||
const char *slice,
|
||||
CustomMount *mounts,
|
||||
unsigned n_mounts,
|
||||
int kill_signal,
|
||||
char **properties,
|
||||
sd_bus_message *properties_message,
|
||||
const char *service,
|
||||
StartMode start_mode,
|
||||
RegisterMachineFlags flags) {
|
||||
const char *service) {
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(machine_name);
|
||||
assert(service);
|
||||
|
||||
r = create_or_register_machine_ex(
|
||||
r = register_machine_ex(
|
||||
bus,
|
||||
machine_name,
|
||||
pid,
|
||||
directory,
|
||||
uuid,
|
||||
local_ifindex,
|
||||
slice,
|
||||
mounts,
|
||||
n_mounts,
|
||||
kill_signal,
|
||||
properties,
|
||||
properties_message,
|
||||
service,
|
||||
start_mode,
|
||||
&error,
|
||||
FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT));
|
||||
&error);
|
||||
if (r >= 0)
|
||||
return 0;
|
||||
if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
|
||||
return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
|
||||
|
||||
sd_bus_error_free(&error);
|
||||
if (FLAGS_SET(flags, REGISTER_MACHINE_KEEP_UNIT)) {
|
||||
r = bus_call_method(
|
||||
bus,
|
||||
bus_machine_mgr,
|
||||
"RegisterMachineWithNetwork",
|
||||
&error,
|
||||
NULL,
|
||||
"sayssusai",
|
||||
machine_name,
|
||||
SD_BUS_MESSAGE_APPEND_ID128(uuid),
|
||||
service,
|
||||
"container",
|
||||
pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
|
||||
strempty(directory),
|
||||
local_ifindex > 0 ? 1 : 0, local_ifindex);
|
||||
} else {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
|
||||
r = bus_message_new_method_call(bus, &m, bus_machine_mgr, "CreateMachineWithNetwork");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(
|
||||
m,
|
||||
"sayssusai",
|
||||
machine_name,
|
||||
SD_BUS_MESSAGE_APPEND_ID128(uuid),
|
||||
service,
|
||||
"container",
|
||||
pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
|
||||
strempty(directory),
|
||||
local_ifindex > 0 ? 1 : 0, local_ifindex);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
if (!isempty(slice)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = append_controller_property(bus, m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = append_machine_properties(
|
||||
m,
|
||||
mounts,
|
||||
n_mounts,
|
||||
kill_signal,
|
||||
start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (properties_message) {
|
||||
r = sd_bus_message_copy(m, properties_message, true);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, NULL);
|
||||
}
|
||||
r = bus_call_method(
|
||||
bus,
|
||||
bus_machine_mgr,
|
||||
"RegisterMachineWithNetwork",
|
||||
&error,
|
||||
NULL,
|
||||
"sayssusai",
|
||||
machine_name,
|
||||
SD_BUS_MESSAGE_APPEND_ID128(uuid),
|
||||
service,
|
||||
"container",
|
||||
pidref_is_set(pid) ? (uint32_t) pid->pid : 0,
|
||||
strempty(directory),
|
||||
local_ifindex > 0 ? 1 : 0, local_ifindex);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
|
||||
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
#include "forward.h"
|
||||
#include "nspawn-settings.h"
|
||||
|
||||
typedef enum RegisterMachineFlags {
|
||||
REGISTER_MACHINE_KEEP_UNIT = 1 << 0,
|
||||
} RegisterMachineFlags;
|
||||
|
||||
int register_machine(
|
||||
sd_bus *bus,
|
||||
const char *machine_name,
|
||||
@@ -15,14 +11,7 @@ int register_machine(
|
||||
const char *directory,
|
||||
sd_id128_t uuid,
|
||||
int local_ifindex,
|
||||
const char *slice,
|
||||
CustomMount *mounts, unsigned n_mounts,
|
||||
int kill_signal,
|
||||
char **properties,
|
||||
sd_bus_message *properties_message,
|
||||
const char *service,
|
||||
StartMode start_mode,
|
||||
RegisterMachineFlags flags);
|
||||
const char *service);
|
||||
int unregister_machine(sd_bus *bus, const char *machine_name);
|
||||
|
||||
typedef enum AllocateScopeFlags {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "sd-event.h"
|
||||
#include "sd-id128.h"
|
||||
#include "sd-netlink.h"
|
||||
#include "sd-path.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "barrier.h"
|
||||
@@ -4936,30 +4937,49 @@ static int load_settings(void) {
|
||||
if (FLAGS_SET(arg_settings_mask, _SETTINGS_MASK_ALL))
|
||||
return 0;
|
||||
|
||||
/* We first look in the admin's directories in /etc and /run */
|
||||
if (arg_privileged)
|
||||
FOREACH_STRING(i, "/etc/systemd/nspawn", "/run/systemd/nspawn") {
|
||||
_cleanup_free_ char *j = NULL;
|
||||
/* We first look in the admin's directories in /etc/ and /run/ */
|
||||
static const uint64_t lookup_dir_system[] = {
|
||||
SD_PATH_SYSTEM_CONFIGURATION,
|
||||
SD_PATH_SYSTEM_RUNTIME,
|
||||
_SD_PATH_INVALID,
|
||||
};
|
||||
static const uint64_t lookup_dir_user[] = {
|
||||
SD_PATH_USER_CONFIGURATION,
|
||||
SD_PATH_USER_RUNTIME,
|
||||
_SD_PATH_INVALID,
|
||||
};
|
||||
|
||||
j = path_join(i, arg_settings_filename);
|
||||
if (!j)
|
||||
return log_oom();
|
||||
|
||||
f = fopen(j, "re");
|
||||
if (f) {
|
||||
p = TAKE_PTR(j);
|
||||
|
||||
/* By default, we trust configuration from /etc and /run */
|
||||
if (arg_settings_trusted < 0)
|
||||
arg_settings_trusted = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to open %s: %m", j);
|
||||
const uint64_t *q = arg_privileged ? lookup_dir_system : lookup_dir_user;
|
||||
for (; *q != _SD_PATH_INVALID; q++) {
|
||||
_cleanup_free_ char *cd = NULL;
|
||||
r = sd_path_lookup(*q, "systemd/nspawn", &cd);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "Failed to determine settings directory, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *j = NULL;
|
||||
j = path_join(cd, arg_settings_filename);
|
||||
if (!j)
|
||||
return log_oom();
|
||||
|
||||
f = fopen(j, "re");
|
||||
if (f) {
|
||||
p = TAKE_PTR(j);
|
||||
|
||||
log_debug("Found settings file: %s", p);
|
||||
|
||||
/* By default, we trust configuration from /etc and /run */
|
||||
if (arg_settings_trusted < 0)
|
||||
arg_settings_trusted = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to open %s: %m", j);
|
||||
}
|
||||
|
||||
if (!f) {
|
||||
/* After that, let's look for a file next to the
|
||||
* actual image we shall boot. */
|
||||
@@ -4979,6 +4999,9 @@ static int load_settings(void) {
|
||||
if (!f && errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to open %s: %m", p);
|
||||
|
||||
if (f)
|
||||
log_debug("Found settings file: %s", p);
|
||||
|
||||
/* By default, we do not trust configuration from /var/lib/machines */
|
||||
if (arg_settings_trusted < 0)
|
||||
arg_settings_trusted = false;
|
||||
@@ -5357,10 +5380,10 @@ static int run_container(
|
||||
(void) sd_bus_set_allow_interactive_authorization(system_bus, arg_ask_password);
|
||||
}
|
||||
|
||||
/* Scope allocation happens on the user bus if we are unpriv, otherwise system bus. */
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *user_bus = NULL;
|
||||
_cleanup_(sd_bus_unrefp) sd_bus *runtime_bus = NULL;
|
||||
if (!arg_keep_unit) {
|
||||
|
||||
if (arg_register || !arg_keep_unit) {
|
||||
if (arg_privileged)
|
||||
runtime_bus = sd_bus_ref(system_bus);
|
||||
else {
|
||||
@@ -5374,7 +5397,22 @@ static int run_container(
|
||||
|
||||
runtime_bus = sd_bus_ref(user_bus);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scope allocation happens on the user bus if we are unpriv, otherwise system bus. */
|
||||
if (arg_keep_unit) {
|
||||
/* If we are not supposed to allocate a unit, then let's move the process now, so that we can
|
||||
* register things while being in the right cgroup location already. Otherwise, let's move
|
||||
* the process later, once we have unit and hence cgroup. */
|
||||
r = create_subcgroup(
|
||||
pid,
|
||||
arg_keep_unit,
|
||||
arg_uid_shift,
|
||||
userns_fd,
|
||||
arg_userns_mode);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
/* When a new scope is created for this container, then we'll be registered as its controller, in which
|
||||
* case PID 1 will send us a friendly RequestStop signal, when it is asked to terminate the
|
||||
* scope. Let's hook into that, and cleanly shut down the container, and print a friendly message. */
|
||||
@@ -5393,22 +5431,8 @@ static int run_container(
|
||||
return log_error_errno(r, "Failed to request RequestStop match: %m");
|
||||
}
|
||||
|
||||
if (arg_keep_unit) {
|
||||
/* If we are not supposed to allocate a unit, then let's move the process now, so that we can
|
||||
* register things while being in the right cgroup location already. Otherwise, let's move
|
||||
* the process later, once we have unit and hence cgroup. */
|
||||
r = create_subcgroup(
|
||||
pid,
|
||||
arg_keep_unit,
|
||||
arg_uid_shift,
|
||||
userns_fd,
|
||||
arg_userns_mode);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
bool scope_allocated = false;
|
||||
if (!arg_keep_unit && (!arg_register || !arg_privileged)) {
|
||||
if (!arg_keep_unit) {
|
||||
AllocateScopeFlags flags = ALLOCATE_SCOPE_ALLOW_PIDFD;
|
||||
r = allocate_scope(
|
||||
runtime_bus,
|
||||
@@ -5427,10 +5451,8 @@ static int run_container(
|
||||
scope_allocated = true;
|
||||
}
|
||||
|
||||
bool registered = false;
|
||||
bool registered_system = false, registered_runtime = false;
|
||||
if (arg_register) {
|
||||
RegisterMachineFlags flags = 0;
|
||||
SET_FLAG(flags, REGISTER_MACHINE_KEEP_UNIT, arg_keep_unit || !arg_privileged);
|
||||
r = register_machine(
|
||||
system_bus,
|
||||
arg_machine,
|
||||
@@ -5438,18 +5460,32 @@ static int run_container(
|
||||
arg_directory,
|
||||
arg_uuid,
|
||||
ifi,
|
||||
arg_slice,
|
||||
arg_custom_mounts, arg_n_custom_mounts,
|
||||
arg_kill_signal,
|
||||
arg_property,
|
||||
arg_property_message,
|
||||
arg_container_service_name,
|
||||
arg_start_mode,
|
||||
flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
arg_container_service_name);
|
||||
if (r < 0) {
|
||||
if (arg_privileged) /* if privileged the request to register definitely failed */
|
||||
return r;
|
||||
|
||||
registered = true;
|
||||
log_notice_errno(r, "Failed to register machine in system context, will try in user context.");
|
||||
} else
|
||||
registered_system = true;
|
||||
|
||||
if (!arg_privileged) {
|
||||
r = register_machine(
|
||||
runtime_bus,
|
||||
arg_machine,
|
||||
pid,
|
||||
arg_directory,
|
||||
arg_uuid,
|
||||
ifi,
|
||||
arg_container_service_name);
|
||||
if (r < 0) {
|
||||
if (!registered_system) /* neither registration worked: fail */
|
||||
return r;
|
||||
|
||||
log_notice_errno(r, "Failed to register machine in user context, but succeeded in system context, will proceed.");
|
||||
} else
|
||||
registered_runtime = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_keep_unit && (arg_slice || arg_property))
|
||||
@@ -5661,8 +5697,10 @@ static int run_container(
|
||||
r = wait_for_container(pid, &container_status);
|
||||
|
||||
/* Tell machined that we are gone. */
|
||||
if (registered)
|
||||
if (registered_system)
|
||||
(void) unregister_machine(system_bus, arg_machine);
|
||||
if (registered_runtime)
|
||||
(void) unregister_machine(runtime_bus, arg_machine);
|
||||
|
||||
if (r < 0)
|
||||
/* We failed to wait for the container, or the container exited abnormally. */
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
enum {
|
||||
__extension__ enum {
|
||||
/* Temporary files */
|
||||
SD_PATH_TEMPORARY,
|
||||
SD_PATH_TEMPORARY_LARGE,
|
||||
@@ -129,7 +129,8 @@ enum {
|
||||
SD_PATH_USER_CREDENTIAL_STORE_ENCRYPTED,
|
||||
SD_PATH_USER_SEARCH_CREDENTIAL_STORE_ENCRYPTED,
|
||||
|
||||
_SD_PATH_MAX
|
||||
_SD_PATH_MAX,
|
||||
_SD_PATH_INVALID = UINT64_MAX
|
||||
};
|
||||
|
||||
int sd_path_lookup(uint64_t type, const char *suffix, char **ret);
|
||||
|
||||
Reference in New Issue
Block a user