From 31a95fecd2e0b1408e9a97e3ae36a7770544d1a2 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Sat, 27 Apr 2013 04:59:11 +0200 Subject: [PATCH] allow site-wide customization of zfsroot and lvm vg /etc/lxc/lxc.conf can contain zfsroot = custom1 lvm_vg = vg0 (Otherwise the defaults are 'lxc' for lvm_vg, and 'lxc' for zfsroot) Signed-off-by: Serge Hallyn --- 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 4ba550cf2..a3577a207 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 2fa2b0cc8..be1ce8860 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 ee463a7f8..09af34ac3 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); /** * BUILD_BUG_ON - break compile if a condition is true.