]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
Add a --thinpool argument to lxc-create, to use thin pool backed lvm when creating...
authorSidnei da Silva <sidnei.da.silva@canonical.com>
Mon, 19 Aug 2013 22:34:19 +0000 (19:34 -0300)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Fri, 18 Oct 2013 19:43:03 +0000 (14:43 -0500)
src/lxc/arguments.h
src/lxc/bdev.c
src/lxc/bdev.h
src/lxc/lxc_config.c
src/lxc/lxc_create.c
src/lxc/lxccontainer.c
src/lxc/lxccontainer.h
src/lxc/utils.c
src/lxc/utils.h

index 7da7d5fdc4d3275917d684ab51830b5edd28e7d0..dc2d117eb9027461fdb5ccefde9ec536e8ef3c5e 100644 (file)
@@ -80,7 +80,7 @@ struct lxc_arguments {
        char *bdevtype, *configfile, *template;
        char *fstype;
        unsigned long fssize;
-       char *lvname, *vgname;
+       char *lvname, *vgname, *thinpool;
        char *zfsroot, *lowerdir, *dir;
 
        /* remaining arguments */
index b643bb7b5d9e96204ad1d7551a8842dde71372c0..bc8ec61a4daa8c88ed9140c86e220923e6229a29 100644 (file)
@@ -816,7 +816,7 @@ static int lvm_umount(struct bdev *bdev)
  * not yet exist.  This function will attempt to create /dev/$vg/$lv of
  * size $size.
  */
-static int do_lvm_create(const char *path, unsigned long size)
+static int do_lvm_create(const char *path, unsigned long size, const char *thinpool)
 {
        int ret, pid;
        char sz[24], *pathdup, *vg, *lv;
@@ -848,11 +848,61 @@ static int do_lvm_create(const char *path, unsigned long size)
        if (!vg)
                exit(1);
        vg++;
-       execlp("lvcreate", "lvcreate", "-L", sz, vg, "-n", lv, (char *)NULL);
+       if (!thinpool) {
+           execlp("lvcreate", "lvcreate", "-L", sz, vg, "-n", lv, (char *)NULL);
+       } else {
+           execlp("lvcreate", "lvcreate", "--thinpool", thinpool, "-V", sz, vg, "-n", lv, (char *)NULL);
+       }
        free(pathdup);
        exit(1);
 }
 
+static int lvm_is_thin_volume(const char *path)
+{
+       FILE *f;
+       int ret, len, start=0;
+       char *cmd, output[12];
+       const char *lvscmd = "lvs --unbuffered --noheadings -o lv_attr %s 2>/dev/null";
+
+       len = strlen(lvscmd) + strlen(path) - 1;
+       cmd = malloc(len);
+       if (!cmd)
+               return -1;
+
+       ret = snprintf(cmd, len, lvscmd, path);
+       if (ret < 0 || ret >= len)
+               return -1;
+
+       process_lock();
+       f = popen(cmd, "r");
+       process_unlock();
+
+       if (f == NULL) {
+               SYSERROR("popen failed");
+               return -1;
+       }
+
+       if (fgets(output, 12, f) == NULL)
+               return -1;
+
+       process_lock();
+       ret = pclose(f);
+       process_unlock();
+
+       if (!WIFEXITED(ret)) {
+               SYSERROR("error executing lvs");
+               return -1;
+       }
+
+       len = strlen(output);
+       while(start < len && output[start] == ' ') start++;
+
+       if (start + 6 < len && output[start + 6] == 't')
+               return 1;
+
+       return 0;
+}
+
 static int lvm_snapshot(const char *orig, const char *path, unsigned long size)
 {
        int ret, pid;
@@ -882,7 +932,18 @@ static int lvm_snapshot(const char *orig, const char *path, unsigned long size)
        *lv = '\0';
        lv++;
 
-       ret = execlp("lvcreate", "lvcreate", "-s", "-L", sz, "-n", lv, orig, (char *)NULL);
+       // check if the original lv is backed by a thin pool, in which case we
+       // cannot specify a size that's different from the original size.
+       ret = lvm_is_thin_volume(orig);
+       if (ret == -1)
+               return -1;
+
+       if (!ret) {
+               ret = execlp("lvcreate", "lvcreate", "-s", "-L", sz, "-n", lv, orig, (char *)NULL);
+       } else {
+               ret = execlp("lvcreate", "lvcreate", "-s", "-n", lv, orig, (char *)NULL);
+       }
+
        free(pathdup);
        exit(1);
 }
@@ -965,7 +1026,7 @@ static int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldna
                        return -1;
                }
        } else {
-               if (do_lvm_create(new->src, size) < 0) {
+               if (do_lvm_create(new->src, size, NULL) < 0) {
                        ERROR("Error creating new lvm blockdev");
                        return -1;
                }
@@ -998,7 +1059,7 @@ static int lvm_destroy(struct bdev *orig)
 static int lvm_create(struct bdev *bdev, const char *dest, const char *n,
                        struct bdev_specs *specs)
 {
-       const char *vg, *fstype, *lv = n;
+       const char *vg, *thinpool, *fstype, *lv = n;
        unsigned long sz;
        int ret, len;
 
@@ -1009,6 +1070,8 @@ static int lvm_create(struct bdev *bdev, const char *dest, const char *n,
        if (!vg)
                vg = default_lvm_vg();
 
+       thinpool = specs->u.lvm.thinpool;
+
        /* /dev/$vg/$lv */
        if (specs->u.lvm.lv)
                lv = specs->u.lvm.lv;
@@ -1027,7 +1090,7 @@ static int lvm_create(struct bdev *bdev, const char *dest, const char *n,
                sz = DEFAULT_FS_SIZE;
 
        INFO("Error creating new lvm blockdev %s size %lu", bdev->src, sz);
-       if (do_lvm_create(bdev->src, sz) < 0) {
+       if (do_lvm_create(bdev->src, sz, thinpool) < 0) {
                ERROR("Error creating new lvm blockdev %s size %lu", bdev->src, sz);
                return -1;
        }
index a603d9e95b16da0461866cb601ff33f085d4cdc9..e10ea8e1c1406f465c7cf79c3050b3b50700c241 100644 (file)
@@ -46,6 +46,7 @@ struct bdev_specs {
                        char *lv;
                        char *fstype;
                        unsigned long fssize;  // fs size in bytes
+                       char *thinpool; // lvm thin pool to use, if any
                } lvm;
                struct {
                        char *fstype;
index c90be7dca911c44473bfe766993ab2a7e4e3eadc..21bde64564a54e26d61a0b2c9f8b1ae1af74a14a 100644 (file)
@@ -31,6 +31,7 @@ struct lxc_config_items items[] =
 {
        { .name = "lxcpath", .fn = &lxc_get_default_config_path, },
        { .name = "lvm_vg", .fn = &lxc_get_default_lvm_vg, },
+       { .name = "lvm_thin_pool", .fn = &lxc_get_default_lvm_thin_pool, },
        { .name = "zfsroot", .fn = &lxc_get_default_zfs_root, },
        { .name = NULL, },
 };
index 98cca325b7c90ab8fa567b3877ca32db17b9d2a9..15b104dda42dbabad7c58d88dff8d70112a06f0a 100644 (file)
@@ -64,10 +64,11 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg)
        case 't': args->template = arg; break;
        case '0': args->lvname = arg; break;
        case '1': args->vgname = arg; break;
-       case '2': args->fstype = arg; break;
-       case '3': args->fssize = get_fssize(arg); break;
-       case '4': args->zfsroot = arg; break;
-       case '5': args->dir = arg; break;
+       case '2': args->thinpool = arg; break;
+       case '3': args->fstype = arg; break;
+       case '4': args->fssize = get_fssize(arg); break;
+       case '5': args->zfsroot = arg; break;
+       case '6': args->dir = arg; break;
        }
        return 0;
 }
@@ -78,10 +79,11 @@ static const struct option my_longopts[] = {
        {"template", required_argument, 0, 't'},
        {"lvname", required_argument, 0, '0'},
        {"vgname", required_argument, 0, '1'},
-       {"fstype", required_argument, 0, '2'},
-       {"fssize", required_argument, 0, '3'},
-       {"zfsroot", required_argument, 0, '4'},
-       {"dir", required_argument, 0, '5'},
+       {"thinpool", required_argument, 0, '2'},
+       {"fstype", required_argument, 0, '3'},
+       {"fssize", required_argument, 0, '4'},
+       {"zfsroot", required_argument, 0, '5'},
+       {"dir", required_argument, 0, '6'},
        LXC_COMMON_OPTIONS
 };
 
@@ -129,6 +131,8 @@ Options :\n\
                      (Default: container name)\n\
   --vgname=VG        Use LVM vg called VG\n\
                      (Default: lxc))\n\
+  --thinpool=TP      Use LVM thin pool called TP\n\
+                     (Default: none))\n\
   --fstype=TYPE      Create fstype TYPE\n\
                      (Default: ext3))\n\
   --fssize=SIZE      Create filesystem of size SIZE\n\
@@ -151,8 +155,8 @@ bool validate_bdev_args(struct lxc_arguments *a)
                }
        }
        if (strcmp(a->bdevtype, "lvm") != 0) {
-               if (a->lvname || a->vgname) {
-                       fprintf(stderr, "--lvname and --vgname are only valid with -B lvm\n");
+               if (a->lvname || a->vgname || a->thinpool) {
+                       fprintf(stderr, "--lvname, --vgname and --thinpool are only valid with -B lvm\n");
                        return false;
                }
        }
@@ -221,6 +225,8 @@ int main(int argc, char *argv[])
                        spec.u.lvm.lv = my_args.lvname;
                if (my_args.vgname)
                        spec.u.lvm.vg = my_args.vgname;
+               if (my_args.thinpool)
+                       spec.u.lvm.thinpool = my_args.thinpool;
                if (my_args.fstype)
                        spec.u.lvm.fstype = my_args.fstype;
                if (my_args.fssize)
index 6f978791109d6e34da85737290accfcc2b3bd181..616c92d50cca4e431c89dc4f385279939ab28033 100644 (file)
@@ -1807,6 +1807,11 @@ const char *lxc_get_default_lvm_vg(void)
        return default_lvm_vg();
 }
 
