]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: add deep cp CLI method 19996/head
authorsongweibin <song.weibin@zte.com.cn>
Thu, 18 Jan 2018 02:56:19 +0000 (10:56 +0800)
committersongweibin <song.weibin@zte.com.cn>
Wed, 24 Jan 2018 01:04:33 +0000 (09:04 +0800)
Signed-off-by: songweibin <song.weibin@zte.com.cn>
doc/man/8/rbd.rst
qa/workunits/rbd/cli_generic.sh
qa/workunits/rbd/journal.sh
src/common/options.cc
src/librbd/deep_copy/ObjectCopyRequest.cc
src/librbd/deep_copy/SnapshotCopyRequest.cc
src/test/cli/rbd/help.t
src/test/cli/rbd/invalid-snap-usage.t
src/test/cli/rbd/not-enough-args.t
src/tools/rbd/action/Copy.cc

index edf09fdea43a96ed1fc538b9f8063e202bdade35..3096d234e70f798a6baeef84009470e0f61030eb 100644 (file)
@@ -201,6 +201,10 @@ Commands
   Will create a new rbd image. You must also specify the size via --size.  The
   --stripe-unit and --stripe-count arguments are optional, but must be used together.
 
+:command:`deep cp` (*src-image-spec* | *src-snap-spec*) *dest-image-spec*
+  Deep copy the content of a src-image into the newly created dest-image.
+  Dest-image will have the same size, object size, image format, and snapshots as src-image.
+
 :command:`diff` [--from-snap *snap-name*] [--whole-object] *image-spec* | *snap-spec*
   Dump a list of byte extents in the image that have changed since the specified start
   snapshot, or since the image was created.  Each output line includes the starting offset
index 5318f507c15c7b248e4f13a7200e0d70e987e834..23fdbcbadcbb0e9b9013707b5aaa596a769ff6d1 100755 (executable)
@@ -3,7 +3,7 @@
 # make sure rbd pool is EMPTY.. this is a test script!!
 rbd ls | wc -l | grep -v '^0$' && echo "nonempty rbd pool, aborting!  run this script on an empty test cluster only." && exit 1
 
-IMGS="testimg1 testimg2 testimg3 testimg-diff1 testimg-diff2 testimg-diff3 foo foo2 bar bar2 test1 test2 test3 clone2"
+IMGS="testimg1 testimg2 testimg3 testimg4 testimg5 testimg6 testimg-diff1 testimg-diff2 testimg-diff3 foo foo2 bar bar2 test1 test2 test3 clone2"
 
 tiered=0
 if ceph osd dump | grep ^pool | grep "'rbd'" | grep tier; then
