]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: add a command to delete all snapshots of an image
authorJosh Durgin <josh.durgin@dreamhost.com>
Thu, 5 Jan 2012 01:07:07 +0000 (17:07 -0800)
committerJosh Durgin <josh.durgin@dreamhost.com>
Thu, 5 Jan 2012 18:19:17 +0000 (10:19 -0800)
This makes deleting images with many snapshots easier.

Signed-off-by: Josh Durgin <josh.durgin@dreamhost.com>
doc/man/8/rbd.rst
man/rbd.8
qa/workunits/rbd/copy.sh
qa/workunits/rbd/kernel.sh
src/rbd.cc
src/test/cli/rbd/help.t
src/test/cli/rbd/invalid-snap-usage.t

index 12a124401edc5ed2e1a4bfd854a56f9d271aaa26..fbf8e3cf638910364d879d3d95f85f80b83aa4f2 100644 (file)
@@ -81,7 +81,8 @@ Commands
   Resizes rbd image. The size parameter also needs to be specified.
 
 :command:`rm` [*image-name*]
-  Deletes rbd image (including all data blocks)
+  Deletes an rbd image (including all data blocks). If the image has
+  snapshots, this fails and nothing is deleted.
 
 :command:`export` [*image-name*] [*dest-path*]
   Exports image to dest path.
@@ -108,6 +109,9 @@ Commands
 :command:`snap` rm [*image-name*]
   Removes the specified snapshot.
 
+:command:`snap` purge [*image-name*]
+  Removes all snapshots from an image.
+
 :command:`map` [*image-name*]
   Maps the specified image to a block device via the rbd kernel module.
 
index 16da65aea1f23f6f23bf99a2aa365a45e4b5b7b6..0278137d8578cc69cbb9313ec4d189c81bcfe326 100644 (file)
--- a/man/rbd.8
+++ b/man/rbd.8
@@ -103,7 +103,8 @@ Will create a new rbd image. You must also specify the size via \-\-size.
 Resizes rbd image. The size parameter also needs to be specified.
 .TP
 .B \fBrm\fP [\fIimage\-name\fP]
-Deletes rbd image (including all data blocks)
+Deletes an rbd image (including all data blocks). If the image has
+snapshots, this fails and nothing is deleted.
 .TP
 .B \fBexport\fP [\fIimage\-name\fP] [\fIdest\-path\fP]
 Exports image to dest path.
@@ -130,6 +131,9 @@ array and update the data head content to the snapshotted version.
 .B \fBsnap\fP rm [\fIimage\-name\fP]
 Removes the specified snapshot.
 .TP
+.B \fBsnap\fP purge [\fIimage\-name\fP]
+Removes all snapshots from an image.
+.TP
 .B \fBmap\fP [\fIimage\-name\fP]
 Maps the specified image to a block device via the rbd kernel module.
 .TP
index 3c6bb029abd9e2a4cd9d10b655a224fafe7b2cdb..5d922920ad9a4b69c3bcab5c95404875fe68b9bb 100755 (executable)
@@ -2,6 +2,7 @@
 
 TMP_FILES="/tmp/img1 /tmp/img1.new /tmp/img2 /tmp/img2.new /tmp/img3 /tmp/img3.new /tmp/img1.snap1"
 
+rbd snap purge testimg1 || true
 rbd rm testimg1 || true
 rbd rm testimg2 || true
 rbd rm testimg3 || true
index c0eced27193a27c6b168c0e3ab190b6254d4f557..bf8452aa578729a842e13f5aa79be312384c361e 100755 (executable)
@@ -20,6 +20,7 @@ function clean_up {
        rbd unmap /dev/rbd/rbd/testimg1 || true
        rbd unmap /dev/rbd/rbd/testimg1@snap1 || true
        sudo chown root /sys/bus/rbd/add /sys/bus/rbd/remove
+       rbd snap purge testimg1 || true
        rbd rm testimg1 || true
        sudo rm -f $TMP_FILES
 }
index 216d0f9f2c7292de5346fe848286af0b048054ff..3f86de6357fe96c0eb3d8fe2765c4387be6720b2 100644 (file)
@@ -78,6 +78,7 @@ void usage()
        << "  snap create <--snap=name> [image-name]    create a snapshot\n"
        << "  snap rollback <--snap=name> [image-name]  rollback image head to snapshot\n"
        << "  snap rm <--snap=name> [image-name]        deletes a snapshot\n"
+       << "  snap purge [image-name]                   deletes all snapshots\n"
        << "  watch [image-name]                        watch events on image\n"
        << "  map [image-name]                          map the image to a block device\n"
        << "                                            using the kernel\n"
@@ -259,6 +260,25 @@ static int do_rollback_snap(librbd::Image& image, const char *snapname)
   return 0;
 }
 
