From: Victor Denisov Date: Wed, 25 May 2016 02:10:33 +0000 (-0700) Subject: rbd: Add cg create, cg list, cg remove commands X-Git-Tag: v11.0.0~148^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=8d06d8bbb70ea0516f346888a54c140570b617db;p=ceph.git rbd: Add cg create, cg list, cg remove commands Signed-off-by: Victor Denisov --- diff --git a/src/tools/Makefile-client.am b/src/tools/Makefile-client.am index 7762c8b5e27b..906ea48439fb 100644 --- a/src/tools/Makefile-client.am +++ b/src/tools/Makefile-client.am @@ -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 \ diff --git a/src/tools/rbd/ArgumentTypes.cc b/src/tools/rbd/ArgumentTypes.cc index 94355bbb63f3..c71c32b7f6a4 100644 --- a/src/tools/rbd/ArgumentTypes.cc +++ b/src/tools/rbd/ArgumentTypes.cc @@ -102,6 +102,29 @@ void add_image_option(po::options_description *opt, (name.c_str(), po::value(), 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(), 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: [/])").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) { diff --git a/src/tools/rbd/ArgumentTypes.h b/src/tools/rbd/ArgumentTypes.h index 50c74aa8ff3b..a48ef6cd659f 100644 --- a/src/tools/rbd/ArgumentTypes.h +++ b/src/tools/rbd/ArgumentTypes.h @@ -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); diff --git a/src/tools/rbd/Utils.cc b/src/tools/rbd/Utils.cc index d39819201b09..6575e4ec5e94 100644 --- a/src/tools/rbd/Utils.cc +++ b/src/tools/rbd/Utils.cc @@ -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(); + } + if (vm.count(group_key) && group_name != nullptr) { + *group_name = vm[group_key].as(); + } + + 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, diff --git a/src/tools/rbd/Utils.h b/src/tools/rbd/Utils.h index cad18d93dcd3..453e2ce8b2b6 100644 --- a/src/tools/rbd/Utils.h +++ b/src/tools/rbd/Utils.h @@ -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 index 000000000000..ce01c0efa4e3 --- /dev/null +++ b/src/tools/rbd/action/Group.cc @@ -0,0 +1,150 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include + +#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 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