]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
network: pass info in env if hook version is 1
authorChristian Brauner <christian.brauner@ubuntu.com>
Tue, 12 Dec 2017 12:30:54 +0000 (13:30 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 14 Dec 2017 10:54:13 +0000 (11:54 +0100)
Unblocks #2013.
Unblocks #2015.
Closes #1766.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
doc/lxc.container.conf.sgml.in
src/lxc/conf.c
src/lxc/conf.h
src/lxc/lxccontainer.c
src/lxc/network.c
src/lxc/start.c

index 43df6a632569336bd3b9347531dacba81d64b441..4b97de611cfe4f46455b8b96020750fe27b24f1f 100644 (file)
@@ -308,9 +308,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       <title>Init ID</title>
       <para>
         Sets the UID/GID to use for the init system, and subsequent commands.
-        Note that using a non-root uid when booting a system container will
+        Note that using a non-root UID when booting a system container will
         likely not work due to missing privileges. Setting the UID/GID is mostly
-        useful when running application container.
+        useful when running application containers.
 
         Defaults to: UID(0), GID(0)
       </para>
@@ -608,7 +608,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
           </listitem>
         </varlistentry>
 
-
         <varlistentry>
           <term>
             <option>lxc.net.[i].ipv6.address</option>
@@ -651,15 +650,56 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
             <para>
               Add a configuration option to specify a script to be
               executed after creating and configuring the network used
-              from the host side. The following arguments are passed
-              to the script: container name and config section name
-              (net) Additional arguments depend on the config section
-              employing a script hook; the following are used by the
-              network system: execution context (up), network type
-              (empty/veth/macvlan/phys), Depending on the network
-              type, other arguments may be passed:
-              veth/macvlan/phys. And finally (host-sided) device name.
+              from the host side.
+            </para>
+
+            <para>
+              In addition to the information available to all hooks. The
+              following information is provided to the script:
+              <itemizedlist>
+                <listitem>
+                 <para>
+                 LXC_HOOK_TYPE: the hook type. This is either 'up' or 'down'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_HOOK_SECTION: the section type 'net'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_TYPE: the network type. This is one of the valid
+                 network types listed here (e.g. 'macvlan', 'veth').
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_PARENT: the parent device on the host. This is only
+                 set for network types 'mavclan', 'veth', 'phys'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_PEER: the name of the peer device on the host. This is
+                 only set for 'veth' network types. Note that this information
+                 is only available when <option>lxc.hook.version</option> is set
+                 to 1.
+                  </para>
+                </listitem>
+              </itemizedlist>
+
+              Whether this information is provided in the form of environment
+              variables or as arguments to the script depends on the value of
+              <option>lxc.hook.version</option>. If set to 1 then information is
+              provided in the form of environment variables. If set to 0
+              information is provided as arguments to the script.
             </para>
+
             <para>
               Standard output from the script is logged at debug level.
               Standard error is not logged, but can be captured by the
@@ -676,15 +716,56 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
             <para>
               Add a configuration option to specify a script to be
               executed before destroying the network used from the
-              host side. The following arguments are passed to the
-              script: container name and config section name (net)
-              Additional arguments depend on the config section
-              employing a script hook; the following are used by the
-              network system: execution context (down), network type
-              (empty/veth/macvlan/phys), Depending on the network
-              type, other arguments may be passed:
-              veth/macvlan/phys. And finally (host-sided) device name.
+              host side.
+            </para>
+
+            <para>
+              In addition to the information available to all hooks. The
+              following information is provided to the script:
+              <itemizedlist>
+                <listitem>
+                 <para>
+                 LXC_HOOK_TYPE: the hook type. This is either 'up' or 'down'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_HOOK_SECTION: the section type 'net'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_TYPE: the network type. This is one of the valid
+                 network types listed here (e.g. 'macvlan', 'veth').
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_PARENT: the parent device on the host. This is only
+                 set for network types 'mavclan', 'veth', 'phys'.
+                  </para>
+                </listitem>
+
+                <listitem>
+                 <para>
+                 LXC_NET_PEER: the name of the peer device on the host. This is
+                 only set for 'veth' network types. Note that this information
+                 is only available when <option>lxc.hook.version</option> is set
+                 to 1.
+                  </para>
+                </listitem>
+              </itemizedlist>
+
+              Whether this information is provided in the form of environment
+              variables or as arguments to the script depends on the value of
+              <option>lxc.hook.version</option>. If set to 1 then information is
+              provided in the form of environment variables. If set to 0
+              information is provided as arguments to the script.
             </para>
+
             <para>
               Standard output from the script is logged at debug level.
               Standard error is not logged, but can be captured by the
index 8e31275f6219fc53884f641765f788f34a986552..54b55acdae36793b67cfab76ec6af0ad17c4a26e 100644 (file)
@@ -339,10 +339,9 @@ static int run_buffer(char *buffer)
        return 0;
 }
 
-static int run_script_argv(const char *name, unsigned int hook_version,
-                          const char *section, const char *script,
-                          const char *hookname, const char *lxcpath,
-                          char **argsin)
+int run_script_argv(const char *name, unsigned int hook_version,
+                   const char *section, const char *script,
+                   const char *hookname, char **argsin)
 {
        int buf_pos, i, ret;
        char *buffer;
@@ -405,6 +404,59 @@ static int run_script_argv(const char *name, unsigned int hook_version,
                        return -1;
                }
                TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
+
+               if (strcmp(section, "net") == 0) {
+                       char *parent;
+
+                       if (!argsin[0])
+                               return -EINVAL;
+
+                       ret = setenv("LXC_NET_TYPE", argsin[0], 1);
+                       if (ret < 0) {
+                               SYSERROR("Failed to set environment variable: "
+                                        "LXC_NET_TYPE=%s", argsin[0]);
+                               return -1;
+                       }
+                       TRACE("Set environment variable: LXC_NET_TYPE=%s", argsin[0]);
+
+                       parent = argsin[1] ? argsin[1] : "";
+
+                       if (strcmp(argsin[0], "macvlan")) {
+                               ret = setenv("LXC_NET_PARENT", parent, 1);
+                               if (ret < 0) {
+                                       SYSERROR("Failed to set environment "
+                                                "variable: LXC_NET_PARENT=%s", parent);
+                                       return -1;
+                               }
+                               TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
+                       } else if (strcmp(argsin[0], "phys")) {
+                               ret = setenv("LXC_NET_PARENT", parent, 1);
+                               if (ret < 0) {
+                                       SYSERROR("Failed to set environment "
+                                                "variable: LXC_NET_PARENT=%s", parent);
+                                       return -1;
+                               }
+                               TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
+                       } else if (strcmp(argsin[0], "veth")) {
+                               char *peer = argsin[2] ? argsin[2] : "";
+
+                               ret = setenv("LXC_NET_PEER", peer, 1);
+                               if (ret < 0) {
+                                       SYSERROR("Failed to set environment "
+                                                "variable: LXC_NET_PEER=%s", peer);
+                                       return -1;
+                               }
+                               TRACE("Set environment variable: LXC_NET_PEER=%s", peer);
+
+                               ret = setenv("LXC_NET_PARENT", parent, 1);
+                               if (ret < 0) {
+                                       SYSERROR("Failed to set environment "
+                                                "variable: LXC_NET_PARENT=%s", parent);
+                                       return -1;
+                               }
+                               TRACE("Set environment variable: LXC_NET_PARENT=%s", parent);
+                       }
+               }
        }
 
        for (i = 0; argsin && argsin[i]; i++) {
@@ -3099,7 +3151,7 @@ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath
 
        remount_all_slave();
 
-       if (run_lxc_hooks(name, "pre-mount", conf, lxcpath, NULL)) {
+       if (run_lxc_hooks(name, "pre-mount", conf, NULL)) {
                ERROR("failed to run pre-mount hooks for container '%s'.", name);
                return -1;
        }
@@ -3208,13 +3260,13 @@ int lxc_setup(struct lxc_handler *handler)
                return -1;
        }
 
-       if (run_lxc_hooks(name, "mount", lxc_conf, lxcpath, NULL)) {
+       if (run_lxc_hooks(name, "mount", lxc_conf, NULL)) {
                ERROR("failed to run mount hooks for container '%s'.", name);
                return -1;
        }
 
        if (lxc_conf->autodev > 0) {
-               if (run_lxc_hooks(name, "autodev", lxc_conf, lxcpath, NULL)) {
+               if (run_lxc_hooks(name, "autodev", lxc_conf, NULL)) {
                        ERROR("failed to run autodev hooks for container '%s'.", name);
                        return -1;
                }
@@ -3292,7 +3344,7 @@ int lxc_setup(struct lxc_handler *handler)
 }
 
 int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf,
-                 const char *lxcpath, char *argv[])
+                 char *argv[])
 {
        struct lxc_list *it;
        int which = -1;
@@ -3325,7 +3377,7 @@ int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf,
                char *hook = it->elem;
 
                ret = run_script_argv(name, conf->hooks_version, "lxc", hook,
-                                     hookname, lxcpath, argv);
+                                     hookname, argv);
                if (ret < 0)
                        return -1;
        }
