[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