@@ -73,6 +73,14 @@ test_others() {
     rbd info testimg-diff2 | grep 'size 256 MB'
     rbd info testimg-diff3 | grep 'size 128 MB'
 
+    # deep copies
+    rbd deep copy testimg1 testimg4
+    rbd deep copy testimg1 --snap=snap1 testimg5
+    rbd info testimg4 | grep 'size 128 MB'
+    rbd info testimg5 | grep 'size 256 MB'
+    rbd snap ls testimg4 | grep -v 'SNAPID' | wc -l | grep 1
+    rbd snap ls testimg4 | grep '.*snap1.*'
+
     rbd export testimg1 /tmp/img1.new
     rbd export testimg2 /tmp/img2.new
     rbd export testimg3 /tmp/img3.new
@@ -100,6 +108,7 @@ test_others() {
     rbd rm testimg3
     rbd create testimg2 -s 0
     rbd cp testimg2 testimg3
+    rbd deep cp testimg2 testimg6
 
     # remove snapshots
     rbd snap rm --snap=snap1 testimg1
index 02a8ebd8c13fcf3573f190ed04dddf3651974fab..157e7ad8af57caaaf5d802a44dab7746b1646c87 100755 (executable)
@@ -172,6 +172,30 @@ test_rbd_copy()
     rbd remove ${image}
 }
 
+test_rbd_deep_copy()
+{
+    local src=testrbdcopys$$
+    rbd create --size 256 ${src}
+    rbd snap create ${src}@snap1
+
+    local dest=testrbdcopy$$
+    rbd deep copy --image-feature exclusive-lock --image-feature journaling \
+        --journal-pool rbd \
+        --journal-object-size 20M \
+        --journal-splay-width 6 \
+        ${src} ${dest}
+
+    rbd snap purge ${src}
+    rbd remove ${src}
+
+    rbd_assert_eq ${dest} 'journal info' '//journal/order' 25
+    rbd_assert_eq ${dest} 'journal info' '//journal/splay_width' 6
+    rbd_assert_eq ${dest} 'journal info' '//journal/object_pool' rbd
+
+    rbd snap purge ${dest}
+    rbd remove ${dest}
+}
+
 test_rbd_clone()
 {
     local parent=testrbdclonep$$
index 505cf277e7fae3df9ade7019dd315b0af7b76657..2d8eccc73e3ce4d81d38bf78d91fd1cd7d373026 100644 (file)
@@ -5956,7 +5956,7 @@ static std::vector<Option> get_rbd_options() {
     .set_description("threshold for issuing a sparse-read")
     .set_long_description("minimum number of sequential bytes to read against "
                           "an object before issuing a sparse-read request to "
-                          "the cluster. 0 implies it must be a full object read"
+                          "the cluster. 0 implies it must be a full object read "
                           "to issue a sparse-read, 1 implies always use "
                           "sparse-read, and any value larger than the maximum "
                           "object size will disable sparse-read for all "
index 8bd9c5768382611c6196c66eba4a052b1598295e..39ed63c3c3cec76fe1ccd00e39e58e90fd6448b9 100644 (file)
@@ -245,7 +245,7 @@ void ObjectCopyRequest<I>::send_write_object() {
     case COPY_OP_TYPE_WRITE:
       buffer_offset = 0;
       for (auto &e : copy_op.dst_extent_map) {
-        ldout(m_cct, 20) << "write op: " << e.first << "~" << e.second
+        ldout(m_cct, 20) << "write op: " << e.first << "~" << e.second
                          << dendl;
         bufferlist tmpbl;
         tmpbl.substr_of(copy_op.out_bl, buffer_offset, e.second);
index 4f5edd39e42cc33a623a15846a1fa8a07f490267..72c764132edddb99429c5652aa88616e87be5b2f 100644 (file)
@@ -133,7 +133,9 @@ void SnapshotCopyRequest<I>::send_snap_unprotect() {
       bool src_unprotected;
       r = m_src_image_ctx->is_snap_unprotected(snap_seq_it->first,
                                                &src_unprotected);
-      ldout(m_cct, 20) << "m_src_image_ctx->is_snap_unprotected("<< snap_seq_it->first << "): r=" << r << ", src_unprotected=" << src_unprotected << dendl;
+      ldout(m_cct, 20) << "m_src_image_ctx->is_snap_unprotected("
+                       << snap_seq_it->first << "): r=" << r
+                       << ", src_unprotected=" << src_unprotected << dendl;
       if (r == -ENOENT) {
         src_unprotected = true;
         r = 0;
index 506a18356602e22f1225bca58ba0c35cc8e13889..3cba3d4ab92268f6641f019cffad6b7db6820c41 100644 (file)
@@ -14,6 +14,7 @@ Skip test on FreeBSD as it generates different output there.
       clone                             Clone a snapshot into a COW child image.
       copy (cp)                         Copy src image to dest.
       create                            Create an empty image.
+      deep copy (deep cp)               Deep copy src image to dest.
       diff                              Print extents that differ since a
                                         previous snap, or image creation.
       disk-usage (du)                   Show disk usage stats for pool, image or
@@ -303,6 +304,53 @@ Skip test on FreeBSD as it generates different output there.
     (-) supports disabling-only on existing images
     (+) enabled by default for new images if features not specified
   
+  rbd help deep copy
+  usage: rbd deep copy [--pool <pool>] [--image <image>] [--snap <snap>] 
+                       [--dest-pool <dest-pool>] [--dest <dest>] 
+                       [--order <order>] [--object-size <object-size>] 
+                       [--image-feature <image-feature>] [--image-shared] 
+                       [--stripe-unit <stripe-unit>] 
+                       [--stripe-count <stripe-count>] [--data-pool <data-pool>] 
+                       [--journal-splay-width <journal-splay-width>] 
+                       [--journal-object-size <journal-object-size>] 
+                       [--journal-pool <journal-pool>] [--no-progress] 
+                       <source-image-or-snap-spec> <dest-image-spec> 
+  
+  Deep copy src image to dest.
+  
+  Positional arguments
+    <source-image-or-snap-spec>  source image or snapshot specification
+                                 (example:
+                                 [<pool-name>/]<image-name>[@<snap-name>])
+    <dest-image-spec>            destination image specification
+                                 (example: [<pool-name>/]<image-name>)
+  
+  Optional arguments
+    -p [ --pool ] arg            source pool name
+    --image arg                  source image name
+    --snap arg                   source snapshot name
+    --dest-pool arg              destination pool name
+    --dest arg                   destination image name
+    --order arg                  object order [12 <= order <= 25]
+    --object-size arg            object size in B/K/M [4K <= object size <= 32M]
+    --image-feature arg          image features
+                                 [layering(+), exclusive-lock(+*),
+                                 object-map(+*), fast-diff(+*), deep-flatten(+-),
+                                 journaling(*)]
+    --image-shared               shared image
+    --stripe-unit arg            stripe unit in B/K/M
+    --stripe-count arg           stripe count
+    --data-pool arg              data pool
+    --journal-splay-width arg    number of active journal objects
+    --journal-object-size arg    size of journal objects
+    --journal-pool arg           pool for journal objects
+    --no-progress                disable progress output
+  
+  Image Features:
+    (*) supports enabling/disabling on existing images
+    (-) supports disabling-only on existing images
+    (+) enabled by default for new images if features not specified
+  
   rbd help diff
   usage: rbd diff [--pool <pool>] [--image <image>] [--snap <snap>] 
                   [--from-snap <from-snap>] [--whole-object] [--format <format>] 
index 5f98c1a243e8b5bcc26d27b8e8a10fb1de5c8089..176092800e5020e1a1d1a314fb8cb961dd5e4cf0 100644 (file)
   $ rbd cp foo@snap bar@snap
   rbd: destination snapname specified for a command that doesn't use it
   [22]
+  $ rbd deep cp foo bar@snap
+  rbd: destination snapname specified for a command that doesn't use it
+  [22]
+  $ rbd deep cp foo@snap bar@snap
+  rbd: destination snapname specified for a command that doesn't use it
+  [22]
   $ rbd mv foo bar@snap
   rbd: destination snapname specified for a command that doesn't use it
   [22]
index 3cc98b2899677e9be7ed9f6651a60f8c205e82dc..3d44eaf688a77cbd76731d61493b5d32b9d94ad1 100644 (file)
   $ rbd cp foo@snap
   rbd: destination image name was not specified
   [22]
+  $ rbd deep cp
+  rbd: image name was not specified
+  [22]
+  $ rbd deep cp foo
+  rbd: destination image name was not specified
+  [22]
+  $ rbd deep cp foo@snap
+  rbd: destination image name was not specified
+  [22]
   $ rbd mv
   rbd: image name was not specified
   [22]
index f951811eebe62cf8357888b21f85d78e08086e4f..cad4c980ab54e401faeea4b0ff83ed517aacc980 100644 (file)
@@ -102,6 +102,87 @@ Shell::Action action(
   {"copy"}, {"cp"}, "Copy src image to dest.", at::get_long_features_help(),
   &get_arguments, &execute);
 
+static int do_deep_copy(librbd::Image &src, librados::IoCtx& dest_pp,
+                       const char *destname, librbd::ImageOptions& opts,
+                       bool no_progress)
+{
+  utils::ProgressContext pc("Image deep copy", no_progress);
+  int r = src.deep_copy_with_progress(dest_pp, destname, opts, pc);
+  if (r < 0){
+    pc.fail();
+    return r;
+  }
+  pc.finish();
+  return 0;
+}
+
+void get_arguments_deep(po::options_description *positional,
+                        po::options_description *options) {
+  at::add_image_or_snap_spec_options(positional, options,
+                                     at::ARGUMENT_MODIFIER_SOURCE);
+  at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_DEST);
+  at::add_create_image_options(options, false);
+  at::add_no_progress_option(options);
+}
+
+int execute_deep(const po::variables_map &vm,
+                 const std::vector<std::string> &ceph_global_init_args) {
+  size_t arg_index = 0;
+  std::string pool_name;
+  std::string image_name;
+  std::string snap_name;
+  int r = utils::get_pool_image_snapshot_names(
+    vm, at::ARGUMENT_MODIFIER_SOURCE, &arg_index, &pool_name, &image_name,
+    &snap_name, utils::SNAPSHOT_PRESENCE_PERMITTED,
+    utils::SPEC_VALIDATION_NONE);
+  if (r < 0) {
+    return r;
+  }
+
+  std::string dst_pool_name;
+  std::string dst_image_name;
+  std::string dst_snap_name;
+  r = utils::get_pool_image_snapshot_names(
+    vm, at::ARGUMENT_MODIFIER_DEST, &arg_index, &dst_pool_name, &dst_image_name,
+    &dst_snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_FULL);
+  if (r < 0) {
+    return r;
+  }
+
+  librbd::ImageOptions opts;
+  r = utils::get_image_options(vm, false, &opts);
+  if (r < 0) {
+    return r;
+  }
+
+  librados::Rados rados;
+  librados::IoCtx io_ctx;
+  librbd::Image image;
+  r = utils::init_and_open_image(pool_name, image_name, "", snap_name, true,
+                                 &rados, &io_ctx, &image);
+  if (r < 0) {
+    return r;
+  }
+
+  librados::IoCtx dst_io_ctx;
+  r = utils::init_io_ctx(rados, dst_pool_name, &dst_io_ctx);
+  if (r < 0) {
+    return r;
+  }
+
+  r = do_deep_copy(image, dst_io_ctx, dst_image_name.c_str(), opts,
+                   vm[at::NO_PROGRESS].as<bool>());
+  if (r < 0) {
+    std::cerr << "rbd: deep copy failed: " << cpp_strerror(r) << std::endl;
+    return r;
+  }
+  return 0;
+}
+
+Shell::Action action_deep(
+  {"deep", "copy"}, {"deep", "cp"}, "Deep copy src image to dest.", at::get_long_features_help(),
+  &get_arguments_deep, &execute_deep);
+
 } // namespace copy
 } // namespace action
 } // namespace rbd