]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
Add network-down script
authorJan Kiszka <jan.kiszka@siemens.com>
Mon, 9 Jul 2012 17:15:48 +0000 (19:15 +0200)
committerStéphane Graber <stgraber@ubuntu.com>
Mon, 12 Nov 2012 17:04:30 +0000 (12:04 -0500)
Analogously to lxc.network.script.up, add the ability to register a down
script. It is called before the guest network is finally destroyed,
allowing to clean up resources that are not reset/destroyed
automatically. Parameters of the down script are identical to the up
script except for the execution context "down".

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
doc/lxc.conf.sgml.in
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/start.c

index 05d6bc7f7fc87d0a5b2d3ea76af4dd0c2575604d..80c4335e34d39480c816407dad3a8db8c55e679d 100644 (file)
@@ -374,6 +374,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
            </para>
          </listitem>
        </varlistentry>
+
+       <varlistentry>
+         <term>
+           <option>lxc.network.script.down</option>
+         </term>
+         <listitem>
+           <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.
+           </para>
+         </listitem>
+       </varlistentry>
       </variablelist>
     </refsect2>
 
index b437654a386916111b433de3b41d8e42c87f6982..79fe4ad5a32a63e1968ff1e816861886f9bc0889 100644 (file)
@@ -138,6 +138,20 @@ static  instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
        [LXC_NET_EMPTY]   = instanciate_empty,
 };
 
+static int shutdown_veth(struct lxc_handler *, struct lxc_netdev *);
+static int shutdown_macvlan(struct lxc_handler *, struct lxc_netdev *);
+static int shutdown_vlan(struct lxc_handler *, struct lxc_netdev *);
+static int shutdown_phys(struct lxc_handler *, struct lxc_netdev *);
+static int shutdown_empty(struct lxc_handler *, struct lxc_netdev *);
+
+static  instanciate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
+       [LXC_NET_VETH]    = shutdown_veth,
+       [LXC_NET_MACVLAN] = shutdown_macvlan,
+       [LXC_NET_VLAN]    = shutdown_vlan,
+       [LXC_NET_PHYS]    = shutdown_phys,
+       [LXC_NET_EMPTY]   = shutdown_empty,
+};
+
 static struct mount_opt mount_opt[] = {
        { "defaults",      0, 0              },
        { "ro",            0, MS_RDONLY      },
@@ -1765,6 +1779,8 @@ static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
                        return -1;
                }
                veth1 = mktemp(veth1buf);
+               /* store away for deconf */
+               memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
        }
 
        snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
@@ -1841,6 +1857,25 @@ out_delete:
        return -1;
 }
 
+static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
+{
+       char *veth1;
+       int err;
+
+       if (netdev->priv.veth_attr.pair)
+               veth1 = netdev->priv.veth_attr.pair;
+       else
+               veth1 = netdev->priv.veth_attr.veth1;
+
+       if (netdev->downscript) {
+               err = run_script(handler->name, "net", netdev->downscript,
+                                "down", "veth", veth1, (char*) NULL);
+               if (err)
+                       return -1;
+       }
+       return 0;
+}
+
 static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        char peerbuf[IFNAMSIZ], *peer;
@@ -1889,6 +1924,20 @@ static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
        return 0;
 }
 
+static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
+{
+       int err;
+
+       if (netdev->downscript) {
+               err = run_script(handler->name, "net", netdev->downscript,
+                                "down", "macvlan", netdev->link,
+                                (char*) NULL);
+               if (err)
+                       return -1;
+       }
+       return 0;
+}
+
 /* XXX: merge with instanciate_macvlan */
 static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
@@ -1926,6 +1975,11 @@ static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
        return 0;
 }
 
+static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
+{
+       return 0;
+}
+
 static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        if (!netdev->link) {
@@ -1950,6 +2004,19 @@ static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
        return 0;
 }
 
+static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
+{
+       int err;
+
+       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 instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        netdev->ifindex = 0;
@@ -1963,6 +2030,19 @@ static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *net
        return 0;
 }
 
+static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
+{
+       int err;
+
+       if (netdev->downscript) {
+               err = run_script(handler->name, "net", netdev->downscript,
+                                "down", "empty", (char*) NULL);
+               if (err)
+                       return -1;
+       }
+       return 0;
+}
+
 int lxc_create_network(struct lxc_handler *handler)
 {
        struct lxc_list *network = &handler->conf->network;
@@ -1989,28 +2069,32 @@ int lxc_create_network(struct lxc_handler *handler)
        return 0;
 }
 
