[lxc-devel] [PATCH] Add network-down script

Serge Hallyn serge.hallyn at canonical.com
Mon Jul 9 17:33:17 UTC 2012


Quoting Jan Kiszka (jan.kiszka at 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.kiszka at siemens.com>

Acked-by: Serge E. Hallyn <serge at 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 at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel




More information about the lxc-devel mailing list