]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: Add cg create, cg list, cg remove commands
authorVictor Denisov <denisovenator@gmail.com>
Wed, 25 May 2016 02:10:33 +0000 (19:10 -0700)
committerVictor Denisov <denisovenator@gmail.com>
Thu, 16 Jun 2016 06:32:52 +0000 (02:32 -0400)
Signed-off-by: Victor Denisov <denisovenator@gmail.com>
src/tools/Makefile-client.am
src/tools/rbd/ArgumentTypes.cc
src/tools/rbd/ArgumentTypes.h
src/tools/rbd/Utils.cc
src/tools/rbd/Utils.h
src/tools/rbd/action/Group.cc [new file with mode: 0644]

index 7762c8b5e27bc43587bbcf6aa8e7676226845ccf..906ea48439fbe821e05e2e1e767b9bcb3229c00a 100644 (file)
@@ -33,6 +33,7 @@ rbd_SOURCES = \
        tools/rbd/action/BenchWrite.cc \
        tools/rbd/action/Children.cc \
        tools/rbd/action/Clone.cc \
+       tools/rbd/action/Group.cc \
        tools/rbd/action/Copy.cc \
        tools/rbd/action/Create.cc \
        tools/rbd/action/Diff.cc \
index 94355bbb63f3590043595d382a7ec6ad2ca8b1fe..c71c32b7f6a4fb22e33dfbccb1565c648d7a4d2c 100644 (file)
@@ -102,6 +102,29 @@ void add_image_option(po::options_description *opt,
     (name.c_str(), po::value<std::string>(), description.c_str());
 }
 
+void add_group_option(po::options_description *opt,
+                     ArgumentModifier modifier,
+                     const std::string &desc_suffix) {
+  std::string name = GROUP_NAME;
+  std::string description = "group name";
+  switch (modifier) {
+  case ARGUMENT_MODIFIER_NONE:
+    break;
+  case ARGUMENT_MODIFIER_SOURCE:
+    description = "source " + description;
+    break;
+  case ARGUMENT_MODIFIER_DEST:
+    name = DEST_GROUP_NAME;
+    description = "destination " + description;
+    break;
+  }
+  description += desc_suffix;
+
+  // TODO add validator
+  opt->add_options()
+    (name.c_str(), po::value<std::string>(), description.c_str());
+}
+
 void add_snap_option(po::options_description *opt,
                       ArgumentModifier modifier) {
 
@@ -166,6 +189,17 @@ void add_image_spec_options(po::options_description *pos,
   add_image_option(opt, modifier);
 }
 
+void add_group_spec_options(po::options_description *pos,
+                           po::options_description *opt,
+                           ArgumentModifier modifier) {
+  pos->add_options()
+    ((get_name_prefix(modifier) + GROUP_SPEC).c_str(),
+     (get_description_prefix(modifier) + "group specification\n" +
+      "(example: [<pool-name>/]<group-name>)").c_str());
+  add_pool_option(opt, modifier);
+  add_group_option(opt, modifier);
+}
+
 void add_snap_spec_options(po::options_description *pos,
                            po::options_description *opt,
                            ArgumentModifier modifier) {
index 50c74aa8ff3bc76e8f9271500e12f047a564ddf4..a48ef6cd659f30313b00f54a4c0f1f83689958f3 100644 (file)
@@ -38,6 +38,7 @@ static const std::string DEST_PREFIX("dest-");
 static const std::string POSITIONAL_COMMAND_SPEC("positional-command-spec");
 static const std::string POSITIONAL_ARGUMENTS("positional-arguments");
 static const std::string IMAGE_SPEC("image-spec");
+static const std::string GROUP_SPEC("group-spec");
 static const std::string SNAPSHOT_SPEC("snap-spec");
 static const std::string IMAGE_OR_SNAPSHOT_SPEC("image-or-snap-spec");
 static const std::string JOURNAL_SPEC("journal-spec");
@@ -49,6 +50,8 @@ static const std::string POOL_NAME("pool");
 static const std::string DEST_POOL_NAME("dest-pool");
 static const std::string IMAGE_NAME("image");
 static const std::string DEST_IMAGE_NAME("dest");
+static const std::string GROUP_NAME("group");
+static const std::string DEST_GROUP_NAME("dest-group");
 static const std::string SNAPSHOT_NAME("snap");
 static const std::string DEST_SNAPSHOT_NAME("dest-snap");
 static const std::string JOURNAL_NAME("journal");
@@ -119,6 +122,10 @@ void add_image_option(boost::program_options::options_description *opt,
                       ArgumentModifier modifier,
                       const std::string &desc_suffix = "");
 
+void add_group_option(boost::program_options::options_description *opt,
+                     ArgumentModifier modifier,
+                     const std::string &desc_suffix = "");
+
 void add_snap_option(boost::program_options::options_description *opt,
                      ArgumentModifier modifier);
 
@@ -133,6 +140,10 @@ void add_image_spec_options(boost::program_options::options_description *pos,
                             boost::program_options::options_description *opt,
                             ArgumentModifier modifier);
 
+void add_group_spec_options(boost::program_options::options_description *pos,
+                           boost::program_options::options_description *opt,
+                           ArgumentModifier modifier);
+
 void add_snap_spec_options(boost::program_options::options_description *pos,
                            boost::program_options::options_description *opt,
                            ArgumentModifier modifier);
index d39819201b09128bc1e20f5874a14dc0c4aee7b7..6575e4ec5e9489d985263c7115ae17a820961de7 100644 (file)
@@ -124,6 +124,28 @@ int extract_spec(const std::string &spec, std::string *pool_name,
   return 0;
 }
 
+int extract_group_spec(const std::string &spec,
+                      std::string *pool_name,
+                      std::string *group_name) {
+  boost::regex pattern;
+  pattern = "^(?:([^/]+)/)?(.+)?$";
+
+  boost::smatch match;
+  if (!boost::regex_match(spec, match, pattern)) {
+    std::cerr << "rbd: invalid spec '" << spec << "'" << std::endl;
+    return -EINVAL;
+  }
+
+  if (pool_name != nullptr && match[1].matched) {
+    *pool_name = match[1];
+  }
+  if (group_name != nullptr) {
+    *group_name = match[2];
+  }
+
+  return 0;
+}
+
 std::string get_positional_argument(const po::variables_map &vm, size_t index) {
   if (vm.count(at::POSITIONAL_ARGUMENTS) == 0) {
     return "";
@@ -156,6 +178,50 @@ std::string get_pool_name(const po::variables_map &vm,
   return pool_name;
 }
 
+int get_pool_group_names(const po::variables_map &vm,
+                        at::ArgumentModifier mod,
+                        size_t *spec_arg_index,
+                        std::string *pool_name,
+                        std::string *group_name) {
+  std::string pool_key = (mod == at::ARGUMENT_MODIFIER_DEST ?
+    at::DEST_POOL_NAME : at::POOL_NAME);
+  std::string group_key = (mod == at::ARGUMENT_MODIFIER_DEST ?
+    at::DEST_GROUP_NAME : at::GROUP_NAME);
+
+  if (vm.count(pool_key) && pool_name != nullptr) {
+    *pool_name = vm[pool_key].as<std::string>();
+  }
+  if (vm.count(group_key) && group_name != nullptr) {
+    *group_name = vm[group_key].as<std::string>();
+  }
+
+  int r;
+  if (group_name != nullptr && spec_arg_index != nullptr &&
+      group_name->empty()) {
+    std::string spec = get_positional_argument(vm, (*spec_arg_index)++);
+    if (!spec.empty()) {
+      r = extract_group_spec(spec, pool_name, group_name);
+      if (r < 0) {
+        return r;
+      }
+    }
+  }
+
+  if (pool_name->empty()) {
+    *pool_name = at::DEFAULT_POOL_NAME;
+  }
+
+  if (group_name != nullptr && group_name->empty()) {
+    std::string prefix = at::get_description_prefix(mod);
+    std::cerr << "rbd: "
+              << (mod == at::ARGUMENT_MODIFIER_DEST ? prefix : std::string())
+              << "group name was not specified" << std::endl;
+    return -EINVAL;
+  }
+
+  return 0;
+}
+
 int get_pool_image_snapshot_names(const po::variables_map &vm,
                                   at::ArgumentModifier mod,
                                   size_t *spec_arg_index,
index cad18d93dcd31a387e0fec0de3e39b66fdcf9441..453e2ce8b2b6d4073ac9f1ac2450eb2f356ddc8e 100644 (file)
@@ -63,6 +63,12 @@ int get_pool_image_snapshot_names(
     SnapshotPresence snapshot_presence, SpecValidation spec_validation,
     bool image_required = true);
 
+int get_pool_group_names(const boost::program_options::variables_map &vm,
+                        argument_types::ArgumentModifier mod,
+                        size_t *spec_arg_index,
+                        std::string *pool_name,
+                        std::string *group_name);
+
 int get_pool_journal_names(
     const boost::program_options::variables_map &vm,
     argument_types::ArgumentModifier mod, size_t *spec_arg_index,
diff --git a/src/tools/rbd/action/Group.cc b/src/tools/rbd/action/Group.cc
new file mode 100644 (file)
index 0000000..ce01c0e
--- /dev/null
@@ -0,0 +1,150 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <iostream>
+
+#include "tools/rbd/ArgumentTypes.h"
+#include "tools/rbd/Shell.h"
+#include "tools/rbd/Utils.h"
+#include "common/errno.h"
+#include "common/Formatter.h"
+
+namespace rbd {
+namespace action {
+namespace consgrp {
+
+namespace at = argument_types;
+namespace po = boost::program_options;
+
+int execute_create(const po::variables_map &vm) {
+  size_t arg_index = 0;
+
+  std::string group_name;
+  std::string pool_name;
+
+  int r = utils::get_pool_group_names(vm, at::ARGUMENT_MODIFIER_NONE,
+                                      &arg_index, &pool_name, &group_name);
+  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;
+  }
+  librbd::RBD rbd;
+  r = rbd.group_create(io_ctx, group_name.c_str());
+  if (r < 0) {
+    std::cerr << "rbd: create error: " << cpp_strerror(r) << std::endl;
+    return r;
+  }
+
+  return 0;
+}
+
+int execute_list(const po::variables_map &vm) {
+
+  size_t arg_index = 0;
+  std::string pool_name = utils::get_pool_name(vm, &arg_index);
+
+  at::Format::Formatter formatter;
+  int r = utils::get_formatter(vm, &formatter);
+  if (r < 0) {
+    return r;
+  }
+  Formatter *f = formatter.get();
+
+  librados::Rados rados;
+  librados::IoCtx io_ctx;
+  r = utils::init(pool_name, &rados, &io_ctx);
+  if (r < 0) {
+    return r;
+  }
+
+  librbd::RBD rbd;
+  std::vector<std::string> names;
+  r = rbd.group_list(io_ctx, names);
+
+  if (r == -ENOENT)
+    r = 0;
+  if (r < 0)
+    return r;
+
+  if (f)
+    f->open_array_section("consistency_groups");
+  for (auto i : names) {
+    if (f)
+      f->dump_string("name", i);
+    else
+      std::cout << i << std::endl;
+  }
+  if (f) {
+    f->close_section();
+    f->flush(std::cout);
+  }
+
+  return 0;
+}
+
+int execute_remove(const po::variables_map &vm) {
+  size_t arg_index = 0;
+
+  std::string group_name;
+  std::string pool_name;
+
+  int r = utils::get_pool_group_names(vm, at::ARGUMENT_MODIFIER_NONE,
+                                      &arg_index, &pool_name, &group_name);
+  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;
+  }
+  librbd::RBD rbd;
+
+  r = rbd.group_remove(io_ctx, group_name.c_str());
+  if (r < 0) {
+    std::cerr << "rbd: remove error: " << cpp_strerror(r) << std::endl;
+    return r;
+  }
+
+  return 0;
+}
+
+void get_create_arguments(po::options_description *positional,
+                          po::options_description *options) {
+  at::add_group_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+}
+
+void get_remove_arguments(po::options_description *positional,
+                          po::options_description *options) {
+  at::add_group_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+}
+
+void get_list_arguments(po::options_description *positional,
+                        po::options_description *options) {
+  add_pool_option(options, at::ARGUMENT_MODIFIER_NONE);
+  at::add_format_options(options);
+}
+
+Shell::Action action_create(
+  {"group", "create"}, {}, "Create a consistency group.",
+  "", &get_create_arguments, &execute_create);
+Shell::Action action_remove(
+  {"group", "remove"}, {"group", "rm"}, "Delete a consistency group.",
+  "", &get_remove_arguments, &execute_remove);
+Shell::Action action_list(
+  {"group", "list"}, {"group", "ls"}, "List rbd consistency groups.",
+  "", &get_list_arguments, &execute_list);
+
+} // namespace snap
+} // namespace action
+} // namespace rbd