[lxc-devel] [PATCH] allow site-wide customization of zfsroot and lvm vg

Serge Hallyn serge.hallyn at ubuntu.com
Sun Apr 28 02:42:00 UTC 2013


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.hallyn at 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 at 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





More information about the lxc-devel mailing list