+const char *lxc_get_default_lvm_thin_pool(void)
+{
+       return default_lvm_thin_pool();
+}
+
 const char *lxc_get_default_zfs_root(void)
 {
        return default_zfs_root();
index 5901066a5784ca5b1ccfca580f460b2cd967e887..b7dc1a47f81fab2be3c76a60179b4fcf5e4875e9 100644 (file)
@@ -245,6 +245,7 @@ int lxc_container_put(struct lxc_container *c);
 int lxc_get_wait_states(const char **states);
 const char *lxc_get_default_config_path(void);
 const char *lxc_get_default_lvm_vg(void);
+const char *lxc_get_default_lvm_thin_pool(void);
 const char *lxc_get_default_zfs_root(void);
 const char *lxc_get_version(void);
 
index 12ed454afe4e8ddea6db56d740db9499f89f8305..11f5fb7b895585a7350fab4b401a80dfd871ea0f 100644 (file)
@@ -243,6 +243,7 @@ const char *lxc_global_config_value(const char *option_name)
 {
        static const char *options[][2] = {
                { "lvm_vg",          DEFAULT_VG      },
+               { "lvm_thin_pool",   NULL            },
                { "zfsroot",         DEFAULT_ZFSROOT },
                { "lxcpath",         LXCPATH         },
                { "cgroup.pattern",  DEFAULT_CGROUP_PATTERN },
@@ -326,6 +327,11 @@ const char *default_lvm_vg(void)
        return lxc_global_config_value("lvm_vg");
 }
 
+const char *default_lvm_thin_pool(void)
+{
+       return lxc_global_config_value("lvm_thin_pool");
+}
+
 const char *default_zfs_root(void)
 {
        return lxc_global_config_value("zfsroot");
index 87a914b9b0ad8e1dc8e88e8512ef7fcc221545b4..fc4676096d6572608fff0d8b9ec7899df24d65a6 100644 (file)
@@ -48,6 +48,7 @@ extern const char *lxc_global_config_value(const char *option_name);
 extern const char *default_lxc_path(void);
 extern const char *default_zfs_root(void);
 extern const char *default_lvm_vg(void);
+extern const char *default_lvm_thin_pool(void);
 
 /* Define getline() if missing from the C library */
 #ifndef HAVE_GETLINE