index d4b48cc404588785b87fb4f1c26855c0e9b602ee..b7ddf1d3f434dedf95847115dfa113780cfcb368 100644 (file)
@@ -412,7 +412,7 @@ extern struct lxc_conf *current_config;
 #endif
 
 extern int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf,
-                        const char *lxcpath, char *argv[]);
+                        char *argv[]);
 extern int detect_shared_rootfs(void);
 extern struct lxc_conf *lxc_conf_init(void);
 extern void lxc_conf_free(struct lxc_conf *conf);
@@ -457,6 +457,9 @@ extern unsigned long add_required_remount_flags(const char *s, const char *d,
                                                unsigned long flags);
 extern int run_script(const char *name, const char *section, const char *script,
                      ...);
+extern int run_script_argv(const char *name, unsigned int hook_version,
+                          const char *section, const char *script,
+                          const char *hookname, char **argsin);
 extern int in_caplist(int cap, struct lxc_list *caps);
 extern int setup_sysctl_parameters(struct lxc_list *sysctls);
 extern int lxc_clear_sysctls(struct lxc_conf *c, const char *key);
index c134947b2d768880939e778a8204008eb70a32c7..2a578ea65b6cdc11ecd33c77ec8c38330a2ef22f 100644 (file)
@@ -2746,7 +2746,7 @@ static bool container_destroy(struct lxc_container *c,
                        SYSERROR("Failed to set environment variable for console log");
                /* End of environment variable setup for hooks */
 
-               if (run_lxc_hooks(c->name, "destroy", conf, c->get_config_path(c), NULL)) {
+               if (run_lxc_hooks(c->name, "destroy", conf, NULL)) {
                        ERROR("Failed to execute clone hook for \"%s\"", c->name);
                        goto out;
                }
@@ -3458,7 +3458,7 @@ static int clone_update_rootfs(struct clone_update_data *data)
                        SYSERROR("failed to set environment variable for rootfs mount");
                }
 
-               if (run_lxc_hooks(c->name, "clone", conf, c->get_config_path(c), hookargs)) {
+               if (run_lxc_hooks(c->name, "clone", conf, hookargs)) {
                        ERROR("Error executing clone hook for %s", c->name);
                        storage_put(bdev);
                        return -1;
index 23febe6d22fb7e9d96e6ae986a1a66160beee6ce..2e397ad4c046c5492ee7f47da84ec25b53b2c798 100644 (file)
@@ -204,9 +204,17 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
        }
 
        if (netdev->upscript) {
-               err = run_script(handler->name, "net", netdev->upscript, "up",
-                                "veth", veth1, (char*) NULL);
-               if (err)
+               char *argv[] = {
+                   "veth",
+                   netdev->link,
+                   "veth1",
+                   NULL,
+               };
+
+               err = run_script_argv(handler->name,
+                               handler->conf->hooks_version, "net",
+                               netdev->upscript, "up", argv);
+               if (err < 0)
                        goto out_delete;
        }
 
@@ -254,9 +262,16 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
        }
 
        if (netdev->upscript) {
-               err = run_script(handler->name, "net", netdev->upscript, "up",
-                                "macvlan", netdev->link, (char*) NULL);
-               if (err)
+               char *argv[] = {
+                   "macvlan",
+                   netdev->link,
+                   NULL,
+               };
+
+               err = run_script_argv(handler->name,
+                               handler->conf->hooks_version, "net",
+                               netdev->upscript, "up", argv);
+               if (err < 0)
                        goto on_error;
        }
 
@@ -323,6 +338,13 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
 
 static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
+       int ret;
+       char *argv[] = {
+               "phys",
+               netdev->link,
+               NULL,
+       };
+
        if (netdev->link[0] == '\0') {
                ERROR("No link for physical interface specified");
                return -1;
@@ -346,27 +368,34 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
         */
        netdev->priv.phys_attr.ifindex = netdev->ifindex;
 
-       if (netdev->upscript) {
-               int err;
-               err = run_script(handler->name, "net", netdev->upscript,
-                                "up", "phys", netdev->link, (char*) NULL);
-               if (err)
-                       return -1;
-       }
+       if (!netdev->upscript)
+               return 0;
+
+       ret = run_script_argv(handler->name, handler->conf->hooks_version,
+                             "net", netdev->upscript, "up", argv);
+       if (ret < 0)
+               return -1;
 
        return 0;
 }
 
 static int instantiate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
+       int ret;
+       char *argv[] = {
+           "empty",
+           NULL,
+       };
+
        netdev->ifindex = 0;
-       if (netdev->upscript) {
-               int err;
-               err = run_script(handler->name, "net", netdev->upscript,
-                                "up", "empty", (char*) NULL);
-               if (err)
-                       return -1;
-       }
+       if (!netdev->upscript)
+               return 0;
+
+       ret = run_script_argv(handler->name, handler->conf->hooks_version,
+                             "net", netdev->upscript, "up", argv);
+       if (ret < 0)
+               return -1;
+
        return 0;
 }
 
