]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: make the hostname of the container explicitly configurable with a new --hostn...
authorLennart Poettering <lennart@poettering.net>
Mon, 7 May 2018 16:37:32 +0000 (18:37 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 17 May 2018 18:46:45 +0000 (20:46 +0200)
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.

man/systemd-nspawn.xml
man/systemd.nspawn.xml
src/nspawn/nspawn-gperf.gperf
src/nspawn/nspawn-settings.c
src/nspawn/nspawn-settings.h
src/nspawn/nspawn.c

index c6b027c58f72931429eaa929651e7f29d4048d8c..16d65d2b29c58465732e1afedd5dd23d5e7fa39c 100644 (file)
         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>
 
index 6bd7b33b34b432c15173944f8725bbc8b16fdfc4..3f8c325fd9cbeb4688c06cd881f15b88b431d76e 100644 (file)
         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>
 
index 58184d412d16c110700747c82d0cbd0739887912..f7d2e1a5155b5f71b5e3dde02e2e9f90d1dd4dab 100644 (file)
@@ -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
index 19bf1d4b941e015b99799a1e7c62ae648277f467..3757380e282639504d9664cd43c74bf3f6973ee9 100644 (file)
@@ -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;
+}
index 0e6ce6121718b4a36ae6138dbf79c266757cd780..3d3ee4c28cd5aed7860449371947c8e4e948a992 100644 (file)
@@ -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);
index 8ba8e73bf73e3c8a6dae935c2bbb0304fef6e873..7357576a2ad5e87474ccaa01b56e5fcd448230b8 100644 (file)
@@ -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);