+static int do_purge_snaps(librbd::Image& image)
+{
+  MyProgressContext pc("Removing all snapshots");
+  std::vector<librbd::snap_info_t> snaps;
+  int r = image.snap_list(snaps);
+  if (r < 0) {
+    pc.fail();
+    return r;
+  }
+
+  for (size_t i = 0; i < snaps.size(); ++i) {
+    image.snap_remove(snaps[i].name.c_str());
+    pc.update_progress(i + 1, snaps.size());
+  }
+
+  pc.finish();
+  return 0;
+}
+
 struct ExportContext {
   int fd;
   MyProgressContext pc;
@@ -815,6 +835,7 @@ enum {
   OPT_SNAP_ROLLBACK,
   OPT_SNAP_REMOVE,
   OPT_SNAP_LIST,
+  OPT_SNAP_PURGE,
   OPT_WATCH,
   OPT_MAP,
   OPT_UNMAP,
@@ -866,6 +887,8 @@ static int get_cmd(const char *cmd, bool snapcmd)
     if (strcmp(cmd, "ls") == 0||
         strcmp(cmd, "list") == 0)
       return OPT_SNAP_LIST;
+    if (strcmp(cmd, "purge") == 0)
+      return OPT_SNAP_PURGE;
   }
 
   return OPT_NO_CMD;
@@ -979,6 +1002,7 @@ int main(int argc, const char **argv)
       case OPT_SNAP_ROLLBACK:
       case OPT_SNAP_REMOVE:
       case OPT_SNAP_LIST:
+      case OPT_SNAP_PURGE:
       case OPT_WATCH:
       case OPT_MAP:
        set_conf_param(v, &imgname, NULL);
@@ -1083,8 +1107,8 @@ int main(int argc, const char **argv)
   if (imgname && talk_to_cluster &&
       (opt_cmd == OPT_RESIZE || opt_cmd == OPT_INFO || opt_cmd == OPT_SNAP_LIST ||
        opt_cmd == OPT_SNAP_CREATE || opt_cmd == OPT_SNAP_ROLLBACK ||
-       opt_cmd == OPT_SNAP_REMOVE || opt_cmd == OPT_EXPORT || opt_cmd == OPT_WATCH ||
-       opt_cmd == OPT_COPY)) {
+       opt_cmd == OPT_SNAP_REMOVE || opt_cmd == OPT_SNAP_PURGE ||
+       opt_cmd == OPT_EXPORT || opt_cmd == OPT_WATCH || opt_cmd == OPT_COPY)) {
     r = rbd.open(io_ctx, image, imgname);
     if (r < 0) {
       cerr << "error opening image " << imgname << ": " << cpp_strerror(-r) << std::endl;
@@ -1161,7 +1185,13 @@ int main(int argc, const char **argv)
   case OPT_RM:
     r = do_delete(rbd, io_ctx, imgname);
     if (r < 0) {
-      cerr << "delete error: " << cpp_strerror(-r) << std::endl;
+      if (r == -EBUSY) {
+       cerr << "delete error: image has snapshots - these must be deleted"
+            << " with 'rbd snap purge' before the image can be removed."
+            << std::endl;
+      } else {
+       cerr << "delete error: " << cpp_strerror(-r) << std::endl;
+      }
       exit(1);
     }
     break;
@@ -1222,6 +1252,18 @@ int main(int argc, const char **argv)
     }
     break;
 
+  case OPT_SNAP_PURGE:
+    if (!imgname) {
+      usage();
+      exit(1);
+    }
+    r = do_purge_snaps(image);
+    if (r < 0) {
+      cerr << "removing snaps failed: " << cpp_strerror(-r) << std::endl;
+      exit(1);
+    }
+    break;
+
   case OPT_EXPORT:
     if (!path) {
       cerr << "pathname should be specified" << std::endl;
index e9aafff4e235c3baac07eb1d7daaea95c9f3034b..3c804457b97b3895013fb4ccc2c14e1ceceb0891 100644 (file)
@@ -16,6 +16,7 @@
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
index 44037e4b13cff9bb919db6e2f6126dc43df42ea3..771e4c2fd2b5227c7a61eeb4be09903fb35777dd 100644 (file)
@@ -17,6 +17,7 @@
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
@@ -59,6 +60,7 @@
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel
     snap create <--snap=name> [image-name]    create a snapshot
     snap rollback <--snap=name> [image-name]  rollback image head to snapshot
     snap rm <--snap=name> [image-name]        deletes a snapshot
+    snap purge [image-name]                   deletes all snapshots
     watch [image-name]                        watch events on image
     map [image-name]                          map the image to a block device
                                               using the kernel