flatten Fill clone with parent data (make it
independent).
group create Create a consistency group.
+ group image add Add an image to a consistency group.
+ group image list List images in a consistency group.
+ group image remove Remove an image from a consistency group.
group list (group ls) List rbd consistency groups.
group remove (group rm) Delete a consistency group.
image-meta get Image metadata get the value associated with
-p [ --pool ] arg pool name
--group arg group name
+ rbd help group image add
+ usage: rbd group image add [--group-pool <group-pool>] [--group <group>]
+ [--image-pool <image-pool>] [--image <image>]
+ [--pool <pool>]
+ <group-spec> <image-spec>
+
+ Add an image to a consistency group.
+
+ Positional arguments
+ <group-spec> group specification
+ (example: [<pool-name>/]<group-name>)
+ <image-spec> image specification
+ (example: [<pool-name>/]<image-name>)
+
+ Optional arguments
+ --group-pool arg group pool name
+ --group arg group name
+ --image-pool arg image pool name
+ --image arg image name
+ -p [ --pool ] arg pool name unless overridden
+
+ rbd help group image list
+ usage: rbd group image list [--format <format>] [--pretty-format]
+ [--pool <pool>] [--group <group>]
+ <group-spec>
+
+ List images in a consistency group.
+
+ Positional arguments
+ <group-spec> group specification
+ (example: [<pool-name>/]<group-name>)
+
+ Optional arguments
+ --format arg output format [plain, json, or xml]
+ --pretty-format pretty formatting (json and xml)
+ -p [ --pool ] arg pool name
+ --group arg group name
+
+ rbd help group image remove
+ usage: rbd group image remove [--group-pool <group-pool>] [--group <group>]
+ [--image-pool <image-pool>] [--image <image>]
+ [--pool <pool>]
+ <group-spec> <image-spec>
+
+ Remove an image from a consistency group.
+
+ Positional arguments
+ <group-spec> group specification
+ (example: [<pool-name>/]<group-name>)
+ <image-spec> image specification
+ (example: [<pool-name>/]<image-name>)
+
+ Optional arguments
+ --group-pool arg group pool name
+ --group arg group name
+ --image-pool arg image pool name
+ --image arg image name
+ -p [ --pool ] arg pool name unless overridden
+
rbd help group list
usage: rbd group list [--pool <pool>] [--format <format>] [--pretty-format]
}
}
+void add_special_pool_option(po::options_description *opt,
+ std::string prefix) {
+ std::string name = prefix + "-" + POOL_NAME;
+ std::string description = prefix + " pool name";
+
+ opt->add_options()
+ (name.c_str(), po::value<std::string>(), description.c_str());
+}
+
void add_pool_option(po::options_description *opt,
ArgumentModifier modifier,
const std::string &desc_suffix) {
std::string get_description_prefix(ArgumentModifier modifier);
+void add_special_pool_option(boost::program_options::options_description *opt,
+ std::string prefix);
+
void add_pool_option(boost::program_options::options_description *opt,
ArgumentModifier modifier,
const std::string &desc_suffix = "");
return pool_name;
}
+int get_special_pool_group_names(const po::variables_map &vm,
+ size_t *arg_index,
+ std::string *group_pool_name,
+ std::string *group_name) {
+ if (nullptr == group_pool_name) return -EINVAL;
+ if (nullptr == group_name) return -EINVAL;
+ std::string pool_key = at::POOL_NAME;
+
+ std::string group_pool_key = "group-" + at::POOL_NAME;
+ std::string group_key = at::GROUP_NAME;
+
+ if (vm.count(group_pool_key)) {
+ *group_pool_name = vm[group_pool_key].as<std::string>();
+ }
+
+ if (vm.count(group_key)) {
+ *group_name = vm[group_key].as<std::string>();
+ }
+
+ int r;
+ if (group_name->empty()) {
+ std::string spec = utils::get_positional_argument(vm, (*arg_index)++);
+ if (!spec.empty()) {
+ r = utils::extract_group_spec(spec, group_pool_name, group_name);
+ if (r < 0) {
+ return r;
+ }
+ }
+ }
+
+ if (group_pool_name->empty()) {
+ *group_pool_name = vm[pool_key].as<std::string>();
+ }
+
+ if (group_pool_name->empty()) {
+ *group_pool_name = at::DEFAULT_POOL_NAME;
+ }
+
+ if (group_name->empty()) {
+ std::cerr << "rbd: consistency group name was not specified" << std::endl;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int get_special_pool_image_names(const po::variables_map &vm,
+ size_t *arg_index,
+ std::string *image_pool_name,
+ std::string *image_name) {
+ if (nullptr == image_pool_name) return -EINVAL;
+ if (nullptr == image_name) return -EINVAL;
+
+ std::string pool_key = at::POOL_NAME;
+
+ std::string image_pool_key = "image-" + at::POOL_NAME;
+ std::string image_key = at::IMAGE_NAME;
+
+ if (vm.count(image_pool_key)) {
+ *image_pool_name = vm[image_pool_key].as<std::string>();
+ }
+
+ if (vm.count(image_key)) {
+ *image_name = vm[image_key].as<std::string>();
+ }
+
+ int r;
+ if (image_name->empty()) {
+ std::string spec = utils::get_positional_argument(vm, (*arg_index)++);
+ if (!spec.empty()) {
+ r = utils::extract_spec(spec, image_pool_name,
+ image_name, nullptr,
+ utils::SPEC_VALIDATION_NONE);
+ if (r < 0) {
+ return r;
+ }
+ }
+ }
+
+ if (image_pool_name->empty()) {
+ *image_pool_name = vm[pool_key].as<std::string>();
+ }
+
+ if (image_pool_name->empty()) {
+ *image_pool_name = at::DEFAULT_POOL_NAME;
+ }
+
+ if (image_name->empty()) {
+ std::cerr << "rbd: image name was not specified" << std::endl;
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
int get_pool_group_names(const po::variables_map &vm,
at::ArgumentModifier mod,
size_t *spec_arg_index,
std::string *image_name, std::string *snap_name,
SpecValidation spec_validation);
+int extract_group_spec(const std::string &spec,
+ std::string *pool_name,
+ std::string *group_name);
+
std::string get_positional_argument(
const boost::program_options::variables_map &vm, size_t index);
SnapshotPresence snapshot_presence, SpecValidation spec_validation,
bool image_required = true);
+int get_special_pool_group_names(const boost::program_options::variables_map &vm,
+ size_t *arg_index,
+ std::string *group_pool_name,
+ std::string *group_name);
+
+int get_special_pool_image_names(const boost::program_options::variables_map &vm,
+ size_t *arg_index,
+ std::string *image_pool_name,
+ std::string *image_name);
+
int get_pool_group_names(const boost::program_options::variables_map &vm,
argument_types::ArgumentModifier mod,
size_t *spec_arg_index,
#include "tools/rbd/ArgumentTypes.h"
#include "tools/rbd/Shell.h"
#include "tools/rbd/Utils.h"
+#include "include/rbd_types.h"
+#include "cls/rbd/cls_rbd_types.h"
#include "common/errno.h"
#include "common/Formatter.h"
return 0;
}
+int execute_add(const po::variables_map &vm) {
+ size_t arg_index = 0;
+ // Parse group data.
+ std::string group_name;
+ std::string group_pool_name;
+
+ int r = utils::get_special_pool_group_names(vm, &arg_index,
+ &group_pool_name,
+ &group_name);
+ if (r < 0) {
+ std::cerr << "rbd: image add error: " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+
+ std::string image_name;
+ std::string image_pool_name;
+
+ r = utils::get_special_pool_image_names(vm, &arg_index,
+ &image_pool_name,
+ &image_name);
+
+ if (r < 0) {
+ std::cerr << "rbd: image add error: " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+
+ librados::Rados rados;
+
+ librados::IoCtx cg_io_ctx;
+ r = utils::init(group_pool_name, &rados, &cg_io_ctx);
+ if (r < 0) {
+ return r;
+ }
+
+ librados::IoCtx image_io_ctx;
+ r = utils::init(image_pool_name, &rados, &image_io_ctx);
+ if (r < 0) {
+ return r;
+ }
+
+ librbd::RBD rbd;
+ r = rbd.group_image_add(cg_io_ctx, group_name.c_str(),
+ image_io_ctx, image_name.c_str());
+ if (r < 0) {
+ std::cerr << "rbd: add image error: " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+
+ return 0;
+}
+
+int execute_remove_image(const po::variables_map &vm) {
+ size_t arg_index = 0;
+
+ std::string group_name;
+ std::string group_pool_name;
+
+ int r = utils::get_special_pool_group_names(vm, &arg_index,
+ &group_pool_name,
+ &group_name);
+ if (r < 0) {
+ std::cerr << "rbd: image remove error: " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+
+ std::string image_name;
+ std::string image_pool_name;
+
+ r = utils::get_special_pool_image_names(vm, &arg_index,
+ &image_pool_name,
+ &image_name);
+
+ if (r < 0) {
+ std::cerr << "rbd: image remove error: " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+
+ librados::Rados rados;
+
+ librados::IoCtx cg_io_ctx;
+ r = utils::init(group_pool_name, &rados, &cg_io_ctx);
+ if (r < 0) {
+ return r;
+ }
+
+ librados::IoCtx image_io_ctx;
+ r = utils::init(image_pool_name, &rados, &image_io_ctx);
+ if (r < 0) {
+ return r;
+ }
+
+ librbd::RBD rbd;
+ r = rbd.group_image_remove(cg_io_ctx, group_name.c_str(),
+ image_io_ctx, image_name.c_str());
+ if (r < 0) {
+ std::cerr << "rbd: remove image error: " << cpp_strerror(r) << std::endl;
+ return r;
+ }
+
+ return 0;
+}
+
+int execute_list_images(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;
+ }
+
+ if (group_name.empty()) {
+ std::cerr << "rbd: "
+ << "consistency group name was not specified" << std::endl;
+ return -EINVAL;
+ }
+
+ at::Format::Formatter formatter;
+ 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<librbd::group_image_status_t> images;
+
+ r = rbd.group_image_list(io_ctx, group_name.c_str(), images);
+
+ if (r == -ENOENT)
+ r = 0;
+ if (r < 0)
+ return r;
+
+ if (f)
+ f->open_array_section("consistency_groups");
+ for (auto i : images) {
+ std::string image_name = i.name;
+ int64_t pool_id = i.pool;
+ int state = i.state;
+ std::string state_string;
+ if (cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE == state) {
+ state_string = "incomplete";
+ }
+ if (r < 0)
+ return r;
+ if (f) {
+ f->dump_string("image name", image_name);
+ f->dump_int("pool id", pool_id);
+ f->dump_int("state", state);
+ } else
+ std::cout << pool_id << "." << image_name << " " << state_string << std::endl;
+ }
+ if (f) {
+ f->close_section();
+ f->flush(std::cout);
+ }
+
+ 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);
at::add_format_options(options);
}
+void get_add_arguments(po::options_description *positional,
+ po::options_description *options) {
+ positional->add_options()
+ (at::GROUP_SPEC.c_str(),
+ "group specification\n"
+ "(example: [<pool-name>/]<group-name>)");
+
+ at::add_special_pool_option(options, "group");
+ at::add_group_option(options, at::ARGUMENT_MODIFIER_NONE);
+
+ positional->add_options()
+ (at::IMAGE_SPEC.c_str(),
+ "image specification\n"
+ "(example: [<pool-name>/]<image-name>)");
+
+ at::add_special_pool_option(options, "image");
+ at::add_image_option(options, at::ARGUMENT_MODIFIER_NONE);
+
+ at::add_pool_option(options, at::ARGUMENT_MODIFIER_NONE,
+ " unless overridden");
+}
+
+void get_remove_image_arguments(po::options_description *positional,
+ po::options_description *options) {
+ positional->add_options()
+ (at::GROUP_SPEC.c_str(),
+ "group specification\n"
+ "(example: [<pool-name>/]<group-name>)");
+
+ at::add_special_pool_option(options, "group");
+ at::add_group_option(options, at::ARGUMENT_MODIFIER_NONE);
+
+ positional->add_options()
+ (at::IMAGE_SPEC.c_str(),
+ "image specification\n"
+ "(example: [<pool-name>/]<image-name>)");
+
+ at::add_special_pool_option(options, "image");
+ at::add_image_option(options, at::ARGUMENT_MODIFIER_NONE);
+
+ at::add_pool_option(options, at::ARGUMENT_MODIFIER_NONE,
+ " unless overridden");
+}
+
+void get_list_images_arguments(po::options_description *positional,
+ po::options_description *options) {
+ at::add_format_options(options);
+ at::add_group_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+}
+
Shell::Action action_create(
{"group", "create"}, {}, "Create a consistency group.",
"", &get_create_arguments, &execute_create);
Shell::Action action_list(
{"group", "list"}, {"group", "ls"}, "List rbd consistency groups.",
"", &get_list_arguments, &execute_list);
-
+Shell::Action action_add(
+ {"group", "image", "add"}, {}, "Add an image to a consistency group.",
+ "", &get_add_arguments, &execute_add);
+Shell::Action action_remove_image(
+ {"group", "image", "remove"}, {}, "Remove an image from a consistency group.",
+ "", &get_remove_image_arguments, &execute_remove_image);
+Shell::Action action_list_images(
+ {"group", "image", "list"}, {}, "List images in a consistency group.",
+ "", &get_list_images_arguments, &execute_list_images);
} // namespace snap
} // namespace action
} // namespace rbd
#include "tools/rbd/Shell.h"
#include "tools/rbd/Utils.h"
#include "include/types.h"
+#include "include/stringify.h"
#include "common/errno.h"
#include "common/Formatter.h"
#include <iostream>
strncpy(prefix, info.block_name_prefix, RBD_MAX_BLOCK_NAME_SIZE);
prefix[RBD_MAX_BLOCK_NAME_SIZE] = '\0';
+ librbd::group_spec_t group_spec;
+ r = image.get_group(&group_spec);
+ if (r < 0) {
+ return r;
+ }
+
+ std::string group_string = "";
+ if (-1 != group_spec.pool)
+ group_string = stringify(group_spec.pool) + "." + group_spec.name;
+
if (f) {
f->open_object_section("image");
f->dump_string("name", imgname);
<< "\tblock_name_prefix: " << prefix
<< std::endl
<< "\tformat: " << (old_format ? "1" : "2")
- << std::endl;
+ << std::endl;
}
if (!old_format) {
format_flags(f, flags);
}
+ if (!group_string.empty()) {
+ if (f) {
+ f->dump_string("group", group_string);
+ } else {
+ std::cout << "\tconsistency group: " << group_string
+ << std::endl;
+ }
+ }
+
// snapshot info, if present
if (snapname) {
if (f) {
<< "it crashed. Try again after closing/unmapping it or "
<< "waiting 30s for the crashed client to timeout."
<< std::endl;
+ } else if (r == -EMLINK) {
+ librbd::Image image;
+ int image_r = utils::open_image(io_ctx, image_name, true, &image);
+ librbd::group_spec_t group_spec;
+ if (image_r == 0) {
+ image_r = image.get_group(&group_spec);
+ }
+ if (image_r == 0)
+ std::cerr << "rbd: error: image belongs to a consistency group "
+ << group_spec.pool << "." << group_spec.name;
+ else
+ std::cerr << "rbd: error: image belongs to a consistency group";
+
+ std::cerr << std::endl
+ << "Remove the image from the consistency group and try again."
+ << std::endl;
+ image.close();
} else {
std::cerr << "rbd: delete error: " << cpp_strerror(r) << std::endl;
}