@@ -387,34 +416,48 @@ static  instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
 
 static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
-       char *veth1;
-       int err;
+       int ret;
+       char *argv[] = {
+           "veth",
+           netdev->link,
+           NULL,
+           NULL,
+       };
+
+       if (!netdev->downscript)
+               return 0;
 
        if (netdev->priv.veth_attr.pair[0] != '\0')
-               veth1 = netdev->priv.veth_attr.pair;
+               argv[2] = netdev->priv.veth_attr.pair;
        else
-               veth1 = netdev->priv.veth_attr.veth1;
+               argv[2] = netdev->priv.veth_attr.veth1;
+
+       ret = run_script_argv(handler->name,
+                       handler->conf->hooks_version, "net",
+                       netdev->downscript, "down", argv);
+       if (ret < 0)
+               return -1;
 
-       if (netdev->downscript) {
-               err = run_script(handler->name, "net", netdev->downscript,
-                                "down", "veth", veth1, (char*) NULL);
-               if (err)
-                       return -1;
-       }
        return 0;
 }
 
 static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
-       int err;
+       int ret;
+       char *argv[] = {
+               "macvlan",
+               netdev->link,
+               NULL,
+       };
+
+       if (!netdev->downscript)
+               return 0;
+
+       ret = run_script_argv(handler->name, handler->conf->hooks_version,
+                             "net", netdev->downscript, "down", argv);
+       if (ret < 0)
+               return -1;
 
