#include "cls/rbd/cls_rbd_types.h"
#include "common/errno.h"
#include "common/Formatter.h"
+#include "common/TextTable.h"
namespace rbd {
namespace action {
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;
+ for (auto image : images) {
+ std::string image_name = image.name;
+ int state = image.state;
std::string state_string;
- if (cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE == state) {
+ if (GROUP_IMAGE_STATE_INCOMPLETE == state) {
state_string = "incomplete";
}
if (f) {
f->dump_string("image name", image_name);
- f->dump_int("pool id", pool_id);
+ f->dump_int("pool", image.pool);
f->dump_int("state", state);
} else
- std::cout << pool_id << "." << image_name << " " << state_string << std::endl;
+ std::cout << image.pool << "/" << image_name << " " << state_string << std::endl;
}
if (f) {
return 0;
}
+int execute_group_snap_create(const po::variables_map &vm) {
+ size_t arg_index = 0;
+
+ std::string group_name;
+ std::string pool_name;
+ std::string snap_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 (vm.count(at::SNAPSHOT_NAME)) {
+ snap_name = vm[at::SNAPSHOT_NAME].as<std::string>();
+ }
+
+ if (snap_name.empty()) {
+ snap_name = utils::get_positional_argument(vm, arg_index++);
+ }
+
+ if (snap_name.empty()) {
+ std::cerr << "rbd: "
+ << "snapshot name was not specified" << std::endl;
+ return -EINVAL;
+ }
+
+ librados::IoCtx io_ctx;
+ librados::Rados rados;
+
+ r = utils::init(pool_name, &rados, &io_ctx);
+ if (r < 0) {
+ return r;
+ }
+
+ librbd::RBD rbd;
+ r = rbd.group_snap_create(io_ctx, group_name.c_str(), snap_name.c_str());
+ if (r < 0) {
+ return r;
+ }
+
+ return 0;
+}
+
+int execute_group_snap_remove(const po::variables_map &vm) {
+ size_t arg_index = 0;
+
+ std::string group_name;
+ std::string pool_name;
+ std::string snap_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 (vm.count(at::SNAPSHOT_NAME)) {
+ snap_name = vm[at::SNAPSHOT_NAME].as<std::string>();
+ }
+
+ if (snap_name.empty()) {
+ snap_name = utils::get_positional_argument(vm, arg_index++);
+ }
+
+ if (snap_name.empty()) {
+ std::cerr << "rbd: "
+ << "snapshot name was not specified" << std::endl;
+ return -EINVAL;
+ }
+
+ librados::IoCtx io_ctx;
+ librados::Rados rados;
+
+ r = utils::init(pool_name, &rados, &io_ctx);
+ if (r < 0) {
+ return r;
+ }
+
+ librbd::RBD rbd;
+ r = rbd.group_snap_remove(io_ctx, group_name.c_str(), snap_name.c_str());
+
+ return r;
+}
+
+int execute_group_snap_list(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_snap_spec_t> snaps;
+
+ r = rbd.group_snap_list(io_ctx, group_name.c_str(), &snaps);
+
+ if (r == -ENOENT) {
+ r = 0;
+ }
+ if (r < 0) {
+ return r;
+ }
+
+ TextTable t;
+ if (f) {
+ f->open_array_section("consistency_group_snaps");
+ } else {
+ t.define_column("NAME", TextTable::LEFT, TextTable::LEFT);
+ t.define_column("STATUS", TextTable::RIGHT, TextTable::RIGHT);
+ }
+
+ for (auto i : snaps) {
+ std::string snap_name = i.name;
+ int state = i.state;
+ std::string state_string;
+ if (GROUP_SNAP_STATE_PENDING == state) {
+ state_string = "pending";
+ } else {
+ state_string = "ok";
+ }
+ if (r < 0) {
+ return r;
+ }
+ if (f) {
+ f->dump_string("snap name", snap_name);
+ f->dump_int("state", state);
+ } else {
+ t << snap_name << state_string << TextTable::endrow;
+ }
+ }
+
+ if (f) {
+ f->close_section();
+ f->flush(std::cout);
+ } else {
+ std::cout << t;
+ }
+ 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_group_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
}
+void get_group_snap_create_arguments(po::options_description *positional,
+ po::options_description *options) {
+ at::add_group_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+
+ positional->add_options()
+ (at::SNAPSHOT_NAME.c_str(), "snapshot name\n(example: <snapshot-name>)");
+
+ at::add_snap_option(options, at::ARGUMENT_MODIFIER_NONE);
+}
+
+void get_group_snap_remove_arguments(po::options_description *positional,
+ po::options_description *options) {
+ at::add_group_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
+
+ positional->add_options()
+ (at::SNAPSHOT_NAME.c_str(), "snapshot name\n(example: <snapshot-name>)");
+
+ at::add_snap_option(options, at::ARGUMENT_MODIFIER_NONE);
+}
+
+void get_group_snap_list_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_images(
{"group", "image", "list"}, {}, "List images in a consistency group.",
"", &get_list_images_arguments, &execute_list_images);
+Shell::Action action_group_snap_create(
+ {"group", "snap", "create"}, {}, "Make a snapshot of a group.",
+ "", &get_group_snap_create_arguments, &execute_group_snap_create);
+Shell::Action action_group_snap_remove(
+ {"group", "snap", "remove"}, {}, "Remove a snapshot from a group.",
+ "", &get_group_snap_remove_arguments, &execute_group_snap_remove);
+Shell::Action action_group_snap_list(
+ {"group", "snap", "list"}, {}, "List snapshots of a consistency group.",
+ "", &get_group_snap_list_arguments, &execute_group_snap_list);
} // namespace group
} // namespace action
} // namespace rbd
#include "common/TextTable.h"
#include <iostream>
#include <boost/program_options.hpp>
+#include <boost/bind.hpp>
namespace rbd {
namespace action {
namespace snap {
+static const std::string ALL_NAME("all");
+
namespace at = argument_types;
namespace po = boost::program_options;
-int do_list_snaps(librbd::Image& image, Formatter *f)
+static bool is_not_user_snap_namespace(librbd::Image* image,
+ const librbd::snap_info_t &snap_info)
+{
+ librbd::snap_namespace_type_t namespace_type;
+ int r = image->snap_get_namespace_type(snap_info.id, &namespace_type);
+ if (r < 0) {
+ return false;
+ }
+ return namespace_type != SNAP_NAMESPACE_TYPE_USER;
+}
+
+int do_list_snaps(librbd::Image& image, Formatter *f, bool all_snaps, librados::Rados& rados)
{
std::vector<librbd::snap_info_t> snaps;
TextTable t;
if (r < 0)
return r;
+ if (!all_snaps) {
+ snaps.erase(remove_if(snaps.begin(),
+ snaps.end(),
+ boost::bind(is_not_user_snap_namespace, &image, _1)),
+ snaps.end());
+ }
+
if (f) {
f->open_array_section("snapshots");
} else {
t.define_column("NAME", TextTable::LEFT, TextTable::LEFT);
t.define_column("SIZE", TextTable::RIGHT, TextTable::RIGHT);
t.define_column("TIMESTAMP", TextTable::LEFT, TextTable::LEFT);
+ if (all_snaps) {
+ t.define_column("NAMESPACE", TextTable::LEFT, TextTable::LEFT);
+ }
}
+ std::list<std::pair<int64_t, std::string>> pool_list;
+ rados.pool_list2(pool_list);
+ std::map<int64_t, std::string> pool_map(pool_list.begin(), pool_list.end());
+
for (std::vector<librbd::snap_info_t>::iterator s = snaps.begin();
s != snaps.end(); ++s) {
struct timespec timestamp;
tt_str = ctime(&tt);
tt_str = tt_str.substr(0, tt_str.length() - 1);
}
+ librbd::group_snap_t group_snap;
+ int get_group_res = image.snap_get_group(s->id, &group_snap);
if (f) {
f->open_object_section("snapshot");
f->dump_string("name", s->name);
f->dump_unsigned("size", s->size);
f->dump_string("timestamp", tt_str);
+ if (all_snaps) {
+ f->open_object_section("namespace");
+ if (get_group_res == 0) {
+ std::string pool_name = pool_map[group_snap.group_pool];
+ f->dump_string("pool", pool_name);
+ f->dump_string("group", group_snap.group_name);
+ f->dump_string("group snap", group_snap.group_snap_name);
+ }
+ f->close_section();
+ }
f->close_section();
} else {
- t << s->id << s->name << stringify(prettybyte_t(s->size)) << tt_str
- << TextTable::endrow;
+ std::string namespace_string;
+ if (all_snaps && (get_group_res == 0)) {
+ ostringstream oss;
+ std::string pool_name = pool_map[group_snap.group_pool];
+ oss << "group snapshot - " << pool_name << "/" <<
+ group_snap.group_name << "@" <<
+ group_snap.group_snap_name;
+
+ namespace_string = oss.str();
+ }
+ t << s->id << s->name << stringify(prettybyte_t(s->size)) << tt_str;
+ if (all_snaps) {
+ t << namespace_string;
+ }
+ t << TextTable::endrow;
}
}
uint32_t flags = force? RBD_SNAP_REMOVE_FORCE : 0;
int r = 0;
utils::ProgressContext pc("Removing snap", no_progress);
-
+
r = image.snap_remove2(snapname, flags, pc);
if (r < 0) {
pc.fail();
return image.snap_set_limit(UINT64_MAX);
}
+void add_all_option(po::options_description *opt, std::string description) {
+ std::string name = ALL_NAME + ",a";
+
+ opt->add_options()
+ (name.c_str(), po::bool_switch(), description.c_str());
+}
+
void get_list_arguments(po::options_description *positional,
po::options_description *options) {
at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
at::add_image_id_option(options);
at::add_format_options(options);
+ add_all_option(options, "list snapshots from all namespaces");
}
int execute_list(const po::variables_map &vm) {
if (r < 0) {
return r;
}
+ r = utils::get_pool_image_snapshot_names(
+ vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
+ &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE);
+ if (r < 0) {
+ return r;
+ }
at::Format::Formatter formatter;
r = utils::get_formatter(vm, &formatter);
return r;
}
- r = do_list_snaps(image, formatter.get());
+ bool all_snaps = vm[ALL_NAME].as<bool>();
+ r = do_list_snaps(image, formatter.get(), all_snaps, rados);
if (r < 0) {
cerr << "rbd: failed to list snapshots: " << cpp_strerror(r)
<< std::endl;