Commit 9be53773 by Serge Hallyn

implement backend drivers and container clone API (v3)

1. commonize waitpid users to use a single helper. We frequently want to run something in a clean namespace, or fork off a script. This lets us keep the function doing fork:(1)exec(2)waitpid simpler. 2. start a blockdev backend implementation. This will be used for mounting, copying, and snapshotting container filesystems. 3. implement btrfs, lvm, directory, and overlayfs backends. 4. For overlayfs, support a new lxc.rootfs format of 'bdevtype:<extra>'. This means you can now use overlayfs-based containers without using lxc-start-ephemeral, by using lxc.rootfs = overlayfs:/readonly-dir:writeable-dir 5. add a set of simple clone testcases 6. Write a new lxc_clone.c based on api clone. Still to do (there's more, but off top of my head): 1. support zfs, aufs 2. have clone handle other mount entries (right now it only clones the rootfs) 3. python, lua, and go bindings (not me :) 4. lxc-destroy: if lvm backing store, check for snapshots of it. (what about directories which have overlayfs clones?) Changes since v2: Initialize random generator when picking new macaddr (reported by caglar@10ur.org) Fix wrong use of bitmask flags On copy-clone of btrfs, create a subvolume lxc_clone.c: respect the command line usage of the old script lxc-clone(1): update documentation Refuse to try changing backing stores expect to overlayfs, as it is not implemented (yet) anyway. Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Conflicts: src/lxc/utils.h
parent ab1bf971
......@@ -382,7 +382,7 @@ AC_CONFIG_FILES([
src/lxc/lxc-checkconfig
src/lxc/lxc-version
src/lxc/lxc-create
src/lxc/lxc-clone
src/lxc/lxc-clone-sh
src/lxc/lxc-shutdown
src/lxc/lxc-start-ephemeral
src/lxc/lxc-destroy
......
......@@ -50,13 +50,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
<refsynopsisdiv>
<cmdsynopsis>
<command>lxc-clone</command>
<arg choice="opt">-s </arg>
<arg choice="opt">-K </arg>
<arg choice="opt">-M </arg>
<arg choice="opt">-H </arg>
<arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
<arg choice="opt">-L <replaceable>fssize</replaceable></arg>
<arg choice="opt">-p <replaceable>lxcpath</replaceable></arg>
<arg choice="opt">-P <replaceable>newlxcpath</replaceable></arg>
<arg choice="req">-o <replaceable>orig</replaceable></arg>
<arg choice="req">-n <replaceable>new</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
<command>lxc-clone</command>
<arg choice="opt">-s </arg>
<arg choice="opt">-K </arg>
<arg choice="opt">-M </arg>
<arg choice="opt">-H </arg>
<arg choice="opt">-B <replaceable>backingstore</replaceable></arg>
<arg choice="opt">-L <replaceable>fssize</replaceable></arg>
<arg choice="opt">-v <replaceable>vgname</replaceable></arg>
<arg choice="opt">-p <replaceable>lxc_lv_prefix</replaceable></arg>
<arg choice="opt">-t <replaceable>fstype</replaceable></arg>
<arg choice="opt">-p <replaceable>lxcpath</replaceable></arg>
<arg choice="opt">-P <replaceable>newlxcpath</replaceable></arg>
<arg choice="req">orig</arg>
<arg choice="req">new</arg>
</cmdsynopsis>
</refsynopsisdiv>
......@@ -64,10 +80,29 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
<title>Description</title>
<para>
<command>lxc-clone</command> Creates a new container as a copy of an existing
container. When the original container's rootfs is an LVM block device or
is on a btrfs filesystem, then a snapshotted clone can be created, taking up
very little initial disk space.
<command>lxc-clone</command> Creates a new container as a clone of an existing
container. Two types of clones are supported: copy and snapshot. A copy
clone copies the root filessytem from the original container to the new. A
snapshot filesystem uses the backing store's snapshot functionality to create
a very small copy-on-write snapshot of the original container. Snapshot
clones require the new container backing store to support snapshotting. Currently
this includes only btrfs, lvm, overlayfs and zfs. LVM devices do not support
snapshots fo snapshots.
</para>
<para>
The backing store of the new container will be the same type as the
original container,
with one exception: overlayfs snapshots can be created of directory backed
containers. This can be requested by using the <replaceable>-B overlayfs</replaceable>
arguments.
</para>
<para>
The names of the original and new container can be given (in that order)
after all options, or can be specified with the
<replaceable>-o</replaceable> and <replaceable>-n</replaceable> options,
respectively.
</para>
</refsect1>
......@@ -80,33 +115,47 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
<varlistentry>
<term>
<option>-o, --orig <replaceable>orig</replaceable></option>
<option>-s, --snapshot</option>
</term>
<listitem>
<para>
The name of the original container to clone.
The new container's rootfs should be a LVM or btrfs snapshot of the original.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --new <replaceable>new</replaceable></option>
<option>-K, --keepname</option>
</term>
<listitem>
<para>
The name of the new container to create.
Do not change the hostname of the container (in the root
filesystem).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-s, --snapshot</option>
<option>-M, --keepmac</option>
</term>
<listitem>
<para>
The new container's rootfs should be a LVM or btrfs snapshot of the original.
Use the same MAC address as the original container, rather tahn
generating a new random one.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-H, --copyhooks</option>
</term>
<listitem>
<para>
Copy all mount hooks into the new container's directory, and
update any lxcpaths and container names as needed.
</para>
</listitem>
</varlistentry>
......@@ -117,7 +166,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
</term>
<listitem>
<para>
In the case of a LVM-backed container, a size for the new
In the case of a block device backed container, a size for the new
block device. By default, the new device will be made the
same size as the original.
</para>
......@@ -126,43 +175,69 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
<varlistentry>
<term>
<option>-v, --vgname <replaceable>vgname</replaceable></option>
<option>-p, --lxcpath <replaceable>fssize</replaceable></option>
</term>
<listitem>
<para>
For an LVM-backed container, the volume group name to use. By
default it is 'lxc'.
The lxcpath of the original container. By default, the system
wide configured lxcpath will be used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-p, --lvprefix <replaceable>lxc_lv_prefix</replaceable></option>
<option>-P, --newpath <replaceable>fssize</replaceable></option>
</term>
<listitem>
<para>
For an LVM-backed container, a string to prefix to the container name to
form the logical volume name. For instance, specifying
<command>-n c1 -p lxc_</command> will cause the container rootfs to
be on a logical volume called <replaceable>lxc_c1</replaceable>.
The lxcpath for the new container. By default the same lxcpath
as the original will be used. Note that with btrfs snapshots,
changing lxcpaths may not be possible, as subvolume snapshots
must be in the same btrfs filesystem.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-t, --fstype <replaceable>fstype</replaceable></option>
<option>-B, --backingstore <replaceable>fssize</replaceable></option>
</term>
<listitem>
<para>
For a non-snapshot LVM clone, the file system to use for the new
container. Note this option is ignored when requesting a
snapshotted container.
Select a different backing store for the new container. By
default the same as the original container's is used. Note that
currently changing the backingstore is only supported for
overlayfs snapshots of directory backed containers. Valid
backing stores include dir (directory), btrfs, lvm, zfs
and overlayfs.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-o, --orig <replaceable>orig</replaceable></option>
</term>
<listitem>
<para>
The name of the original container to clone.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>-n, --new <replaceable>new</replaceable></option>
</term>
<listitem>
<para>
The name of the new container to create.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
......
......@@ -16,6 +16,7 @@ pkginclude_HEADERS = \
attach.h \
lxccontainer.h \
lxclock.h \
bdev.h \
version.h
if IS_BIONIC
......@@ -36,6 +37,7 @@ so_PROGRAMS = liblxc.so
liblxc_so_SOURCES = \
arguments.c arguments.h \
bdev.c bdev.h \
commands.c commands.h \
start.c start.h \
stop.c \
......@@ -122,7 +124,7 @@ bin_SCRIPTS = \
lxc-checkconfig \
lxc-version \
lxc-create \
lxc-clone \
lxc-clone-sh \
lxc-shutdown \
lxc-destroy
......@@ -148,6 +150,7 @@ bin_PROGRAMS = \
lxc-unshare \
lxc-stop \
lxc-start \
lxc-clone \
lxc-execute \
lxc-monitor \
lxc-monitord \
......@@ -184,6 +187,7 @@ lxc_init_SOURCES = lxc_init.c
lxc_monitor_SOURCES = lxc_monitor.c
lxc_monitord_SOURCES = lxc_monitord.c
lxc_restart_SOURCES = lxc_restart.c
lxc_clone_SOURCES = lxc_clone.c
lxc_start_SOURCES = lxc_start.c
lxc_stop_SOURCES = lxc_stop.c
lxc_unfreeze_SOURCES = lxc_unfreeze.c
......
This diff is collapsed. Click to expand it.
#ifndef __LXC_BDEV_H
#define __LXC_BDEV_H
/* blockdev operations for:
* dir, raw, btrfs, overlayfs, aufs, lvm, loop, zfs, btrfs
* someday: qemu-nbd, qcow2, qed
*/
#include "config.h"
#include "lxccontainer.h"
struct bdev;
struct bdev_ops {
/* detect whether path is of this bdev type */
int (*detect)(const char *path);
// mount requires src and dest to be set.
int (*mount)(struct bdev *bdev);
int (*umount)(struct bdev *bdev);
/* given original mount, rename the paths for cloned container */
int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath,
int snap, unsigned long newsize);
};
struct bdev {
struct bdev_ops *ops;
char *type;
char *src;
char *dest;
char *data;
};
/*
* Instantiate a bdev object. The src is used to determine which blockdev
* type this should be. The dst and data are optional, and will be used
* in case of mount/umount.
*
* Optionally, src can be 'dir:/var/lib/lxc/c1' or 'lvm:/dev/lxc/c1'. For
* other backing stores, this will allow additional options. In particular,
* "overlayfs:/var/lib/lxc/canonical/rootfs:/var/lib/lxc/c1/delta" will mean
* use /var/lib/lxc/canonical/rootfs as lower dir, and /var/lib/lxc/c1/delta
* as the upper, writeable layer.
*/
struct bdev *bdev_init(const char *src, const char *dst, const char *data);
struct bdev *bdev_copy(const char *src, const char *oldname, const char *cname,
const char *oldpath, const char *lxcpath, const char *bdevtype,
int snap, const char *bdevdata, unsigned long newsize);
void bdev_put(struct bdev *bdev);
#endif
......@@ -64,6 +64,7 @@
#include "log.h"
#include "lxc.h" /* for lxc_cgroup_set() */
#include "caps.h" /* for lxc_caps_last_cap() */
#include "bdev.h"
#if HAVE_APPARMOR
#include <apparmor.h>
......@@ -590,8 +591,8 @@ int pin_rootfs(const char *rootfs)
return -2;
if (!realpath(rootfs, absrootfs)) {
SYSERROR("failed to get real path for '%s'", rootfs);
return -1;
INFO("failed to get real path for '%s', not pinning", rootfs);
return -2;
}
if (access(absrootfs, F_OK)) {
......@@ -1163,6 +1164,12 @@ static int setup_rootfs(struct lxc_conf *conf)
}
}
// First try mounting rootfs using a bdev
struct bdev *bdev = bdev_init(rootfs->path, rootfs->mount, NULL);
if (bdev && bdev->ops->mount(bdev) == 0) {
DEBUG("mounted '%s' on '%s'", rootfs->path, rootfs->mount);
return 0;
}
if (mount_rootfs(rootfs->path, rootfs->mount)) {
ERROR("failed to mount rootfs");
return -1;
......
#include <unistd.h>
#include <getopt.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
#include "log.h"
#include "config.h"
#include "lxc.h"
#include "conf.h"
#include "state.h"
#include "lxccontainer.h"
lxc_log_define(lxc_clone, lxc);
void usage(char *me)
{
printf("Usage: %s [-s] [-B backingstore] [-L size] [-K] [-M] [-H]\n", me);
printf(" [-p lxcpath] [-P newlxcpath] orig new\n");
printf("\n");
printf(" -s: snapshot rather than copy\n");
printf(" -B: use specified new backingstore. Default is the same as\n");
printf(" the original. Options include btrfs, lvm, overlayfs, \n");
printf(" dir\n");
printf(" -L: for blockdev-backed backingstore, use specified size\n");
printf(" -K: Keep name - do not change the container name\n");
printf(" -M: Keep macaddr - do not choose a random new mac address\n");
printf(" -H: copy Hooks - copy mount hooks into container directory\n");
printf(" and substitute container names and lxcpaths\n");
printf(" -p: use container orig from custom lxcpath\n");
printf(" -P: create container new in custom lxcpath\n");
exit(1);
}
static struct option options[] = {
{ "snapshot", no_argument, 0, 's'},
{ "backingstore", required_argument, 0, 'B'},
{ "size", required_argument, 0, 'L'},
{ "orig", required_argument, 0, 'o'},
{ "new", required_argument, 0, 'n'},
{ "vgname", required_argument, 0, 'v'},
{ "keepname", no_argument, 0, 'K'},
{ "keepmac", no_argument, 0, 'M'},
{ "copyhooks", no_argument, 0, 'H'}, // should this be default?
{ "lxcpath", required_argument, 0, 'p'},
{ "newpath", required_argument, 0, 'P'},
{ "fstype", required_argument, 0, 't'},
{ "help", no_argument, 0, 'h'},
{ 0, 0, 0, 0 },
};
int main(int argc, char *argv[])
{
struct lxc_container *c1 = NULL, *c2 = NULL;
int snapshot = 0, keepname = 0, keepmac = 0, copyhooks = 0;
int flags = 0, option_index;
long newsize = 0;
char *bdevtype = NULL, *lxcpath = NULL, *newpath = NULL, *fstype = NULL;
char *orig = NULL, *new = NULL, *vgname = NULL;
char c;
if (argc < 3)
usage(argv[0]);
while (1) {
c = getopt_long(argc, argv, "sB:L:o:n:v:KMHp:P:t:h", options, &option_index);
if (c == -1)
break;
switch (c) {
case 's': snapshot = 1; break;
case 'B': bdevtype = optarg; break;
case 'L': newsize = atol(optarg); break;
case 'o': orig = optarg; break;
case 'n': new = optarg; break;
case 'v': vgname = optarg; break;
case 'K': keepname = 1; break;
case 'M': keepmac = 1; break;
case 'H': copyhooks = 1; break;
case 'p': lxcpath = optarg; break;
case 'P': newpath = optarg; break;
case 't': fstype = optarg; break;
case 'h': usage(argv[0]);
default: break;
}
}
if (optind == argc-2 && !orig)
orig = argv[optind++];
if (optind == argc-1 && !new)
new = argv[optind++];
if (optind < argc) {
printf("%d extraneous arguments\n", argc-optind);
usage(argv[0]);
}
if (!new || !orig) {
printf("Error: you must provide orig and new names\n");
usage(argv[0]);
}
if (snapshot) flags |= LXC_CLONE_SNAPSHOT;
if (keepname) flags |= LXC_CLONE_KEEPNAME;
if (keepmac) flags |= LXC_CLONE_KEEPMACADDR;
if (copyhooks) flags |= LXC_CLONE_COPYHOOKS;
// vgname and fstype could be supported by sending them through the
// bdevdata. However, they currently are not yet. I'm not convinced
// they are worthwhile.
if (vgname) {
printf("Error: vgname not supported\n");
usage(argv[0]);
}
if (fstype) {
printf("Error: fstype not supported\n");
usage(argv[0]);
}
c1 = lxc_container_new(orig, lxcpath);
if (!c1)
exit(1);
if (!c1->is_defined(c1)) {
fprintf(stderr, "Error: container %s is not defined\n", orig);
lxc_container_put(c1);
exit(1);
}
c2 = c1->clone(c1, new, newpath, flags, bdevtype, NULL, newsize);
if (c2 == NULL) {
lxc_container_put(c1);
fprintf(stderr, "clone failed\n");
exit(1);
}
printf("Created container %s as %s of %s\n", new,
snapshot ? "snapshot" : "copy", orig);
lxc_container_put(c1);
lxc_container_put(c2);
return(0);
}
#ifndef __LXC_CONTAINER_H
#define __LXC_CONTAINER_H
#include "lxclock.h"
#include <stdlib.h>
#include <malloc.h>
#include <stdbool.h>
#define LXC_CLONE_KEEPNAME (1 << 0)
#define LXC_CLONE_COPYHOOKS (1 << 1)
#define LXC_CLONE_KEEPMACADDR (1 << 2)
#define LXC_CLONE_SNAPSHOT (1 << 3)
#define LXC_CLONE_MAXFLAGS (1 << 4)
struct lxc_container {
// private fields
char *name;
......@@ -72,6 +80,33 @@ struct lxc_container {
const char *(*get_config_path)(struct lxc_container *c);
bool (*set_config_path)(struct lxc_container *c, const char *path);
/*
* @c: the original container
* @newname: new name for the container. If NULL, the same name is used, and
* a new lxcpath MUST be specified.
* @lxcpath: lxcpath in which to create the new container. If NULL, then the
* original container's lxcpath will be used. (Shoudl we use the default
* instead?)
* @flags: additional flags to modify cloning behavior.
* LXC_CLONE_KEEPNAME: don't edit the rootfs to change the hostname.
* LXC_CLONE_COPYHOOKS: copy all hooks into the container dir
* LXC_CLONE_KEEPMACADDR: don't change the mac address on network interfaces.
* LXC_CLONE_SNAPSHOT: snapshot the original filesystem(s). If @devtype was not
* specified, then do so with the native bdevtype if possible, else use an
* overlayfs.
* @bdevtype: optionally force the cloned bdevtype to a specified plugin. By
* default the original is used (subject to snapshot requirements).
* @bdevdata: information about how to create the new storage (i.e. fstype and
* fsdata)
* @newsize: in case of a block device backing store, an optional size. If 0,
* then the original backing store's size will be used if possible. Note this
* only applies to the rootfs. For any other filesystems, the original size
* will be duplicated.
*/
struct lxc_container *(*clone)(struct lxc_container *c, const char *newname,
const char *lxcpath, int flags, const char *bdevtype,
const char *bdevdata, unsigned long newsize);
#if 0
bool (*commit_cgroups)(struct lxc_container *c);
bool (*reread_cgroups)(struct lxc_container *c);
......@@ -93,3 +128,4 @@ const char *lxc_get_version(void);
char ** lxc_get_valid_keys();
char ** lxc_get_valid_values(char *key);
#endif
#endif
......@@ -34,6 +34,8 @@
#include <dirent.h>
#include <fcntl.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "log.h"
......@@ -172,3 +174,21 @@ out:
fclose(fin);
return default_lxcpath;
}
int wait_for_pid(pid_t pid)
{
int status, ret;
again:
ret = waitpid(pid, &status, 0);
if (ret == -1) {
if (errno == -EINTR)
goto again;
return -1;
}
if (ret != pid)
goto again;
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
return -1;
return 0;
}
......@@ -58,4 +58,9 @@ extern int __build_bug_on_failed;
} while(0)
#endif
/*
* wait on a child we forked
*/
extern int wait_for_pid(pid_t pid);
#endif
......@@ -13,6 +13,7 @@ lxc_test_get_item_SOURCES = get_item.c
lxc_test_getkeys_SOURCES = getkeys.c
lxc_test_lxcpath_SOURCES = lxcpath.c
lxc_test_cgpath_SOURCES = cgpath.c
lxc_test_clonetest_SOURCES = clonetest.c
AM_CFLAGS=-I$(top_srcdir)/src \
-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
......@@ -23,7 +24,7 @@ AM_CFLAGS=-I$(top_srcdir)/src \
bin_PROGRAMS = lxc-test-containertests lxc-test-locktests lxc-test-startone \
lxc-test-destroytest lxc-test-saveconfig lxc-test-createtest \
lxc-test-shutdowntest lxc-test-get_item lxc-test-getkeys lxc-test-lxcpath \
lxc-test-cgpath
lxc-test-cgpath lxc-test-clonetest
endif
......@@ -38,4 +39,5 @@ EXTRA_DIST = \
lxcpath.c \
saveconfig.c \
shutdowntest.c \
clonetest.c \
startone.c
/* liblxcapi
*
* Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
* Copyright © 2012 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "../lxc/lxccontainer.h"
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
#define MYNAME "clonetest1"
#define MYNAME2 "clonetest2"
int main(int argc, char *argv[])
{
struct lxc_container *c = NULL, *c2 = NULL, *c3 = NULL;
int ret = 1;
c = lxc_container_new(MYNAME, NULL);
c2 = lxc_container_new(MYNAME2, NULL);
if (c) {
c->destroy(c);
lxc_container_put(c);
c = NULL;
}
if (c2) {
c2->destroy(c2);
lxc_container_put(c2);
c2 = NULL;
}
if ((c = lxc_container_new(MYNAME, NULL)) == NULL) {
fprintf(stderr, "%d: error opening lxc_container %s\n", __LINE__, MYNAME);
ret = 1;
goto out;
}
c->save_config(c, NULL);
if (!c->createl(c, "ubuntu", NULL)) {
fprintf(stderr, "%d: failed to create a container\n", __LINE__);
goto out;
}
c->load_config(c, NULL);
if (!c->is_defined(c)) {
fprintf(stderr, "%d: %s thought it was not defined\n", __LINE__, MYNAME);
goto out;
}
c2 = c->clone(c, MYNAME2, NULL, 0, NULL, NULL, 0);
if (!c2) {
fprintf(stderr, "%d: %s clone returned NULL\n", __LINE__, MYNAME2);
goto out;
}
if (!c2->is_defined(c)) {
fprintf(stderr, "%d: %s not defined after clone\n", __LINE__, MYNAME2);
goto out;
}
fprintf(stderr, "directory backing store tests passed\n");
// now test with lvm
// Only do this if clonetestlvm1 exists - user has to set this up
// in advance
//c2->destroy(c2);
lxc_container_put(c2);
//c->destroy(c);
lxc_container_put(c);
c = NULL;
c2 = lxc_container_new("clonetestlvm2", NULL);
if (c2) {
if (c2->is_defined(c2))
c2->destroy(c2);
lxc_container_put(c2);
}
c2 = lxc_container_new("clonetest-o1", NULL);
if (c2) {
if (c2->is_defined(c2))
c2->destroy(c2);
lxc_container_put(c2);
}
c2 = lxc_container_new("clonetest-o2", NULL);
if (c2) {
if (c2->is_defined(c2))
c2->destroy(c2);
lxc_container_put(c2);
}
c2 = NULL;
// lvm-copied
c = lxc_container_new("clonetestlvm1", NULL);
if (!c) {
fprintf(stderr, "failed loading clonetestlvm1\n");
goto out;
}
if (!c->is_defined(c)) {
fprintf(stderr, "clonetestlvm1 does not exist, skipping lvm tests\n");
ret = 0;
goto out;
}
if ((c2 = c->clone(c, "clonetestlvm2", NULL, 0, NULL, NULL, 0)) == NULL) {
fprintf(stderr, "lvm clone failed\n");
goto out;
}
lxc_container_put(c2);
// lvm-snapshot
c2 = lxc_container_new("clonetestlvm3", NULL);
if (c2) {
if (c2->is_defined(c2))
c2->destroy(c2);
lxc_container_put(c2);
c2 = NULL;
}
if ((c2 = c->clone(c, "clonetestlvm3", NULL, LXC_CLONE_SNAPSHOT, NULL, NULL, 0)) == NULL) {
fprintf(stderr, "lvm clone failed\n");
goto out;
}
lxc_container_put(c2);
lxc_container_put(c);
c = c2 = NULL;
if ((c = lxc_container_new(MYNAME, NULL)) == NULL) {
fprintf(stderr, "error opening original container for overlay test\n");
goto out;
}
// Now create an overlayfs clone of a dir-backed container
if ((c2 = c->clone(c, "clonetest-o1", NULL, LXC_CLONE_SNAPSHOT, "overlayfs", NULL, 0)) == NULL) {
fprintf(stderr, "overlayfs clone of dir failed\n");
goto out;
}
// Now create an overlayfs clone of the overlayfs clone
if ((c3 = c2->clone(c2, "clonetest-o2", NULL, LXC_CLONE_SNAPSHOT, "overlayfs", NULL, 0)) == NULL) {
fprintf(stderr, "overlayfs clone of overlayfs failed\n");
goto out;
}
fprintf(stderr, "all clone tests passed for %s\n", c->name);
ret = 0;
out:
if (c3) {
lxc_container_put(c3);
}
if (c2) {
//c2->destroy(c2); // keep around to verify manuall
lxc_container_put(c2);
}
if (c) {
//c->destroy(c);
lxc_container_put(c);
}
exit(ret);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment