[lxc-devel] [PATCH 1/2] c/r: refactor the way we pass data to criu/scripts

Serge Hallyn serge.hallyn at ubuntu.com
Fri Oct 17 12:50:07 UTC 2014


Quoting Tycho Andersen (tycho.andersen at canonical.com):
> We previously wrote a bunch of files (eth*, veth*, and bridge*) as hard coded
> files which we used as the names of interfaces to restore via criu's
> --veth-pair. This meant that if people, e.g. gave a different bridge on their
> new host, we would use our saved bridge in bridge* and try to restore to the
> wrong bridge. Instead, we can just generate a new veth id (if the user hasn't
> provided one), and use whatever the user configured values for the interface
> name and bridge are.
> 
> This allows people to switch the bridge that they restore onto simply by
> migrating the rootfs and config, and then changing the bridge name in the
> container's configuration before running lxc-checkpoint.
> 
> Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>

Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>

> ---
>  src/lxc/lxc-restore-net |  16 +++---
>  src/lxc/lxccontainer.c  | 126 +++++++++++++++++++++++-------------------------
>  2 files changed, 68 insertions(+), 74 deletions(-)
> 
> diff --git a/src/lxc/lxc-restore-net b/src/lxc/lxc-restore-net
> index 7d45583..1725dc3 100755
> --- a/src/lxc/lxc-restore-net
> +++ b/src/lxc/lxc-restore-net
> @@ -1,15 +1,15 @@
>  #!/bin/sh
>  
> -[ -z "$CRTOOLS_IMAGE_DIR" ] && exit 1
> -
>  set -e
>  
> -dir="$CRTOOLS_IMAGE_DIR"
> -
>  i=0
> -while [ -f "$dir/eth$i" ] && [ -f "$dir/veth$i" ] && [ -f "$dir/bridge$i" ]; do
> -	veth=$(cat "$dir/veth$i")
> -	bridge=$(cat "$dir/bridge$i")
> +while true; do
> +	eval "bridge=\$LXC_CRIU_BRIDGE$i"
> +	eval "veth=\$LXC_CRIU_VETH$i"
> +
> +	if [ -z "$bridge" ] || [ -z "$veth" ]; then
> +		exit 0
> +	fi
>  
>  	if [ "$CRTOOLS_SCRIPT_ACTION" = "network-lock" ]; then
>  		brctl delif $bridge $veth
> @@ -22,3 +22,5 @@ while [ -f "$dir/eth$i" ] && [ -f "$dir/veth$i" ] && [ -f "$dir/bridge$i" ]; do
>  
>  	i=$((i+1))
>  done
> +
> +exit 1
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index 703042a..61d06ea 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -54,6 +54,7 @@
>  #include "attach.h"
>  #include "monitor.h"
>  #include "namespace.h"
> +#include "network.h"
>  #include "lxclock.h"
>  #include "sync.h"
>  
> @@ -3488,37 +3489,12 @@ struct criu_opts {
>  	const char *cgroup_path;
>  };
>  
> -/*
> - * @out must be 128 bytes long
> - */
> -static int read_criu_file(const char *directory, const char *file, int netnr, char *out)
> -{
> -	char path[PATH_MAX];
> -	int ret;
> -	FILE *f;
> -
> -	ret = snprintf(path, PATH_MAX,  "%s/%s%d", directory, file, netnr);
> -	if (ret < 0 || ret >= PATH_MAX) {
> -		ERROR("%s: path too long", __func__);
> -		return -1;
> -	}
> -
> -	f = fopen(path, "r");
> -	if (!f)
> -		return -1;
> -
> -	ret = fscanf(f, "%127s", out);
> -	fclose(f);
> -	if (ret <= 0)
> -		return -1;
> -
> -	return 0;
> -}
> -
>  static void exec_criu(struct criu_opts *opts)
>  {
> -	char **argv, log[PATH_MAX];
> +	char **argv, log[PATH_MAX], buf[257];
>  	int static_args = 14, argc = 0, i, ret;
> +	int netnr = 0;
> +	struct lxc_list *it;
>  
>  	/* The command line always looks like:
>  	 * criu $(action) --tcp-established --file-locks --link-remap --force-irmap \
> @@ -3600,9 +3576,6 @@ static void exec_criu(struct criu_opts *opts)
>  		if (!opts->stop)
>  			DECLARE_ARG("--leave-running");
>  	} else if (strcmp(opts->action, "restore") == 0) {
> -		int netnr = 0;
> -		struct lxc_list *it;
> -
>  		DECLARE_ARG("--root");
>  		DECLARE_ARG(opts->c->lxc_conf->rootfs.mount);
>  		DECLARE_ARG("--restore-detached");
> @@ -3613,18 +3586,24 @@ static void exec_criu(struct criu_opts *opts)
>  		DECLARE_ARG(opts->cgroup_path);
>  
>  		lxc_list_for_each(it, &opts->c->lxc_conf->network) {
> -			char eth[128], veth[128], buf[257];
> +			char eth[128], *veth;
>  			void *m;
> +			struct lxc_netdev *n = it->elem;
> +
> +			if (n->name) {
> +				if (strlen(n->name) >= 128)
> +					goto err;
> +				strncpy(eth, n->name, 128);
> +			} else
> +				sprintf(eth, "eth%d", netnr);
> +
> +			veth = n->priv.veth_attr.pair;
>  
> -			if (read_criu_file(opts->directory, "veth", netnr, veth))
> -				goto err;
> -			if (read_criu_file(opts->directory, "eth", netnr, eth))
> -				goto err;
>  			ret = snprintf(buf, 257, "%s=%s", eth, veth);
>  			if (ret < 0 || ret >= 257)
>  				goto err;
>  
> -			/* final NULL and --veth-pair eth0:vethASDF */
> +			/* final NULL and --veth-pair eth0=vethASDF */
>  			m = realloc(argv, (argc + 1 + 2) * sizeof(*argv));
>  			if (!m)
>  				goto err;
> @@ -3634,12 +3613,43 @@ static void exec_criu(struct criu_opts *opts)
>  			DECLARE_ARG(buf);
>  			argv[argc] = NULL;
>  
> -			netnr++;
>  		}
>  	}
>  
> -#undef DECLARE_ARG
> +	netnr = 0;
> +	lxc_list_for_each(it, &opts->c->lxc_conf->network) {
> +		struct lxc_netdev *n = it->elem;
> +		char veth[128];
> +
> +		/*
> +		 * Here, we set some parameters that lxc-restore-net
> +		 * will examine to figure out the right network to
> +		 * restore.
> +		 */
> +		snprintf(buf, sizeof(buf), "LXC_CRIU_BRIDGE%d", netnr);
> +		if (setenv(buf, n->link, 1))
> +			goto err;
> +
> +		if (strcmp("restore", opts->action) == 0)
> +			strncpy(veth, n->priv.veth_attr.pair, sizeof(veth));
> +		else {
> +			char *tmp;
> +			ret = snprintf(buf, sizeof(buf), "lxc.network.%d.veth.pair", netnr);
> +			if (ret < 0 || ret >= sizeof(buf))
> +				goto err;
> +			tmp = lxcapi_get_running_config_item(opts->c, buf);
> +			strncpy(veth, tmp, sizeof(veth));
> +			free(tmp);
> +		}
> +
> +		snprintf(buf, sizeof(buf), "LXC_CRIU_VETH%d", netnr);
> +		if (setenv(buf, veth, 1))
> +			goto err;
>  
> +		netnr++;
> +	}
> +
> +#undef DECLARE_ARG
>  	execv(argv[0], argv);
>  err:
>  	for (i = 0; argv[i]; i++)
> @@ -3723,10 +3733,6 @@ static bool dump_net_info(struct lxc_container *c, char *directory)
>  			break;
>  		}
>  
> -		pret = snprintf(veth_path, PATH_MAX, "lxc.network.%d.link", netnr);
> -		if (pret < 0 || pret >= PATH_MAX)
> -			goto out;
> -
>  		bridge = lxcapi_get_running_config_item(c, veth_path);
>  		if (!bridge)
>  			goto out;
> @@ -3735,10 +3741,6 @@ static bool dump_net_info(struct lxc_container *c, char *directory)
>  		if (pret < 0 || pret >= PATH_MAX || print_to_file(veth_path, veth) < 0)
>  			goto out;
>  
> -		pret = snprintf(veth_path, PATH_MAX, "%s/bridge%d", directory, netnr);
> -		if (pret < 0 || pret >= PATH_MAX || print_to_file(veth_path, bridge) < 0)
> -			goto out;
> -
>  		if (n->name) {
>  			if (strlen(n->name) >= 128)
>  				goto out;
> @@ -3746,10 +3748,6 @@ static bool dump_net_info(struct lxc_container *c, char *directory)
>  		} else
>  			sprintf(eth, "eth%d", netnr);
>  
> -		pret = snprintf(veth_path, PATH_MAX, "%s/eth%d", directory, netnr);
> -		if (pret < 0 || pret >= PATH_MAX || print_to_file(veth_path, eth) < 0)
> -			goto out;
> -
>  		has_error = false;
>  out:
>  		if (veth)
> @@ -3808,30 +3806,24 @@ static bool lxcapi_checkpoint(struct lxc_container *c, char *directory, bool sto
>  	}
>  }
>  
> -static bool restore_net_info(struct lxc_container *c, char *directory)
> +static bool restore_net_info(struct lxc_container *c)
>  {
>  	struct lxc_list *it;
>  	bool has_error = true;
> -	int netnr = 0;
>  
>  	if (container_mem_lock(c))
>  		return false;
>  
>  	lxc_list_for_each(it, &c->lxc_conf->network) {
> -		char eth[128], veth[128];
>  		struct lxc_netdev *netdev = it->elem;
> +		char template[IFNAMSIZ];
> +		snprintf(template, sizeof(template), "vethXXXXXX");
>  
> -		if (read_criu_file(directory, "veth", netnr, veth))
> -			goto out_unlock;
> -
> -		if (read_criu_file(directory, "eth", netnr, eth))
> -			goto out_unlock;
> +		if (!netdev->priv.veth_attr.pair)
> +			netdev->priv.veth_attr.pair = lxc_mkifname(template);
>  
> -		netdev->priv.veth_attr.pair = strdup(veth);
>  		if (!netdev->priv.veth_attr.pair)
>  			goto out_unlock;
> -
> -		netnr++;
>  	}
>  
>  	has_error = false;
> @@ -3874,6 +3866,11 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
>  		goto out_fini_handler;
>  	}
>  
> +	if (!restore_net_info(c)) {
> +		ERROR("failed restoring network info");
> +		goto out_fini_handler;
> +	}
> +
>  	pid = fork();
>  	if (pid < 0)
>  		goto out_fini_handler;
> @@ -3944,11 +3941,6 @@ static bool lxcapi_restore(struct lxc_container *c, char *directory, bool verbos
>  					goto out_fini_handler;
>  				}
>  
> -				if (!restore_net_info(c, directory)) {
> -					ERROR("failed restoring network info");
> -					goto out_fini_handler;
> -				}
> -
>  				if (lxc_set_state(c->name, handler, RUNNING))
>  					goto out_fini_handler;
>  			}
> -- 
> 1.9.1
> 
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel


More information about the lxc-devel mailing list