[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