-       if (netdev->downscript) {
-               err = run_script(handler->name, "net", netdev->downscript,
-                                "down", "macvlan", netdev->link,
-                                (char*) NULL);
-               if (err)
-                       return -1;
-       }
        return 0;
 }
 
@@ -425,27 +468,40 @@ static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 
 static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
-       int err;
+       int ret;
+       char *argv[] = {
+           "phys",
+           netdev->link,
+           NULL,
+       };
+
+       if (!netdev->downscript)
+               return 0;
+
+       ret = run_script_argv(handler->name, handler->conf->hooks_version,
+                             "net", netdev->downscript, "down", argv);
+       if (ret < 0)
+               return -1;
 
-       if (netdev->downscript) {
-               err = run_script(handler->name, "net", netdev->downscript,
-                                "down", "phys", netdev->link, (char*) NULL);
-               if (err)
-                       return -1;
-       }
        return 0;
 }
 
 static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
-       int err;
+       int ret;
+       char *argv[] = {
+           "empty",
+           NULL,
+       };
+
+       if (!netdev->downscript)
+               return 0;
+
+       ret = run_script_argv(handler->name, handler->conf->hooks_version,
+                             "net", netdev->downscript, "down", argv);
+       if (ret < 0)
+               return -1;
 
-       if (netdev->downscript) {
-               err = run_script(handler->name, "net", netdev->downscript,
-                                "down", "empty", (char*) NULL);
-               if (err)
-                       return -1;
-       }
        return 0;
 }
 
index b29540603be134abc227c2f6b756570b56400d24..5052e2d5a7a9034f014acd1ea56b5962e43a95b8 100644 (file)
@@ -668,7 +668,7 @@ int lxc_init(const char *name, struct lxc_handler *handler)
 
        TRACE("set environment variables");
 
-       if (run_lxc_hooks(name, "pre-start", conf, handler->lxcpath, NULL)) {
+       if (run_lxc_hooks(name, "pre-start", conf, NULL)) {
                ERROR("Failed to run lxc.hook.pre-start for container \"%s\".", name);
                goto out_aborting;
        }
@@ -767,9 +767,9 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
                SYSERROR("Failed to set environment variable: LXC_TARGET=stop.");
 
        if (handler->conf->hooks_version == 0)
-               rc = run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, namespaces);
+               rc = run_lxc_hooks(name, "stop", handler->conf, namespaces);
        else
-               rc = run_lxc_hooks(name, "stop", handler->conf, handler->lxcpath, NULL);
+               rc = run_lxc_hooks(name, "stop", handler->conf, NULL);
 
        while (namespace_count--)
                free(namespaces[namespace_count]);
@@ -792,7 +792,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
                handler->conf->maincmd_fd = -1;
        }
 
-       if (run_lxc_hooks(name, "post-stop", handler->conf, handler->lxcpath, NULL)) {
+       if (run_lxc_hooks(name, "post-stop", handler->conf, NULL)) {
                ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", name);
                if (handler->conf->reboot) {
                        WARN("Container will be stopped instead of rebooted.");
@@ -1053,7 +1053,7 @@ static int do_start(void *data)
        if (lxc_seccomp_load(handler->conf) != 0)
                goto out_warn_father;
 
-       if (run_lxc_hooks(handler->name, "start", handler->conf, handler->lxcpath, NULL)) {
+       if (run_lxc_hooks(handler->name, "start", handler->conf, NULL)) {
                ERROR("Failed to run lxc.hook.start for container \"%s\".", handler->name);
                goto out_warn_father;
        }
@@ -1513,7 +1513,7 @@ static int lxc_spawn(struct lxc_handler *handler)
                SYSERROR("Failed to set environment variable: LXC_PID=%s.", pidstr);
 
        /* Run any host-side start hooks */
-       if (run_lxc_hooks(name, "start-host", conf, handler->lxcpath, NULL)) {
+       if (run_lxc_hooks(name, "start-host", conf, NULL)) {
                ERROR("Failed to run lxc.hook.start-host for container \"%s\".", name);
                return -1;
        }