]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
c/r: refactor the way we pass data to criu/scripts
authorTycho Andersen <tycho.andersen@canonical.com>
Thu, 16 Oct 2014 13:13:59 +0000 (13:13 +0000)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Fri, 17 Oct 2014 13:22:02 +0000 (15:22 +0200)
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@canonical.com>
Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
src/lxc/lxc-restore-net
src/lxc/lxccontainer.c

index 7d4558399ae967fe7349adf4167328008df27f47..1725dc3a9cddbd6cb3927273d9c85f75edc505a4 100755 (executable)
@@ -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
index c4cb0ab3c3cf9ead2f3e4fd4f298e736f85adaa0..d1f41c7f2141581f568d506527b28178d7f82356 100644 (file)
@@ -55,6 +55,7 @@
 #include "attach.h"
 #include "monitor.h"
 #include "namespace.h"
+#include "network.h"
 #include "lxclock.h"
 #include "sync.h"
 
@@ -3536,37 +3537,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 \
@@ -3648,9 +3624,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");
@@ -3661,18 +3634,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;
@@ -3682,12 +3661,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++)
@@ -3771,10 +3781,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;
@@ -3783,10 +3789,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;
@@ -3794,10 +3796,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)
@@ -3856,30 +3854,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;
@@ -3922,6 +3914,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;
@@ -3992,11 +3989,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;
                        }