]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rbd: new 'mirror pool peer bootstrap create/import' commands
authorJason Dillaman <dillaman@redhat.com>
Mon, 16 Sep 2019 17:21:40 +0000 (13:21 -0400)
committerJason Dillaman <dillaman@redhat.com>
Wed, 18 Sep 2019 18:06:49 +0000 (14:06 -0400)
These two commands simplify the process of creating users and
exchanging keys between two clusters.

Fixes: https://tracker.ceph.com/issues/41653
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/cli/rbd/help.t
src/tools/rbd/action/MirrorPool.cc

index be724d4907800b0bfbe098d7997c602e157b654c..803a61d782a34ad01039c2b4c2f07b6586876ddc 100644 (file)
       mirror pool info                  Show information about the pool mirroring
                                         configuration.
       mirror pool peer add              Add a mirroring peer to a pool.
+      mirror pool peer bootstrap create Create a peer bootstrap token to import
+                                        in a remote cluster
+      mirror pool peer bootstrap import Import a peer bootstrap token created
+                                        from a remote cluster
       mirror pool peer remove           Remove a mirroring peer from a pool.
       mirror pool peer set              Update mirroring peer settings.
       mirror pool promote               Promote all non-primary images in the
     --remote-mon-host arg    remote mon host(s)
     --remote-key-file arg    path to file containing remote key
   
+  rbd help mirror pool peer bootstrap create
+  usage: rbd mirror pool peer bootstrap create
+                                           [--pool <pool>] 
+                                           [--site-name <site-name>] 
+                                           <pool-name> 
+  
+  Create a peer bootstrap token to import in a remote cluster
+  
+  Positional arguments
+    <pool-name>          pool name
+  
+  Optional arguments
+    -p [ --pool ] arg    pool name
+    --site-name arg      local site name
+  
+  rbd help mirror pool peer bootstrap import
+  usage: rbd mirror pool peer bootstrap import
+                                           [--pool <pool>] 
+                                           [--site-name <site-name>] 
+                                           [--token-path <token-path>] 
+                                           [--direction <direction>] 
+                                           <pool-name> <token-path> 
+  
+  Import a peer bootstrap token created from a remote cluster
+  
+  Positional arguments
+    <pool-name>          pool name
+    <token-path>         bootstrap token file (or '-' for stdin)
+  
+  Optional arguments
+    -p [ --pool ] arg    pool name
+    --site-name arg      local site name
+    --token-path arg     bootstrap token file (or '-' for stdin)
+    --direction arg      mirroring direction (rx-only, rx-tx)
+                         [default: rx-tx]
+  
   rbd help mirror pool peer remove
   usage: rbd mirror pool peer remove [--pool <pool>] 
                                      <pool-name> <uuid> 
index 45a510fd405b7eb1da1cb5a280604a0378f9992c..941d1e57572fd683206e1eec2aead03235be2a8f 100644 (file)
@@ -63,6 +63,22 @@ int set_site_name(librados::Rados& rados, const std::string& site_name) {
   return 0;
 }
 
+struct MirrorPeerDirection {};
+
+void validate(boost::any& v, const std::vector<std::string>& values,
+              MirrorPeerDirection *target_type, int) {
+  po::validators::check_first_occurrence(v);
+  const std::string &s = po::validators::get_single_string(values);
+
+  if (s == "rx-only") {
+    v = boost::any(RBD_MIRROR_PEER_DIRECTION_RX);
+  } else if (s == "rx-tx") {
+    v = boost::any(RBD_MIRROR_PEER_DIRECTION_RX_TX);
+  } else {
+    throw po::validation_error(po::validation_error::invalid_option_value);
+  }
+}
+
 int validate_mirroring_enabled(librados::IoCtx& io_ctx) {
   librbd::RBD rbd;
   rbd_mirror_mode_t mirror_mode;
@@ -674,6 +690,154 @@ private:
 
 } // anonymous namespace
 
