1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 SUSE LINUX GmbH
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
14 #include "tools/rbd/ArgumentTypes.h"
15 #include "tools/rbd/Shell.h"
16 #include "tools/rbd/Utils.h"
17 #include "include/stringify.h"
18 #include "common/config.h"
19 #include "common/errno.h"
20 #include "common/Formatter.h"
21 #include "common/TextTable.h"
22 #include "global/global_context.h"
24 #include <boost/program_options.hpp>
25 #include <boost/regex.hpp>
29 namespace mirror_image {
31 namespace at = argument_types;
32 namespace po = boost::program_options;
36 int validate_mirroring_enabled(librbd::Image& image) {
37 librbd::mirror_image_info_t mirror_image;
38 int r = image.mirror_image_get_info(&mirror_image, sizeof(mirror_image));
40 std::cerr << "rbd: failed to retrieve mirror mode: "
41 << cpp_strerror(r) << std::endl;
45 if (mirror_image.state != RBD_MIRROR_IMAGE_ENABLED) {
46 std::cerr << "rbd: mirroring not enabled on the image" << std::endl;
52 } // anonymous namespace
54 void get_arguments(po::options_description *positional,
55 po::options_description *options) {
56 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
59 void get_arguments_disable(po::options_description *positional,
60 po::options_description *options) {
61 options->add_options()
62 ("force", po::bool_switch(), "disable even if not primary");
63 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
66 int execute_enable_disable(const po::variables_map &vm, bool enable,
69 std::string pool_name;
70 std::string image_name;
71 std::string snap_name;
72 int r = utils::get_pool_image_snapshot_names(
73 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
74 &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE);
79 librados::Rados rados;
80 librados::IoCtx io_ctx;
82 r = utils::init_and_open_image(pool_name, image_name, "", "", false,
83 &rados, &io_ctx, &image);
88 r = enable ? image.mirror_image_enable() : image.mirror_image_disable(force);
93 std::cout << (enable ? "Mirroring enabled" : "Mirroring disabled")
99 int execute_disable(const po::variables_map &vm) {
100 return execute_enable_disable(vm, false, vm["force"].as<bool>());
103 int execute_enable(const po::variables_map &vm) {
104 return execute_enable_disable(vm, true, false);
107 void get_arguments_promote(po::options_description *positional,
108 po::options_description *options) {
109 options->add_options()
110 ("force", po::bool_switch(), "promote even if not cleanly demoted by remote cluster");
111 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
114 int execute_promote(const po::variables_map &vm) {
115 size_t arg_index = 0;
116 std::string pool_name;
117 std::string image_name;
118 std::string snap_name;
119 int r = utils::get_pool_image_snapshot_names(
120 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
121 &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE);
126 bool force = vm["force"].as<bool>();
128 librados::Rados rados;
129 librados::IoCtx io_ctx;
131 r = utils::init_and_open_image(pool_name, image_name, "", "", false,
132 &rados, &io_ctx, &image);
137 r = validate_mirroring_enabled(image);
142 r = image.mirror_image_promote(force);
144 std::cerr << "rbd: error promoting image to primary" << std::endl;
148 std::cout << "Image promoted to primary" << std::endl;
152 int execute_demote(const po::variables_map &vm) {
153 size_t arg_index = 0;
154 std::string pool_name;
155 std::string image_name;
156 std::string snap_name;
157 int r = utils::get_pool_image_snapshot_names(
158 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
159 &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE);
164 librados::Rados rados;
165 librados::IoCtx io_ctx;
167 r = utils::init_and_open_image(pool_name, image_name, "", "", false,
168 &rados, &io_ctx, &image);
173 r = validate_mirroring_enabled(image);
178 r = image.mirror_image_demote();
180 std::cerr << "rbd: error demoting image to non-primary" << std::endl;
184 std::cout << "Image demoted to non-primary" << std::endl;
188 int execute_resync(const po::variables_map &vm) {
189 size_t arg_index = 0;
190 std::string pool_name;
191 std::string image_name;
192 std::string snap_name;
193 int r = utils::get_pool_image_snapshot_names(
194 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
195 &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE);
200 librados::Rados rados;
201 librados::IoCtx io_ctx;
203 r = utils::init_and_open_image(pool_name, image_name, "", "", false,
204 &rados, &io_ctx, &image);
209 r = validate_mirroring_enabled(image);
214 r = image.mirror_image_resync();
216 std::cerr << "rbd: error flagging image resync" << std::endl;
220 std::cout << "Flagged image for resync from primary" << std::endl;
224 void get_status_arguments(po::options_description *positional,
225 po::options_description *options) {
226 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
227 at::add_format_options(options);
230 int execute_status(const po::variables_map &vm) {
231 at::Format::Formatter formatter;
232 int r = utils::get_formatter(vm, &formatter);
237 size_t arg_index = 0;
238 std::string pool_name;
239 std::string image_name;
240 std::string snap_name;
241 r = utils::get_pool_image_snapshot_names(
242 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
243 &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE);
248 librados::Rados rados;
249 librados::IoCtx io_ctx;
251 r = utils::init_and_open_image(pool_name, image_name, "", "", false,
252 &rados, &io_ctx, &image);
257 r = validate_mirroring_enabled(image);
262 librbd::mirror_image_status_t status;
263 r = image.mirror_image_get_status(&status, sizeof(status));
265 std::cerr << "rbd: failed to get status for image " << image_name << ": "
266 << cpp_strerror(r) << std::endl;
270 std::string state = utils::mirror_image_status_state(status);
271 std::string last_update = (
272 status.last_update == 0 ? "" : utils::timestr(status.last_update));
274 if (formatter != nullptr) {
275 formatter->open_object_section("image");
276 formatter->dump_string("name", image_name);
277 formatter->dump_string("global_id", status.info.global_id);
278 formatter->dump_string("state", state);
279 formatter->dump_string("description", status.description);
280 formatter->dump_string("last_update", last_update);
281 formatter->close_section(); // image
282 formatter->flush(std::cout);
284 std::cout << image_name << ":\n"
285 << " global_id: " << status.info.global_id << "\n"
286 << " state: " << state << "\n"
287 << " description: " << status.description << "\n"
288 << " last_update: " << last_update << std::endl;
294 Shell::Action action_enable(
295 {"mirror", "image", "enable"}, {},
296 "Enable RBD mirroring for an image.", "",
297 &get_arguments, &execute_enable);
298 Shell::Action action_disable(
299 {"mirror", "image", "disable"}, {},
300 "Disable RBD mirroring for an image.", "",
301 &get_arguments_disable, &execute_disable);
302 Shell::Action action_promote(
303 {"mirror", "image", "promote"}, {},
304 "Promote an image to primary for RBD mirroring.", "",
305 &get_arguments_promote, &execute_promote);
306 Shell::Action action_demote(
307 {"mirror", "image", "demote"}, {},
308 "Demote an image to non-primary for RBD mirroring.", "",
309 &get_arguments, &execute_demote);
310 Shell::Action action_resync(
311 {"mirror", "image", "resync"}, {},
312 "Force resync to primary image for RBD mirroring.", "",
313 &get_arguments, &execute_resync);
314 Shell::Action action_status(
315 {"mirror", "image", "status"}, {},
316 "Show RDB mirroring status for an image.", "",
317 &get_status_arguments, &execute_status);
319 } // namespace mirror_image
320 } // namespace action