We currently support /etc/lxc/lxc.conf containing a customizable default lxcpath. With this patch, /etc/lxc/lxc.conf can also contain
zfsroot = custom1 lvm_vg = vg0 Otherwise the defaults are 'lxc' for lvm_vg, and 'lxc' for zfsroot. Note - I'm stacking these patches up at github.com/hallyn/lxc #s.b.clone2 With these patches, I can # create a regular directory-backed container lxc-create -t ubuntu -n dir1 # clone onto an lvm container lxc-clone -B lvm dir1 lvm1 # create a snapshot of the lvm container lxc-clone -s lvm1 lvm2 lxc-destroy -n lvm1 # refused, lvm2 snapshot depends on lvm1 # Create a zfs backed container lxc-clone -B zfs dir1 zfs1 # Create a snapshot of the zfs container lxc-clone -s zfs1 zfs2 # Create an overlayfs snapshot overlayind dir1 lxc-clone -s -B overlayfs dir1 o1 # Create a clone of o1 lxc-clone -s o1 o2 # convert overlayfs back into plain dir for easy tar'ing lxc-clone -B dir o2 dir3 # after mounting a btrfs filesystem at /home/serge/lxcbase # clone dir1 to a btrfs backed container lxc-clone -B btrfs -P /home/serge/lxcbase dir1 btr1 # create a snapshot of the btrfs container lxc-clone -s -p /home/serge/lxcbase btr1 btr2 A single command to tar up a container (config+rootfs) for easy shipping to another host should, from here, be a short python script using the clone api. Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com> --- src/lxc/bdev.c | 39 +++++++++++++++--------------- src/lxc/utils.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/utils.h | 2 ++ 3 files changed, 94 insertions(+), 20 deletions(-) diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c index 4ba550c..a3577a2 100644 --- a/src/lxc/bdev.c +++ b/src/lxc/bdev.c @@ -492,34 +492,33 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname, { // use the 'zfs list | grep opath' entry to get the zfsroot char output[MAXPATHLEN], option[MAXPATHLEN], *p; + const char *zfsroot = output; int ret; pid_t pid; - if (!zfs_list_entry(opath, output)) - // default is tank. I'd prefer lxc, but apparently this is - // tradition. - sprintf(output, "tank"); - - if ((p = index(output, ' ')) == NULL) - return -1; - *p = '\0'; - if ((p = rindex(output, '/')) == NULL) - return -1; - *p = '\0'; + if (zfs_list_entry(opath, output)) { + // zfsroot is output up to ' ' + if ((p = index(output, ' ')) == NULL) + return -1; + *p = '\0'; + if ((p = rindex(output, '/')) == NULL) + return -1; + *p = '\0'; + } else + zfsroot = default_zfs_root(); ret = snprintf(option, MAXPATHLEN, "-omountpoint=%s/%s/rootfs", lxcpath, nname); if (ret < 0 || ret >= MAXPATHLEN) return -1; - // zfsroot is output up to ' ' // zfs create -omountpoint=$lxcpath/$lxcname $zfsroot/$nname if (!snapshot) { if ((pid = fork()) < 0) return -1; if (!pid) { char dev[MAXPATHLEN]; - ret = snprintf(dev, MAXPATHLEN, "%s/%s", output, nname); + ret = snprintf(dev, MAXPATHLEN, "%s/%s", zfsroot, nname); if (ret < 0 || ret >= MAXPATHLEN) exit(1); execlp("zfs", "zfs", "create", option, dev, NULL); @@ -532,11 +531,11 @@ static int zfs_clone(const char *opath, const char *npath, const char *oname, // zfs clone zfsroot/oname@nname zfsroot/nname char path1[MAXPATHLEN], path2[MAXPATHLEN]; - ret = snprintf(path1, MAXPATHLEN, "%s/%s@%s", output, + ret = snprintf(path1, MAXPATHLEN, "%s/%s@%s", zfsroot, oname, nname); if (ret < 0 || ret >= MAXPATHLEN) return -1; - (void) snprintf(path2, MAXPATHLEN, "%s/%s", output, nname); + (void) snprintf(path2, MAXPATHLEN, "%s/%s", zfsroot, nname); // if the snapshot exists, delete it if ((pid = fork()) < 0) @@ -758,18 +757,18 @@ static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldna return -1; if (strcmp(orig->type, "lvm")) { + const char *vg; + if (snap) { ERROR("LVM snapshot from %s backing store is not supported", orig->type); return -1; } - // Use VG 'lxc' by default - // We will want to support custom VGs, at least as specified through - // /etc/lxc/lxc.conf, preferably also over cmdline - len = strlen("/dev/lxc/") + strlen(cname) + 1; + vg = default_lvm_vg(); + len = strlen("/dev/") + strlen(vg) + strlen(cname) + 2; if ((new->src = malloc(len)) == NULL) return -1; - ret = snprintf(new->src, len, "/dev/lxc/%s", cname); + ret = snprintf(new->src, len, "/dev/%s/%s", vg, cname); if (ret < 0 || ret >= len) return -1; } else { diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 2fa2b0c..be1ce88 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -137,7 +137,80 @@ static char *copypath(char *p) } char *default_lxcpath; +#define DEFAULT_VG "lxc" +char *default_lvmvg; +#define DEFAULT_ZFSROOT "lxc" +char *default_zfsroot; +const char *default_lvm_vg(void) +{ + char buf[1024], *p; + FILE *fin; + + if (default_lvmvg) + return default_lvmvg; + + fin = fopen(LXC_GLOBAL_CONF, "r"); + if (fin) { + while (fgets(buf, 1024, fin)) { + if (buf[0] == '#') + continue; + p = strstr(buf, "lvm_vg"); + if (!p) + continue; + p = strchr(p, '='); + if (!p) + continue; + p++; + while (*p && (*p == ' ' || *p == '\t')) p++; + if (!*p) + continue; + default_lvmvg = copypath(p); + goto out; + } + } + default_lvmvg = DEFAULT_VG; + +out: + if (fin) + fclose(fin); + return default_lvmvg; +} + +const char *default_zfs_root(void) +{ + char buf[1024], *p; + FILE *fin; + + if (default_zfsroot) + return default_zfsroot; + + fin = fopen(LXC_GLOBAL_CONF, "r"); + if (fin) { + while (fgets(buf, 1024, fin)) { + if (buf[0] == '#') + continue; + p = strstr(buf, "zfsroot"); + if (!p) + continue; + p = strchr(p, '='); + if (!p) + continue; + p++; + while (*p && (*p == ' ' || *p == '\t')) p++; + if (!*p) + continue; + default_zfsroot = copypath(p); + goto out; + } + } + default_zfsroot = DEFAULT_ZFSROOT; + +out: + if (fin) + fclose(fin); + return default_zfsroot; +} const char *default_lxc_path(void) { char buf[1024], *p; diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 0a27903..75c747f 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -31,6 +31,8 @@ extern int mkdir_p(const char *dir, mode_t mode); * path. Caller must free this buffer. */ extern const char *default_lxc_path(void); +extern const char *default_zfs_root(void); +extern const char *default_lvm_vg(void); /* * wait on a child we forked -- 1.8.1.2 ------------------------------------------------------------------------------ Try New Relic Now & We'll Send You this Cool Shirt New Relic is the only SaaS-based application performance monitoring service that delivers powerful full stack analytics. Optimize and monitor your browser, app, & servers with just a few lines of code. Try New Relic and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel