Quoting Jan Kiszka (jan.kis...@siemens.com):
> 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.kis...@siemens.com>

Acked-by: Serge E. Hallyn <se...@hallyn.com>

> ---
>  doc/lxc.conf.sgml.in |   20 +++++++++++
>  src/lxc/conf.c       |   94 
> +++++++++++++++++++++++++++++++++++++++++++++++---
>  src/lxc/conf.h       |    6 +++-
>  src/lxc/confile.c    |    5 +++
>  src/lxc/start.c      |    7 +++-
>  5 files changed, 124 insertions(+), 8 deletions(-)
> 
> diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in
> index 9edabf8..2b1a4a5 100644
> --- a/doc/lxc.conf.sgml.in
> +++ b/doc/lxc.conf.sgml.in
> @@ -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>
>  
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index e8088bb..1043342 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -134,6 +134,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      },
> @@ -1606,6 +1620,8 @@ static int instanciate_veth(struct lxc_handler 
> *handler, struct lxc_netdev *netd
>       else {
>               snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
>               veth1 = mktemp(veth1buf);
> +             /* store away for deconf */
> +             memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
>       }
>  
>       snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
> @@ -1682,6 +1698,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;
> @@ -1728,6 +1763,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)
>  {
> @@ -1761,6 +1810,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) {
> @@ -1785,6 +1839,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;
> @@ -1798,6 +1865,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;
> @@ -1824,28 +1904,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);
>       }
>  }
> diff --git a/src/lxc/conf.h b/src/lxc/conf.h
> index 09f55cb..3f65d76 100644
> --- a/src/lxc/conf.h
> +++ b/src/lxc/conf.h
> @@ -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;
>  };
>  
>  /*
> @@ -224,7 +228,7 @@ struct lxc_conf {
>  extern struct lxc_conf *lxc_conf_init(void);
>  
>  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);
>  
> diff --git a/src/lxc/confile.c b/src/lxc/confile.c
> index b305aef..c5e7f47 100644
> --- a/src/lxc/confile.c
> +++ b/src/lxc/confile.c
> @@ -98,6 +98,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      },
> @@ -579,6 +580,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;
> diff --git a/src/lxc/start.c b/src/lxc/start.c
> index 920ff77..1295f41 100644
> --- a/src/lxc/start.c
> +++ b/src/lxc/start.c
> @@ -609,7 +609,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);
> @@ -641,7 +641,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);
> @@ -676,6 +676,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;
> -- 
> 1.7.3.4
> 
> ------------------------------------------------------------------------------
> Live Security Virtual Conference
> Exclusive live event will cover all the ways today's security and 
> threat landscape has changed and how IT managers can respond. Discussions 
> will include endpoint security, mobile security and the latest in malware 
> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
> _______________________________________________
> Lxc-devel mailing list
> Lxc-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to