+void get_peer_bootstrap_create_arguments(po::options_description *positional,
+                                         po::options_description *options) {
+  at::add_pool_options(positional, options, false);
+  options->add_options()
+    (SITE_NAME.c_str(), po::value<std::string>(), "local site name");
+}
+
+int execute_peer_bootstrap_create(
+    const po::variables_map &vm,
+    const std::vector<std::string> &ceph_global_init_args) {
+  std::string pool_name;
+  size_t arg_index = 0;
+  int r = utils::get_pool_and_namespace_names(vm, true, true, &pool_name,
+                                              nullptr, &arg_index);
+  if (r < 0) {
+    return r;
+  }
+
+  librados::Rados rados;
+  librados::IoCtx io_ctx;
+  r = utils::init(pool_name, "", &rados, &io_ctx);
+  if (r < 0) {
+    return r;
+  }
+
+  r = validate_mirroring_enabled(io_ctx);
+  if (r < 0) {
+    return r;
+  }
+
+  if (vm.count(SITE_NAME)) {
+    r = set_site_name(rados, vm[SITE_NAME].as<std::string>());
+    if (r < 0) {
+      return r;
+    }
+  }
+
+  librbd::RBD rbd;
+  std::string token;
+  r = rbd.mirror_peer_bootstrap_create(io_ctx, &token);
+  if (r == -EEXIST) {
+    std::cerr << "rbd: mismatch with pre-existing RBD mirroring peer user caps"
+              << std::endl;
+  } else if (r < 0) {
+    std::cerr << "rbd: failed to create mirroring bootstrap token: "
+              << cpp_strerror(r) << std::endl;
+    return r;
+  }
+
+  std::cout << token << std::endl;
+  return 0;
+}
+
+void get_peer_bootstrap_import_arguments(po::options_description *positional,
+                                         po::options_description *options) {
+  at::add_pool_options(positional, options, false);
+  options->add_options()
+    (SITE_NAME.c_str(), po::value<std::string>(), "local site name");
+  positional->add_options()
+    ("token-path", po::value<std::string>(),
+     "bootstrap token file (or '-' for stdin)");
+  options->add_options()
+    ("token-path", po::value<std::string>(),
+     "bootstrap token file (or '-' for stdin)")
+    ("direction", po::value<MirrorPeerDirection>(),
+     "mirroring direction (rx-only, rx-tx)\n"
+     "[default: rx-tx]");
+}
+
+int execute_peer_bootstrap_import(
+    const po::variables_map &vm,
+    const std::vector<std::string> &ceph_global_init_args) {
+  std::string pool_name;
+  size_t arg_index = 0;
+  int r = utils::get_pool_and_namespace_names(vm, true, true, &pool_name,
+                                              nullptr, &arg_index);
+  if (r < 0) {
+    return r;
+  }
+
+  std::string token_path;
+  if (vm.count("token-path")) {
+    token_path = vm["token-path"].as<std::string>();
+  } else {
+    token_path = utils::get_positional_argument(vm, arg_index++);
+  }
+
+  if (token_path.empty()) {
+    std::cerr << "rbd: token path was not specified" << std::endl;
+    return -EINVAL;
+  }
+
+  rbd_mirror_peer_direction_t mirror_peer_direction =
+    RBD_MIRROR_PEER_DIRECTION_RX_TX;
+  if (vm.count("direction")) {
+    mirror_peer_direction = vm["direction"].as<rbd_mirror_peer_direction_t>();
+  }
+
+  int fd = STDIN_FILENO;
+  if (token_path != "-") {
+    fd = open(token_path.c_str(), O_RDONLY);
+    if (fd < 0) {
+      r = -errno;
+      std::cerr << "rbd: error opening " << token_path << std::endl;
+      return r;
+    }
+  }
+
+  char token[1024];
+  memset(token, 0, sizeof(token));
+  r = safe_read(fd, token, sizeof(token) - 1);
+  if (fd != STDIN_FILENO) {
+    VOID_TEMP_FAILURE_RETRY(close(fd));
+  }
+
+  if (r < 0) {
+    std::cerr << "rbd: error reading token file: " << cpp_strerror(r)
+              << std::endl;
+    return r;
+  }
+
+  librados::Rados rados;
+  librados::IoCtx io_ctx;
+  r = utils::init(pool_name, "", &rados, &io_ctx);
+  if (r < 0) {
+    return r;
+  }
+
+  if (vm.count(SITE_NAME)) {
+    r = set_site_name(rados, vm[SITE_NAME].as<std::string>());
+    if (r < 0) {
+      return r;
+    }
+  }
+
+  librbd::RBD rbd;
+  r = rbd.mirror_peer_bootstrap_import(io_ctx, mirror_peer_direction, token);
+  if (r == -ENOSYS) {
+    std::cerr << "rbd: mirroring is not enabled on remote peer" << std::endl;
+    return r;
+  } else if (r < 0) {
+    std::cerr << "rbd: failed to import peer bootstrap token" << std::endl;
+    return r;
+  }
+
+  return 0;
+}
+
 void get_peer_add_arguments(po::options_description *positional,
                             po::options_description *options) {
   at::add_pool_options(positional, options, false);
@@ -1320,6 +1484,15 @@ int execute_demote(const po::variables_map &vm,
   return r;
 }
 
+Shell::Action action_bootstrap_create(
+  {"mirror", "pool", "peer", "bootstrap", "create"}, {},
+  "Create a peer bootstrap token to import in a remote cluster", "",
+  &get_peer_bootstrap_create_arguments, &execute_peer_bootstrap_create);
+Shell::Action action_bootstreap_import(
+  {"mirror", "pool", "peer", "bootstrap", "import"}, {},
+  "Import a peer bootstrap token created from a remote cluster", "",
+  &get_peer_bootstrap_import_arguments, &execute_peer_bootstrap_import);
+
 Shell::Action action_add(
   {"mirror", "pool", "peer", "add"}, {},
   "Add a mirroring peer to a pool.", "",