]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: introduce --export-format to export command
authorDongsheng Yang <dongsheng.yang@easystack.cn>
Thu, 28 Jul 2016 12:11:08 +0000 (08:11 -0400)
committerDongsheng Yang <dongsheng.yang@easystack.cn>
Sun, 19 Feb 2017 12:42:03 +0000 (20:42 +0800)
Signed-off-by: Dongsheng Yang <dongsheng.yang@easystack.cn>
doc/man/8/rbd.rst
src/test/cli/rbd/help.t
src/tools/rbd/action/Export.cc

index d848214d58e6f6cb5cf0e25c03ac7c7c1adecc05..f2d0d92a3a60e7fb6e184af5279f5867a82766af 100644 (file)
@@ -224,8 +224,10 @@ Commands
   Deletes an rbd image (including all data blocks). If the image has
   snapshots, this fails and nothing is deleted.
 
-:command:`export` (*image-spec* | *snap-spec*) [*dest-path*]
+:command:`export` [--export-format *format (1 or 2)*] (*image-spec* | *snap-spec*) [*dest-path*]
   Exports image to dest path (use - for stdout).
+  The --export-format accepts '1' or '2' currently. Format 2 allow us to export not only the content
+  of image, but also the snapshots and other priorities, such as image_order, features.
 
 :command:`import` [--import-format *format (1 or 2)*] [--image-format *format-id*] [--object-size *size-in-B/K/M*] [--stripe-unit *size-in-B/K/M* --stripe-count *num*] [--image-feature *feature-name*]... [--image-shared] *src-path* [*image-spec*]
   Creates a new image and imports its data from path (use - for
index 820b7ea74d1c050706330fb21a5efc49f6dd8669..12a68367c6f4ec296911f53241095e35330b6b5e 100644 (file)
   rbd help export
   usage: rbd export [--pool <pool>] [--image <image>] [--snap <snap>] 
                     [--path <path>] [--no-progress] 
+                    [--export-format <export-format>] 
                     <source-image-or-snap-spec> <path-name> 
   
   Export image to file.
     --snap arg                   source snapshot name
     --path arg                   export file (or '-' for stdout)
     --no-progress                disable progress output
+    --export-format arg          format of image file
   
   rbd help export-diff
   usage: rbd export-diff [--pool <pool>] [--image <image>] [--snap <snap>] 
                     [--journal-splay-width <journal-splay-width>] 
                     [--journal-object-size <journal-object-size>] 
                     [--journal-pool <journal-pool>] [--no-progress] 
-                    [--import-format <import-format>] [--pool <pool>] 
+                    [--export-format <export-format>] [--pool <pool>] 
                     [--image <image>] 
                     <path-name> <dest-image-spec> 
   
     --journal-object-size arg size of journal objects
     --journal-pool arg        pool for journal objects
     --no-progress             disable progress output
-    --import-format arg       format of the file to be imported
+    --export-format arg       format of image file
     -p [ --pool ] arg         pool name (deprecated)
     --image arg               image name (deprecated)
   
index bffeb22611b3505e504b4f7a6a24c2d5a787df52..6c07440ee16e3674f6f9112eda511afb736bd872 100644 (file)
@@ -110,7 +110,7 @@ private:
 
 int do_export_diff_fd(librbd::Image& image, const char *fromsnapname,
                   const char *endsnapname, bool whole_object,
-                  int fd, bool no_progress)
+                  int fd, bool no_progress, int export_format)
 {
   int r;
   librbd::image_info_t info;
@@ -122,7 +122,10 @@ int do_export_diff_fd(librbd::Image& image, const char *fromsnapname,
   {
     // header
     bufferlist bl;
-    bl.append(utils::RBD_DIFF_BANNER);
+    if (export_format == 1)
+      bl.append(utils::RBD_DIFF_BANNER);
+    else
+      bl.append(utils::RBD_DIFF_BANNER_V2);
 
     __u8 tag;
     if (fromsnapname) {
@@ -192,9 +195,10 @@ int do_export_diff(librbd::Image& image, const char *fromsnapname,
   if (fd < 0)
     return -errno;
 
-  r = do_export_diff_fd(image, fromsnapname, endsnapname, whole_object, fd, no_progress);
+  r = do_export_diff_fd(image, fromsnapname, endsnapname, whole_object, fd, no_progress, 1);
 
-  close(fd);
+  if (fd != 1)
+    close(fd);
   if (r < 0 && fd != 1) {
     remove(path);
   }
@@ -283,11 +287,11 @@ class C_Export : public Context
 {
 public:
   C_Export(SimpleThrottle &simple_throttle, librbd::Image &image,
-                   uint64_t offset, uint64_t length, int fd)
+          uint64_t fd_offset, uint64_t offset, uint64_t length, int fd)
     : m_aio_completion(
         new librbd::RBD::AioCompletion(this, &utils::aio_context_callback)),
-      m_throttle(simple_throttle), m_image(image), m_offset(offset),
-      m_length(length), m_fd(fd)
+      m_throttle(simple_throttle), m_image(image), m_dest_offset(fd_offset),
+      m_offset(offset), m_length(length), m_fd(fd)
   {
   }
 
@@ -325,10 +329,10 @@ public:
         return;
       }
 
-      uint64_t chkret = lseek64(m_fd, m_offset, SEEK_SET);
-      if (chkret != m_offset) {
+      uint64_t chkret = lseek64(m_fd, m_dest_offset, SEEK_SET);
+      if (chkret != m_dest_offset) {
         cerr << "rbd: error seeking destination image to offset "
-             << m_offset << std::endl;
+             << m_dest_offset << std::endl;
         r = -errno;
         return;
       }
@@ -337,7 +341,7 @@ public:
     r = m_bufferlist.write_fd(m_fd);
     if (r < 0) {
       cerr << "rbd: error writing to destination image at offset "
-           << m_offset << std::endl;
+           << m_dest_offset << std::endl;
     }
   }
 
@@ -346,13 +350,20 @@ private:
   SimpleThrottle &m_throttle;
   librbd::Image &m_image;
   bufferlist m_bufferlist;
+  uint64_t m_dest_offset;
   uint64_t m_offset;
   uint64_t m_length;
   int m_fd;
 };
 
-static int do_export(librbd::Image& image, const char *path, bool no_progress)
+static int do_export(librbd::Image& image, const char *path, bool no_progress, int export_format)
 {
+  // check current supported formats.
+  if (export_format != 1 && export_format != 2) {
+    std::cerr << "rbd: wrong file format to import" << std::endl;
+    return -EINVAL;
+  }
+
   librbd::image_info_t info;
   int64_t r = image.stat(info, sizeof(info));
   if (r < 0)
@@ -376,34 +387,96 @@ static int do_export(librbd::Image& image, const char *path, bool no_progress)
   }
 
   utils::ProgressContext pc("Exporting image", no_progress);
-
   SimpleThrottle throttle(max_concurrent_ops, false);
   uint64_t period = image.get_stripe_count() * (1ull << info.order);
-  for (uint64_t offset = 0; offset < info.size; offset += period) {
-    if (throttle.pending_error()) {
-      break;
+
+  if (export_format == 2) {
+    size_t offset = 0;
+    // header
+    bufferlist bl;
+    bl.append(utils::RBD_IMAGE_BANNER_V2);
+
+    // size in header
+    uint64_t size = info.size;
+    ::encode(size, bl);
+
+    r = bl.write_fd(fd);
+    if (r < 0) {
+      goto out;
     }
+    offset += bl.length();
 
-    uint64_t length = min(period, info.size - offset);
-    C_Export *ctx = new C_Export(throttle, image, offset, length, fd);
-    ctx->send();
+    lseek(fd, offset, SEEK_SET);
 
-    pc.update_progress(offset, info.size);
-  }
+    // header for snapshots
+    bl.clear();
+    bl.append(utils::RBD_IMAGE_SNAPS_BANNER_V2);
 
-  r = throttle.wait_for_ret();
-  if (!to_stdout) {
-    if (r >= 0) {
-      r = ftruncate(fd, info.size);
+    std::vector<librbd::snap_info_t> snaps;
+    r = image.snap_list(snaps);
+    if (r < 0) {
+      goto out;
+    }
+
+    uint64_t snap_num = snaps.size() + 1;
+    ::encode(snap_num, bl);
+
+    r = bl.write_fd(fd);
+    if (r < 0) {
+      goto out;
+    }
+
+    if (0 == snap_num) {
+      goto out;
+    } else {
+      const char *last_snap = NULL;
+      for (size_t i = 0; i < snaps.size(); ++i) {
+       utils::snap_set(image, snaps[i].name.c_str());
+       r = do_export_diff_fd(image, last_snap, snaps[i].name.c_str(), false, fd, true, 2);
+       if (r < 0) {
+         goto out;
+       }
+       pc.update_progress(i, snaps.size() + 1);
+       last_snap = snaps[i].name.c_str();
+      }
+      utils::snap_set(image, std::string(""));
+      r = do_export_diff_fd(image, last_snap, nullptr, false, fd, true, 2);
+      if (r < 0) {
+       goto out;
+      }
+      pc.update_progress(snaps.size() + 1, snaps.size() + 1);
+    }
+  } else {
+    size_t file_size = 0;
+    for (uint64_t offset = 0; offset < info.size; offset += period) {
+      if (throttle.pending_error()) {
+       break;
+      }
+
+      uint64_t length = min(period, info.size - offset);
+      C_Export *ctx = new C_Export(throttle, image, file_size + offset, offset, length, fd);
+      ctx->send();
+
+      pc.update_progress(offset, info.size);
+    }
+
+    file_size += info.size;
+    r = throttle.wait_for_ret();
+    if (!to_stdout) {
+      if (r >= 0) {
+       r = ftruncate(fd, file_size);
+       r = lseek(fd, file_size, SEEK_SET);
+      }
     }
-    close(fd);
   }
 
-  if (r < 0) {
+out:
+  if (r < 0)
     pc.fail();
-  } else {
+  else
     pc.finish();
-  }
+  if (!to_stdout)
+    close(fd);
   return r;
 }
 
@@ -414,6 +487,8 @@ void get_arguments(po::options_description *positional,
   at::add_path_options(positional, options,
                        "export file (or '-' for stdout)");
   at::add_no_progress_option(options);
+  options->add_options()
+    ("export-format", po::value<int>(), "format to export image");
 }
 
 int execute(const po::variables_map &vm) {
@@ -443,8 +518,12 @@ int execute(const po::variables_map &vm) {
   if (r < 0) {
     return r;
   }
+  
+  int format = 1;
+  if (vm.count("export-format"))
+    format = vm["export-format"].as<int>();
 
-  r = do_export(image, path.c_str(), vm[at::NO_PROGRESS].as<bool>());
+  r = do_export(image, path.c_str(), vm[at::NO_PROGRESS].as<bool>(), format);
   if (r < 0) {
     std::cerr << "rbd: export error: " << cpp_strerror(r) << std::endl;
     return r;