]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: add new 'migration prepare --import-only' CLI optional
authorJason Dillaman <dillaman@redhat.com>
Wed, 21 Oct 2020 18:29:15 +0000 (14:29 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 3 Nov 2020 00:57:58 +0000 (19:57 -0500)
The '--import-only' optional can be combined with either a
'--source-spec' or '--source-spec-path' optional to define
the source for the read-only import.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/cli/rbd/help.t
src/tools/rbd/action/Migration.cc

index 7eeb4ab6e4bc483eca56d2b76dd9bca2c66ba661..3d89f0bd5484f5f0bcd9452066a06d74cdbbb6c7 100644 (file)
     --no-progress        disable progress output
   
   rbd help migration prepare
-  usage: rbd migration prepare [--pool <pool>] [--namespace <namespace>] 
-                               [--image <image>] [--dest-pool <dest-pool>] 
+  usage: rbd migration prepare [--import-only] 
+                               [--source-spec-path <source-spec-path>] 
+                               [--source-spec <source-spec>] [--pool <pool>] 
+                               [--namespace <namespace>] [--image <image>] 
+                               [--dest-pool <dest-pool>] 
                                [--dest-namespace <dest-namespace>] 
                                [--dest <dest>] [--image-format <image-format>] 
                                [--new-format] [--order <order>] 
                               (example: [<pool-name>/[<namespace>/]]<image-name>)
   
   Optional arguments
+    --import-only             only import data from source
+    --source-spec-path arg    source-spec file (or '-' for stdin)
+    --source-spec arg         source-spec
     -p [ --pool ] arg         source pool name
     --namespace arg           source namespace name
     --image arg               source image name
index 5a929a75939d2adde2a679e476b87b623bcb4cea..eef82d1a1b345df4d0e8cb60cdfdf5e93e47843e 100644 (file)
@@ -1,12 +1,16 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 
+#include "include/compat.h"
 #include "common/errno.h"
+#include "common/safe_io.h"
 
 #include "tools/rbd/ArgumentTypes.h"
 #include "tools/rbd/Shell.h"
 #include "tools/rbd/Utils.h"
 
+#include <sys/types.h>
+#include <fcntl.h>
 #include <iostream>
 #include <boost/program_options.hpp>
 
@@ -17,21 +21,6 @@ namespace migration {
 namespace at = argument_types;
 namespace po = boost::program_options;
 
-static int do_prepare(librados::IoCtx& io_ctx, const std::string &image_name,
-                      librados::IoCtx& dest_io_ctx,
-                      const std::string &dest_image_name,
-                      librbd::ImageOptions& opts) {
-  int r = librbd::RBD().migration_prepare(io_ctx, image_name.c_str(),
-                                          dest_io_ctx, dest_image_name.c_str(),
-                                          opts);
-  if (r < 0) {
-    std::cerr << "rbd: preparing migration failed: " << cpp_strerror(r)
-              << std::endl;
-    return r;
-  }
-  return 0;
-}
-
 static int do_execute(librados::IoCtx& io_ctx, const std::string &image_name,
                       bool no_progress) {
   utils::ProgressContext pc("Image migration", no_progress);
@@ -143,6 +132,12 @@ static int do_commit(librados::IoCtx& io_ctx, const std::string &image_name,
 
 void get_prepare_arguments(po::options_description *positional,
                            po::options_description *options) {
+  options->add_options()
+    ("import-only", po::bool_switch(), "only import data from source")
+    ("source-spec-path", po::value<std::string>(),
+     "source-spec file (or '-' for stdin)")
+    ("source-spec", po::value<std::string>(),
+     "source-spec");
   at::add_image_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, true);
@@ -163,23 +158,90 @@ int execute_prepare(const po::variables_map &vm,
     return r;
   }
 
+  std::string dst_pool_name;
+  std::string dst_namespace_name;
+  std::string dst_image_name;
+  r = utils::get_pool_image_snapshot_names(
+    vm, at::ARGUMENT_MODIFIER_DEST, &arg_index, &dst_pool_name,
+    &dst_namespace_name, &dst_image_name, nullptr, false,
+    utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_FULL);
+  if (r < 0) {
+    return r;
+  }
+
+  bool import_only = vm["import-only"].as<bool>();
+  std::string source_spec;
+  if (vm.count("source-spec") && vm.count("source-spec-path")) {
+    std::cerr << "rbd: cannot specify both source-image-spec and "
+              << "source-spec/source-spec-file" << std::endl;
+    return -EINVAL;
+  } else if (vm.count("source-spec-path")) {
+    std::string source_spec_path = vm["source-spec-path"].as<std::string>();
+
+    int fd = STDIN_FILENO;
+    if (source_spec_path != "-") {
+      fd = open(source_spec_path.c_str(), O_RDONLY);
+      if (fd < 0) {
+        r = -errno;
+        std::cerr << "rbd: error opening " << source_spec_path << std::endl;
+        return r;
+      }
+    }
+
+    source_spec.resize(4096);
+    r = safe_read(fd, source_spec.data(), source_spec.size() - 1);
+    if (fd != STDIN_FILENO) {
+      VOID_TEMP_FAILURE_RETRY(close(fd));
+    }
+
+    if (r >= 0) {
+      source_spec.resize(r);
+    } else {
+      std::cerr << "rbd: error reading source-spec file: " << cpp_strerror(r)
+                << std::endl;
+      return r;
+    }
+  } else if (vm.count("source-spec")) {
+    source_spec = vm["source-spec"].as<std::string>();
+  }
+
   librados::Rados rados;
   librados::IoCtx io_ctx;
   r = utils::init(pool_name, namespace_name, &rados, &io_ctx);
   if (r < 0) {
     return r;
   }
-  io_ctx.set_pool_full_try();
 
-  std::string dest_pool_name;
-  std::string dest_namespace_name;
-  std::string dest_image_name;
-  r = utils::get_pool_image_snapshot_names(
-    vm, at::ARGUMENT_MODIFIER_DEST, &arg_index, &dest_pool_name,
-    &dest_namespace_name, &dest_image_name, nullptr, false,
-    utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_FULL);
-  if (r < 0) {
-    return r;
+  librados::IoCtx dst_io_ctx;
+  if (source_spec.empty()) {
+    utils::normalize_pool_name(&dst_pool_name);
+    r = utils::init_io_ctx(rados, dst_pool_name, dst_namespace_name,
+                           &dst_io_ctx);
+    if (r < 0) {
+      return r;
+    }
+  }
+
+  if (import_only && source_spec.empty()) {
+    std::stringstream ss;
+    ss << R"({)"
+       << R"("type":"native",)"
+       << R"("pool_id":)" << io_ctx.get_id() << R"(,)"
+       << R"("pool_namespace":")" << io_ctx.get_namespace() << R"(",)"
+       << R"("image_name":")" << image_name << R"(")"
+       << R"(})";
+    source_spec = ss.str();
+
+    if (dst_image_name.empty()) {
+      std::cerr << "rbd: destination image name must be provided" << std::endl;
+      return -EINVAL;
+    }
+    io_ctx = dst_io_ctx;
+    image_name = dst_image_name;
+  } else if (!import_only && !source_spec.empty()) {
+    std::cerr << "rbd: --import-only must be used in combination with "
+              << "source-spec/source-spec-path" << std::endl;
+    return -EINVAL;
   }
 
   librbd::ImageOptions opts;
@@ -188,18 +250,28 @@ int execute_prepare(const po::variables_map &vm,
     return r;
   }
 
-  librados::IoCtx dest_io_ctx;
-  utils::normalize_pool_name(&dest_pool_name);
-  r = utils::init_io_ctx(rados, dest_pool_name, dest_namespace_name,
-                         &dest_io_ctx);
-  if (r < 0) {
-    return r;
-  }
+  if (source_spec.empty()) {
+    if (dst_image_name.empty()) {
+      dst_image_name = image_name;
+    }
 
-  r = do_prepare(io_ctx, image_name, dest_pool_name.empty() ? io_ctx :
-                 dest_io_ctx, dest_image_name, opts);
-  if (r < 0) {
-    return r;
+    int r = librbd::RBD().migration_prepare(io_ctx, image_name.c_str(),
+                                            dst_io_ctx, dst_image_name.c_str(),
+                                            opts);
+    if (r < 0) {
+      std::cerr << "rbd: preparing migration failed: " << cpp_strerror(r)
+                << std::endl;
+      return r;
+    }
+  } else {
+    ceph_assert(import_only);
+    r = librbd::RBD().migration_prepare_import(source_spec.c_str(), io_ctx,
+                                               image_name.c_str(), opts);
+    if (r < 0) {
+      std::cerr << "rbd: preparing import migration failed: " << cpp_strerror(r)
+                << std::endl;
+      return r;
+    }
   }
 
   return 0;