-void lxc_delete_network(struct lxc_list *network)
+void lxc_delete_network(struct lxc_handler *handler)
 {
+       struct lxc_list *network = &handler->conf->network;
        struct lxc_list *iterator;
        struct lxc_netdev *netdev;
 
        lxc_list_for_each(iterator, network) {
                netdev = iterator->elem;
-               if (netdev->ifindex == 0)
-                       continue;
 
-               if (netdev->type == LXC_NET_PHYS) {
+               if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
                        if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
                                WARN("failed to rename to the initial name the " \
                                     "netdev '%s'", netdev->link);
                        continue;
                }
 
+               if (netdev_deconf[netdev->type](handler, netdev)) {
+                       WARN("failed to destroy netdev");
+               }
+
                /* Recent kernel remove the virtual interfaces when the network
                 * namespace is destroyed but in case we did not moved the
                 * interface to the network namespace, we have to destroy it
                 */
-               if (lxc_netdev_delete_by_index(netdev->ifindex))
+               if (netdev->ifindex != 0 &&
+                   lxc_netdev_delete_by_index(netdev->ifindex))
                        WARN("failed to remove interface '%s'", netdev->name);
        }
 }
index ad48042af67ef6cb184d5e03e4dd37234adfd4f6..92efc585e14b66f505207c5570d655120dff8e3f 100644 (file)
@@ -24,6 +24,7 @@
 #define _conf_h
 
 #include <netinet/in.h>
+#include <net/if.h>
 #include <sys/param.h>
 #include <stdbool.h>
 
@@ -76,6 +77,7 @@ struct lxc_route6 {
 
 struct ifla_veth {
        char *pair; /* pair name */
+       char veth1[IFNAMSIZ]; /* needed for deconf */
 };
 
 struct ifla_vlan {
@@ -103,6 +105,7 @@ union netdev_p {
  * @ipv4       : a list of ipv4 addresses to be set on the network device
  * @ipv6       : a list of ipv6 addresses to be set on the network device
  * @upscript   : a script filename to be executed during interface configuration
+ * @downscript : a script filename to be executed during interface destruction
  */
 struct lxc_netdev {
        int type;
@@ -120,6 +123,7 @@ struct lxc_netdev {
        struct in6_addr *ipv6_gateway;
        bool ipv6_gateway_auto;
        char *upscript;
+       char *downscript;
 };
 
 /*
@@ -242,7 +246,7 @@ extern struct lxc_conf *lxc_conf_init(void);
 extern int pin_rootfs(const char *rootfs);
 
 extern int lxc_create_network(struct lxc_handler *handler);
-extern void lxc_delete_network(struct lxc_list *networks);
+extern void lxc_delete_network(struct lxc_handler *handler);
 extern int lxc_assign_network(struct lxc_list *networks, pid_t pid);
 extern int lxc_find_gateway_addresses(struct lxc_handler *handler);
 
index 2b5e73c91e44c4f8c1c02bf8e58a68e4e1629574..9e51a639254f89e7e70409fecf605807633e2ed8 100644 (file)
@@ -111,6 +111,7 @@ static struct config config[] = {
        { "lxc.network.macvlan.mode", config_network_macvlan_mode },
        { "lxc.network.veth.pair",    config_network_veth_pair    },
        { "lxc.network.script.up",    config_network_script       },
+       { "lxc.network.script.down",  config_network_script       },
        { "lxc.network.hwaddr",       config_network_hwaddr       },
        { "lxc.network.mtu",          config_network_mtu          },
        { "lxc.network.vlan.id",      config_network_vlan_id      },
@@ -595,6 +596,10 @@ static int config_network_script(const char *key, char *value,
                netdev->upscript = copy;
                return 0;
        }
+       if (strcmp(key, "lxc.network.script.down") == 0) {
+               netdev->downscript = copy;
+               return 0;
+       }
        SYSERROR("Unknown key: %s", key);
        free(copy);
        return -1;
index 60ac1096ba740a19c26a7ce39dd657283f7a3fd5..77755b979e9aca789aa98b9879cdf5fbebad31e5 100644 (file)
@@ -652,7 +652,7 @@ int lxc_spawn(struct lxc_handler *handler)
 
 out_delete_net:
        if (clone_flags & CLONE_NEWNET)
-               lxc_delete_network(&handler->conf->network);
+               lxc_delete_network(handler);
 out_abort:
        lxc_abort(name, handler);
        lxc_sync_fini(handler);
@@ -684,7 +684,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
        err = lxc_spawn(handler);
        if (err) {
                ERROR("failed to spawn '%s'", name);
-               goto out_fini;
+               goto out_fini_nonet;
        }
 
        err = lxc_poll(name, handler);
@@ -719,6 +719,9 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 
        err =  lxc_error_set_and_log(handler->pid, status);
 out_fini:
+       lxc_delete_network(handler);
+
+out_fini_nonet:
        lxc_cgroup_destroy(name);
        lxc_fini(name, handler);
        return err;