mirror of
https://github.com/systemd/systemd.git
synced 2025-03-28 02:50:16 +03:00
nspawn: make the hostname of the container explicitly configurable with a new --hostname= switch
Previously, the container's hostname was exclusively initialized from the machine name configured with --machine=, i.e. the internal name and the external name used for and by the container was synchronized. This adds a new option --hostname= that optionally allows the internal name to deviate from the external name. This new option is mainly useful to ultimately implement the OCI runtime spec directly in nspawn, but it might be useful on its own for some other usecases too.
This commit is contained in:
parent
5a4ff98840
commit
3a9530e5f1
@ -373,6 +373,22 @@
|
||||
instead.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--hostname=</option></term>
|
||||
|
||||
<listitem><para>Controls the hostname to set within the container, if different from the machine name. Expects
|
||||
a valid hostname as argument. If this option is used, the kernel hostname of the container will be set to this
|
||||
value, otherwise it will be initialized to the machine name as controlled by the <option>--machine=</option>
|
||||
option described above. The machine name is used for various aspect of identification of the container from the
|
||||
outside, the kernel hostname configurable with this option is useful for the container to identify itself from
|
||||
the inside. It is usually a good idea to keep both forms of identification synchronized, in order to avoid
|
||||
confusion. It is hence recommended to avoid usage of this option, and use <option>--machine=</option>
|
||||
exclusively. Note that regardless whether the container's hostname is initialized from the name set with
|
||||
<option>--hostname=</option> or the one set with <option>--machine=</option>, the container can later override
|
||||
its kernel hostname freely on its own as well.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--uuid=</option></term>
|
||||
|
||||
|
@ -302,6 +302,15 @@
|
||||
details.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Hostname=</varname></term>
|
||||
|
||||
<listitem><para>Configures the kernel hostname set for the container. This is equivalent to the
|
||||
<option>--hostname=</option> command line switch, and takes the same argument. See
|
||||
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
|
||||
details.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -49,6 +49,7 @@ Exec.LimitMSGQUEUE, config_parse_rlimit, RLIMIT_MSGQUEUE, of
|
||||
Exec.LimitNICE, config_parse_rlimit, RLIMIT_NICE, offsetof(Settings, rlimit)
|
||||
Exec.LimitRTPRIO, config_parse_rlimit, RLIMIT_RTPRIO, offsetof(Settings, rlimit)
|
||||
Exec.LimitRTTIME, config_parse_rlimit, RLIMIT_RTTIME, offsetof(Settings, rlimit)
|
||||
Exec.Hostname, config_parse_hostname, 0, offsetof(Settings, hostname)
|
||||
Files.ReadOnly, config_parse_tristate, 0, offsetof(Settings, read_only)
|
||||
Files.Volatile, config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
|
||||
Files.Bind, config_parse_bind, 0, 0
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "cap-list.h"
|
||||
#include "conf-parser.h"
|
||||
#include "hostname-util.h"
|
||||
#include "nspawn-network.h"
|
||||
#include "nspawn-settings.h"
|
||||
#include "parse-util.h"
|
||||
@ -82,6 +83,7 @@ Settings* settings_free(Settings *s) {
|
||||
strv_free(s->syscall_whitelist);
|
||||
strv_free(s->syscall_blacklist);
|
||||
rlimit_free_all(s->rlimit);
|
||||
free(s->hostname);
|
||||
|
||||
strv_free(s->network_interfaces);
|
||||
strv_free(s->network_macvlan);
|
||||
@ -603,3 +605,31 @@ int config_parse_syscall_filter(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_hostname(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char **s = data;
|
||||
|
||||
assert(rvalue);
|
||||
assert(s);
|
||||
|
||||
if (!hostname_is_valid(rvalue, false)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid hostname, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (free_and_strdup(s, empty_to_null(rvalue)) < 0)
|
||||
return log_oom();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -49,9 +49,10 @@ typedef enum SettingsMask {
|
||||
SETTING_NOTIFY_READY = UINT64_C(1) << 14,
|
||||
SETTING_PIVOT_ROOT = UINT64_C(1) << 15,
|
||||
SETTING_SYSCALL_FILTER = UINT64_C(1) << 16,
|
||||
SETTING_RLIMIT_FIRST = UINT64_C(1) << 17, /* we define one bit per resource limit here */
|
||||
SETTING_RLIMIT_LAST = UINT64_C(1) << (17 + _RLIMIT_MAX - 1),
|
||||
_SETTINGS_MASK_ALL = (UINT64_C(1) << (17 + _RLIMIT_MAX))
|
||||
SETTING_HOSTNAME = UINT64_C(1) << 17,
|
||||
SETTING_RLIMIT_FIRST = UINT64_C(1) << 18, /* we define one bit per resource limit here */
|
||||
SETTING_RLIMIT_LAST = UINT64_C(1) << (18 + _RLIMIT_MAX - 1),
|
||||
_SETTINGS_MASK_ALL = (UINT64_C(1) << (18 + _RLIMIT_MAX)) - 1
|
||||
} SettingsMask;
|
||||
|
||||
typedef struct Settings {
|
||||
@ -74,6 +75,7 @@ typedef struct Settings {
|
||||
char **syscall_whitelist;
|
||||
char **syscall_blacklist;
|
||||
struct rlimit *rlimit[_RLIMIT_MAX];
|
||||
char *hostname;
|
||||
|
||||
/* [Image] */
|
||||
int read_only;
|
||||
@ -118,3 +120,4 @@ int config_parse_boot(const char *unit, const char *filename, unsigned line, con
|
||||
int config_parse_pid2(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_private_users(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_syscall_filter(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
@ -128,7 +128,8 @@ static char *arg_pivot_root_new = NULL;
|
||||
static char *arg_pivot_root_old = NULL;
|
||||
static char *arg_user = NULL;
|
||||
static sd_id128_t arg_uuid = {};
|
||||
static char *arg_machine = NULL;
|
||||
static char *arg_machine = NULL; /* The name used by the host to refer to this */
|
||||
static char *arg_hostname = NULL; /* The name the payload sees by default */
|
||||
static const char *arg_selinux_context = NULL;
|
||||
static const char *arg_selinux_apifs_context = NULL;
|
||||
static const char *arg_slice = NULL;
|
||||
@ -223,6 +224,7 @@ static void help(void) {
|
||||
" Pivot root to given directory in the container\n"
|
||||
" -u --user=USER Run the command under specified user or uid\n"
|
||||
" -M --machine=NAME Set the machine name for the container\n"
|
||||
" --hostname=NAME Override the hostname for the container\n"
|
||||
" --uuid=UUID Set a specific machine UUID for the container\n"
|
||||
" -S --slice=SLICE Place the container in the specified slice\n"
|
||||
" --property=NAME=VALUE Set scope unit property\n"
|
||||
@ -443,6 +445,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_ROOT_HASH,
|
||||
ARG_SYSTEM_CALL_FILTER,
|
||||
ARG_RLIMIT,
|
||||
ARG_HOSTNAME,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -466,6 +469,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "overlay", required_argument, NULL, ARG_OVERLAY },
|
||||
{ "overlay-ro", required_argument, NULL, ARG_OVERLAY_RO },
|
||||
{ "machine", required_argument, NULL, 'M' },
|
||||
{ "hostname", required_argument, NULL, ARG_HOSTNAME },
|
||||
{ "slice", required_argument, NULL, 'S' },
|
||||
{ "setenv", required_argument, NULL, 'E' },
|
||||
{ "selinux-context", required_argument, NULL, 'Z' },
|
||||
@ -701,6 +705,23 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_HOSTNAME:
|
||||
if (isempty(optarg))
|
||||
arg_hostname = mfree(arg_hostname);
|
||||
else {
|
||||
if (!hostname_is_valid(optarg, false)) {
|
||||
log_error("Invalid hostname: %s", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = free_and_strdup(&arg_hostname, optarg);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
arg_settings_mask |= SETTING_HOSTNAME;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
arg_selinux_context = optarg;
|
||||
break;
|
||||
@ -1762,7 +1783,7 @@ static int setup_hostname(void) {
|
||||
if ((arg_clone_ns_flags & CLONE_NEWUTS) == 0)
|
||||
return 0;
|
||||
|
||||
if (sethostname_idempotent(arg_machine) < 0)
|
||||
if (sethostname_idempotent(arg_hostname ?: arg_machine) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
@ -3314,6 +3335,10 @@ static int load_settings(void) {
|
||||
free_and_replace(arg_rlimit[rl], settings->rlimit[rl]);
|
||||
}
|
||||
|
||||
if ((arg_settings_mask & SETTING_HOSTNAME) == 0 &&
|
||||
settings->hostname)
|
||||
free_and_replace(arg_hostname, settings->hostname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4274,6 +4299,7 @@ finish:
|
||||
free(arg_template);
|
||||
free(arg_image);
|
||||
free(arg_machine);
|
||||
free(arg_hostname);
|
||||
free(arg_user);
|
||||
free(arg_pivot_root_new);
|
||||
free(arg_pivot_root_old);
|
||||
|
Loading…
x
Reference in New Issue
Block a user