Originally we kept snapshots under /var/lib/lxcsnaps. If a separate btrfs is mounted at /var/lib/lxc, then we can't make btrfs snapshots under /var/lib/lxcsnaps.
This patch moves the default directory to /var/lib/lxc/c/snaps. If /var/lib/lxcsnaps already exists, then we continue to use that. add c->destroy_with_snapshots() and c->snapshot_destroy_all() API methods. c->snashot_destroy_all() can be triggered from lxc-snapshot using '-d ALL'. There is no command to call c->destroy_with_snapshots(c) as of yet. lxclock: use ".$lxcname" for container lock files that way we can use /run/lock/lxc/$lxcpath/$lxcname/snaps as a directory when locking snapshots without having to worry about /run/lock//lxc/$lxcpath/$lxcname being a file. destroy: split off a container_destroy container_destroy() doesn't check for snapshots, so snapshot_rename can use it. api_destroy() now does check for snapshots (previously it only checked for fs - i.e. overlayfs/aufs - snapshots). Add destroy to the manpage, as it was previously undocumented. Update snapshot testcase accordingly. Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com> --- doc/lxc-snapshot.sgml.in | 13 +++ src/lxc/bdev.c | 6 +- src/lxc/lxc_snapshot.c | 11 ++- src/lxc/lxccontainer.c | 217 ++++++++++++++++++++++++++++++++++++++--------- src/lxc/lxccontainer.h | 24 +++++- src/lxc/lxclock.c | 10 +-- src/lxc/utils.c | 39 +++++++-- src/lxc/utils.h | 2 +- src/tests/snapshot.c | 29 ++----- 9 files changed, 271 insertions(+), 80 deletions(-) diff --git a/doc/lxc-snapshot.sgml.in b/doc/lxc-snapshot.sgml.in index 4b70279..029534e 100644 --- a/doc/lxc-snapshot.sgml.in +++ b/doc/lxc-snapshot.sgml.in @@ -55,6 +55,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA <cmdsynopsis> <command>lxc-snapshot</command> <arg choice="req">-n, --name <replaceable>name</replaceable></arg> + <arg choice="req">-d, -destroy <replaceable>snapshot-name</replaceable></arg> + </cmdsynopsis> + <cmdsynopsis> + <command>lxc-snapshot</command> + <arg choice="req">-n, --name <replaceable>name</replaceable></arg> <arg choice="req">-L, --list </arg> <arg choice="opt">-C, --showcomments </arg> </cmdsynopsis> @@ -92,6 +97,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA </varlistentry> <varlistentry> + <term> <option>-d,--destroy snapshot-name</option> </term> + <listitem> + <para> Destroy the named snapshot. If the named snapshot is ALL, then all snapshots + will be destroyed.</para> + </listitem> + </varlistentry> + + <varlistentry> <term> <option>-L,--list </option> </term> <listitem> <para> List existing snapshots. </para> diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c index 751fa9f..efdbecc 100644 --- a/src/lxc/bdev.c +++ b/src/lxc/bdev.c @@ -482,7 +482,7 @@ static int dir_clonepaths(struct bdev *orig, struct bdev *new, const char *oldna static int dir_destroy(struct bdev *orig) { - if (lxc_rmdir_onedev(orig->src) < 0) + if (lxc_rmdir_onedev(orig->src, NULL) < 0) return -1; return 0; } @@ -2073,7 +2073,7 @@ static int overlayfs_destroy(struct bdev *orig) if (!upper) return -22; upper++; - return lxc_rmdir_onedev(upper); + return lxc_rmdir_onedev(upper, NULL); } /* @@ -2350,7 +2350,7 @@ static int aufs_destroy(struct bdev *orig) if (!upper) return -22; upper++; - return lxc_rmdir_onedev(upper); + return lxc_rmdir_onedev(upper, NULL); } /* diff --git a/src/lxc/lxc_snapshot.c b/src/lxc/lxc_snapshot.c index 1f8fdaf..58288e0 100644 --- a/src/lxc/lxc_snapshot.c +++ b/src/lxc/lxc_snapshot.c @@ -112,7 +112,13 @@ static int do_restore_snapshots(struct lxc_container *c) static int do_destroy_snapshots(struct lxc_container *c) { - if (c->snapshot_destroy(c, snapshot)) + bool bret; + if (strcmp(snapshot, "ALL") == 0) + bret = c->snapshot_destroy_all(c); + else + bret = c->snapshot_destroy(c, snapshot); + + if (bret) return 0; ERROR("Error destroying snapshot %s", snapshot); @@ -154,7 +160,8 @@ Options :\n\ -C, --showcomments show snapshot comments in list\n\ -c, --comment=file add file as a comment\n\ -r, --restore=name restore snapshot name, i.e. 'snap0'\n\ - -d, --destroy=name destroy snapshot name, i.e. 'snap0'\n", + -d, --destroy=name destroy snapshot name, i.e. 'snap0'\n\ + use ALL to destroy all snapshots\n", .options = my_longopts, .parser = my_parser, .checker = NULL, diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index fdac433..b0003d1 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -1203,6 +1203,8 @@ static void lxcapi_clear_config(struct lxc_container *c) } static bool lxcapi_destroy(struct lxc_container *c); +static bool container_destroy(struct lxc_container *c); +static bool get_snappath_dir(struct lxc_container *c, char *snappath); /* * lxcapi_create: * create a container with the given parameters. @@ -1344,7 +1346,7 @@ out_unlock: remove_partial(c, partial_fd); out: if (!ret && c) - lxcapi_destroy(c); + container_destroy(c); free_tpath: if (tpath) free(tpath); @@ -1950,7 +1952,7 @@ out: fclose(f); } -static bool has_snapshots(struct lxc_container *c) +static bool has_fs_snapshots(struct lxc_container *c) { char path[MAXPATHLEN]; int ret, v; @@ -1974,10 +1976,38 @@ out: return bret; } +static bool has_snapshots(struct lxc_container *c) +{ + char path[MAXPATHLEN]; + struct dirent dirent, *direntp; + int count=0; + DIR *dir; + + if (!get_snappath_dir(c, path)) + return false; + dir = opendir(path); + if (!dir) + return false; + while (!readdir_r(dir, &dirent, &direntp)) { + if (!direntp) + break; + + if (!strcmp(direntp->d_name, ".")) + continue; + + if (!strcmp(direntp->d_name, "..")) + continue; + count++; + break; + } + closedir(dir); + return count > 0; +} + static int lxc_rmdir_onedev_wrapper(void *data) { char *arg = (char *) data; - return lxc_rmdir_onedev(arg); + return lxc_rmdir_onedev(arg, "snaps"); } static int do_bdev_destroy(struct lxc_conf *conf) @@ -2012,8 +2042,7 @@ static int bdev_destroy_wrapper(void *data) return do_bdev_destroy(conf); } -// do we want the api to support --force, or leave that to the caller? -static bool lxcapi_destroy(struct lxc_container *c) +static bool container_destroy(struct lxc_container *c) { bool bret = false; int ret; @@ -2030,11 +2059,6 @@ static bool lxcapi_destroy(struct lxc_container *c) goto out; } - if (c->lxc_conf && has_snapshots(c)) { - ERROR("container %s has dependent snapshots", c->name); - goto out; - } - if (c->lxc_conf && c->lxc_conf->rootfs.path && c->lxc_conf->rootfs.mount) { if (am_unpriv()) ret = userns_exec_1(c->lxc_conf, bdev_destroy_wrapper, c->lxc_conf); @@ -2054,7 +2078,7 @@ static bool lxcapi_destroy(struct lxc_container *c) if (am_unpriv()) ret = userns_exec_1(c->lxc_conf, lxc_rmdir_onedev_wrapper, path); else - ret = lxc_rmdir_onedev(path); + ret = lxc_rmdir_onedev(path, "snaps"); if (ret < 0) { ERROR("Error destroying container directory for %s", c->name); goto out; @@ -2066,6 +2090,37 @@ out: return bret; } +static bool lxcapi_destroy(struct lxc_container *c) +{ + if (!c || !lxcapi_is_defined(c)) + return false; + if (has_snapshots(c)) { + ERROR("Container %s has snapshots; not removing", c->name); + return false; + } + + if (has_fs_snapshots(c)) { + ERROR("container %s has snapshots on its rootfs", c->name); + return false; + } + + return container_destroy(c); +} + +static bool lxcapi_snapshot_destroy_all(struct lxc_container *c); + +static bool lxcapi_destroy_with_snapshots(struct lxc_container *c) +{ + if (!c || !lxcapi_is_defined(c)) + return false; + if (!lxcapi_snapshot_destroy_all(c)) { + ERROR("Error deleting all snapshots"); + return false; + } + return lxcapi_destroy(c); +} + + static bool set_config_item_locked(struct lxc_container *c, const char *key, const char *v) { struct lxc_config_t *config; @@ -2780,6 +2835,10 @@ static bool lxcapi_rename(struct lxc_container *c, const char *newname) if (!c || !c->name || !c->config_path || !c->lxc_conf) return false; + if (has_fs_snapshots(c) || has_snapshots(c)) { + ERROR("Renaming a container with snapshots is not supported"); + return false; + } bdev = bdev_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL); if (!bdev) { ERROR("Failed to find original backing store type"); @@ -2796,7 +2855,7 @@ static bool lxcapi_rename(struct lxc_container *c, const char *newname) if (newc && lxcapi_is_defined(newc)) lxc_container_put(newc); - if (!lxcapi_destroy(c)) { + if (!container_destroy(c)) { ERROR("Could not destroy existing container %s", c->name); return false; } @@ -2846,16 +2905,42 @@ static int get_next_index(const char *lxcpath, char *cname) } } +static bool get_snappath_dir(struct lxc_container *c, char *snappath) +{ + int ret; + /* + * If the old style snapshot path exists, use it + * /var/lib/lxc -> /var/lib/lxcsnaps + */ + ret = snprintf(snappath, MAXPATHLEN, "%ssnaps", c->config_path); + if (ret < 0 || ret >= MAXPATHLEN) + return false; + if (dir_exists(snappath)) { + ret = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name); + if (ret < 0 || ret >= MAXPATHLEN) + return false; + return true; + } + + /* + * Use the new style path + * /var/lib/lxc -> /var/lib/lxc + c->name + /snaps + \0 + */ + ret = snprintf(snappath, MAXPATHLEN, "%s/%s/snaps", c->config_path, c->name); + if (ret < 0 || ret >= MAXPATHLEN) + return false; + return true; +} + static int lxcapi_snapshot(struct lxc_container *c, const char *commentfile) { int i, flags, ret; struct lxc_container *c2; char snappath[MAXPATHLEN], newname[20]; - // /var/lib/lxc -> /var/lib/lxcsnaps \0 - ret = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name); - if (ret < 0 || ret >= MAXPATHLEN) + if (!get_snappath_dir(c, snappath)) { return -1; + } i = get_next_index(snappath, c->name); if (mkdir_p(snappath, 0755) < 0) { @@ -2989,7 +3074,7 @@ static char *get_timestamp(char* snappath, char *name) static int lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **ret_snaps) { char snappath[MAXPATHLEN], path2[MAXPATHLEN]; - int dirlen, count = 0, ret; + int count = 0, ret; struct dirent dirent, *direntp; struct lxc_snapshot *snaps =NULL, *nsnaps; DIR *dir; @@ -2997,9 +3082,7 @@ static int lxcapi_snapshot_list(struct lxc_container *c, struct lxc_snapshot **r if (!c || !lxcapi_is_defined(c)) return -1; - // snappath is ${lxcpath}snaps/${lxcname}/ - dirlen = snprintf(snappath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name); - if (dirlen < 0 || dirlen >= MAXPATHLEN) { + if (!get_snappath_dir(c, snappath)) { ERROR("path name too long"); return -1; } @@ -3067,7 +3150,7 @@ out_free: static bool lxcapi_snapshot_restore(struct lxc_container *c, const char *snapname, const char *newname) { char clonelxcpath[MAXPATHLEN]; - int flags = 0,ret; + int flags = 0; struct lxc_container *snap, *rest; struct bdev *bdev; bool b = false; @@ -3075,6 +3158,11 @@ static bool lxcapi_snapshot_restore(struct lxc_container *c, const char *snapnam if (!c || !c->name || !c->config_path) return false; + if (has_fs_snapshots(c)) { + ERROR("container rootfs has dependent snapshots"); + return false; + } + bdev = bdev_init(c->lxc_conf, c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL); if (!bdev) { ERROR("Failed to find original backing store type"); @@ -3084,14 +3172,13 @@ static bool lxcapi_snapshot_restore(struct lxc_container *c, const char *snapnam if (!newname) newname = c->name; if (strcmp(c->name, newname) == 0) { - if (!lxcapi_destroy(c)) { + if (!container_destroy(c)) { ERROR("Could not destroy existing container %s", newname); bdev_put(bdev); return false; } } - ret = snprintf(clonelxcpath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name); - if (ret < 0 || ret >= MAXPATHLEN) { + if (!get_snappath_dir(c, clonelxcpath)) { bdev_put(bdev); return false; } @@ -3118,21 +3205,13 @@ static bool lxcapi_snapshot_restore(struct lxc_container *c, const char *snapnam return b; } -static bool lxcapi_snapshot_destroy(struct lxc_container *c, const char *snapname) +static bool do_snapshot_destroy(const char *snapname, const char *clonelxcpath) { - int ret; - char clonelxcpath[MAXPATHLEN]; struct lxc_container *snap = NULL; - - if (!c || !c->name || !c->config_path) - return false; - - ret = snprintf(clonelxcpath, MAXPATHLEN, "%ssnaps/%s", c->config_path, c->name); - if (ret < 0 || ret >= MAXPATHLEN) - goto err; + bool bret = false; snap = lxc_container_new(snapname, clonelxcpath); - if (!snap || !lxcapi_is_defined(snap)) { + if (!snap) { ERROR("Could not find snapshot %s", snapname); goto err; } @@ -3141,13 +3220,70 @@ static bool lxcapi_snapshot_destroy(struct lxc_container *c, const char *snapnam ERROR("Could not destroy snapshot %s", snapname); goto err; } - lxc_container_put(snap); + bret = true; - return true; err: if (snap) lxc_container_put(snap); - return false; + return bret; +} + +static bool remove_all_snapshots(const char *path) +{ + DIR *dir; + struct dirent dirent, *direntp; + bool bret = true; + + dir = opendir(path); + if (!dir) { + SYSERROR("opendir on snapshot path %s", path); + return false; + } + while (!readdir_r(dir, &dirent, &direntp)) { + if (!direntp) + break; + if (!strcmp(direntp->d_name, ".")) + continue; + if (!strcmp(direntp->d_name, "..")) + continue; + if (!do_snapshot_destroy(direntp->d_name, path)) { + bret = false; + continue; + } + } + + closedir(dir); + + if (rmdir(path)) + SYSERROR("Error removing directory %s", path); + + return bret; +} + +static bool lxcapi_snapshot_destroy(struct lxc_container *c, const char *snapname) +{ + char clonelxcpath[MAXPATHLEN]; + + if (!c || !c->name || !c->config_path || !snapname) + return false; + + if (!get_snappath_dir(c, clonelxcpath)) + return false; + + return do_snapshot_destroy(snapname, clonelxcpath); +} + +static bool lxcapi_snapshot_destroy_all(struct lxc_container *c) +{ + char clonelxcpath[MAXPATHLEN]; + + if (!c || !c->name || !c->config_path) + return false; + + if (!get_snappath_dir(c, clonelxcpath)) + return false; + + return remove_all_snapshots(clonelxcpath); } static bool lxcapi_may_control(struct lxc_container *c) @@ -3307,6 +3443,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath { struct lxc_container *c; + if (!name) + return NULL; + c = malloc(sizeof(*c)); if (!c) { fprintf(stderr, "failed to malloc lxc_container\n"); @@ -3353,7 +3492,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath if (ongoing_create(c) == 2) { ERROR("Error: %s creation was not completed", c->name); - lxcapi_destroy(c); + container_destroy(c); lxcapi_clear_config(c); } c->daemonize = true; @@ -3378,6 +3517,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath c->wait = lxcapi_wait; c->set_config_item = lxcapi_set_config_item; c->destroy = lxcapi_destroy; + c->destroy_with_snapshots = lxcapi_destroy_with_snapshots; c->rename = lxcapi_rename; c->save_config = lxcapi_save_config; c->get_keys = lxcapi_get_keys; @@ -3403,6 +3543,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath c->snapshot_list = lxcapi_snapshot_list; c->snapshot_restore = lxcapi_snapshot_restore; c->snapshot_destroy = lxcapi_snapshot_destroy; + c->snapshot_destroy_all = lxcapi_snapshot_destroy_all; c->may_control = lxcapi_may_control; c->add_device_node = lxcapi_add_device_node; c->remove_device_node = lxcapi_remove_device_node; diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h index 1d0628a..5085c43 100644 --- a/src/lxc/lxccontainer.h +++ b/src/lxc/lxccontainer.h @@ -286,6 +286,17 @@ struct lxc_container { bool (*destroy)(struct lxc_container *c); /*! + * \brief Delete the container and all its snapshots. + * + * \param c Container. + * + * \return \c true on success, else \c false. + * + * \note Container must be stopped. + */ + bool (*destroy_with_snapshots)(struct lxc_container *c); + + /*! * \brief Save configuaration to a file. * * \param c Container. @@ -649,7 +660,7 @@ struct lxc_container { * \brief Create a container snapshot. * * Assuming default paths, snapshots will be created as - * \c /var/lib/lxcsnaps/\<c\>/snap\<n\> + * \c /var/lib/lxc/\<c\>/snaps/snap\<n\> * where \c \<c\> represents the container name and \c \<n\> * represents the zero-based snapshot number. * @@ -691,7 +702,7 @@ struct lxc_container { * fail if the snapshot is overlay-based, since the snapshots * will pin the original container. * \note As an example, if the container exists as \c /var/lib/lxc/c1, snapname might be \c 'snap0' - * (representing \c /var/lib/lxcsnaps/c1/snap0). If \p newname is \p c2, + * (representing \c /var/lib/lxc/c1/snaps/snap0). If \p newname is \p c2, * then \c snap0 will be copied to \c /var/lib/lxc/c2. */ bool (*snapshot_restore)(struct lxc_container *c, const char *snapname, const char *newname); @@ -707,6 +718,15 @@ struct lxc_container { bool (*snapshot_destroy)(struct lxc_container *c, const char *snapname); /*! + * \brief Destroy all the container's snapshot. + * + * \param c Container. + * + * \return \c true on success, else \c false. + */ + bool (*snapshot_destroy_all)(struct lxc_container *c); + + /*! * \brief Determine if the caller may control the container. * * \param c Container. diff --git a/src/lxc/lxclock.c b/src/lxc/lxclock.c index 1d62729..9d1c6f4 100644 --- a/src/lxc/lxclock.c +++ b/src/lxc/lxclock.c @@ -108,8 +108,8 @@ static char *lxclock_name(const char *p, const char *n) * $XDG_RUNTIME_DIR + "/lock/lxc/$lxcpath/$lxcname + '\0' if non-root */ - /* length of "/lock/lxc/" + $lxcpath + "/" + $lxcname + '\0' */ - len = strlen("/lock/lxc/") + strlen(n) + strlen(p) + 2; + /* length of "/lock/lxc/" + $lxcpath + "/" + "." + $lxcname + '\0' */ + len = strlen("/lock/lxc/") + strlen(n) + strlen(p) + 3; rundir = get_rundir(); if (!rundir) return NULL; @@ -129,7 +129,7 @@ static char *lxclock_name(const char *p, const char *n) ret = mkdir_p(dest, 0755); if (ret < 0) { /* fall back to "/tmp/" $(id -u) "/lxc/" $lxcpath / $lxcname + '\0' */ - int l2 = 33 + strlen(n) + strlen(p); + int l2 = 34 + strlen(n) + strlen(p); if (l2 > len) { char *d; d = realloc(dest, l2); @@ -147,9 +147,9 @@ static char *lxclock_name(const char *p, const char *n) free(rundir); return NULL; } - ret = snprintf(dest, len, "/tmp/%d/lxc/%s/%s", geteuid(), p, n); + ret = snprintf(dest, len, "/tmp/%d/lxc/%s/.%s", geteuid(), p, n); } else - ret = snprintf(dest, len, "%s/lock/lxc/%s/%s", rundir, p, n); + ret = snprintf(dest, len, "%s/lock/lxc/%s/.%s", rundir, p, n); free(rundir); diff --git a/src/lxc/utils.c b/src/lxc/utils.c index b076ce7..738bf5e 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -46,12 +46,14 @@ lxc_log_define(lxc_utils, lxc); -static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) +static int _recursive_rmdir_onedev(char *dirname, dev_t pdev, + const char *exclude, int level) { struct dirent dirent, *direntp; DIR *dir; int ret, failed=0; char pathname[MAXPATHLEN]; + bool hadexclude = false; dir = opendir(dirname); if (!dir) { @@ -76,6 +78,29 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) failed=1; continue; } + + if (!level && exclude && !strcmp(direntp->d_name, exclude)) { + ret = rmdir(pathname); + if (ret < 0) { + switch(errno) { + case ENOTEMPTY: + INFO("Not deleting snapshots"); + hadexclude = true; + break; + case ENOTDIR: + ret = unlink(pathname); + if (ret) + INFO("%s: failed to remove %s", __func__, pathname); + break; + default: + SYSERROR("%s: failed to rmdir %s", __func__, pathname); + failed = 1; + break; + } + } + continue; + } + ret = lstat(pathname, &mystat); if (ret) { ERROR("%s: failed to stat %s", __func__, pathname); @@ -85,7 +110,7 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) if (mystat.st_dev != pdev) continue; if (S_ISDIR(mystat.st_mode)) { - if (_recursive_rmdir_onedev(pathname, pdev) < 0) + if (_recursive_rmdir_onedev(pathname, pdev, exclude, level+1) < 0) failed=1; } else { if (unlink(pathname) < 0) { @@ -96,8 +121,10 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) } if (rmdir(dirname) < 0) { - ERROR("%s: failed to delete %s", __func__, dirname); - failed=1; + if (!hadexclude) { + ERROR("%s: failed to delete %s", __func__, dirname); + failed=1; + } } ret = closedir(dir); @@ -110,7 +137,7 @@ static int _recursive_rmdir_onedev(char *dirname, dev_t pdev) } /* returns 0 on success, -1 if there were any failures */ -extern int lxc_rmdir_onedev(char *path) +extern int lxc_rmdir_onedev(char *path, const char *exclude) { struct stat mystat; @@ -119,7 +146,7 @@ extern int lxc_rmdir_onedev(char *path) return -1; } - return _recursive_rmdir_onedev(path, mystat.st_dev); + return _recursive_rmdir_onedev(path, mystat.st_dev, exclude, 0); } static int mount_fs(const char *source, const char *target, const char *type) diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 691e56c..8516fcf 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -34,7 +34,7 @@ #include "config.h" /* returns 1 on success, 0 if there were any failures */ -extern int lxc_rmdir_onedev(char *path); +extern int lxc_rmdir_onedev(char *path, const char *exclude); extern void lxc_setup_fs(void); extern int get_u16(unsigned short *val, const char *arg, int base); extern int mkdir_p(const char *dir, mode_t mode); diff --git a/src/tests/snapshot.c b/src/tests/snapshot.c index 09cee1a..21acd3e 100644 --- a/src/tests/snapshot.c +++ b/src/tests/snapshot.c @@ -32,28 +32,21 @@ static void try_to_remove(void) { struct lxc_container *c; - char snappath[1024]; c = lxc_container_new(RESTNAME, NULL); if (c) { - if (c->is_defined(c)) - c->destroy(c); - lxc_container_put(c); - } - snprintf(snappath, 1024, "%ssnaps/%s", lxc_get_global_config_item("lxc.lxcpath"), MYNAME); - c = lxc_container_new("snap0", snappath); - if (c) { + c->snapshot_destroy_all(c); if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); } c = lxc_container_new(MYNAME2, NULL); if (c) { - if (c->is_defined(c)) - c->destroy(c); + c->destroy_with_snapshots(c); lxc_container_put(c); } c = lxc_container_new(MYNAME, NULL); if (c) { + c->snapshot_destroy_all(c); if (c->is_defined(c)) c->destroy(c); lxc_container_put(c); @@ -77,7 +70,7 @@ int main(int argc, char *argv[]) if (c->is_defined(c)) { fprintf(stderr, "%d: %s thought it was defined\n", __LINE__, MYNAME); - (void) c->destroy(c); + (void) c->destroy_with_snapshots(c); } if (!c->set_config_item(c, "lxc.network.type", "empty")) { fprintf(stderr, "%s: %d: failed to set network type\n", __FILE__, __LINE__); @@ -95,11 +88,11 @@ int main(int argc, char *argv[]) goto err; } - // rootfs should be ${lxcpath}snaps/${lxcname}/snap0/rootfs + // rootfs should be ${lxcpath}${lxcname}/snaps/snap0/rootfs struct stat sb; int ret; char path[1024]; - snprintf(path, 1024, "%ssnaps/%s/snap0/rootfs", lxc_get_global_config_item("lxc.lxcpath"), MYNAME); + snprintf(path, 1024, "%s/%s/snaps/snap0/rootfs", lxc_get_global_config_item("lxc.lxcpath"), MYNAME); ret = stat(path, &sb); if (ret != 0) { fprintf(stderr, "%s: %d: snapshot was not actually created\n", __FILE__, __LINE__); @@ -169,17 +162,7 @@ int main(int argc, char *argv[]) goto err; } - if (!c2->destroy(c2)) { - fprintf(stderr, "%s: %d: failed to destroy container\n", __FILE__, __LINE__); - goto err; - } - good: - if (!c->destroy(c)) { - fprintf(stderr, "%s: %d: failed to destroy container\n", __FILE__, __LINE__); - goto err; - } - lxc_container_put(c); try_to_remove(); -- 2.0.0.rc0 _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel