Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / tools / rbd / action / MirrorImage.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2016 SUSE LINUX GmbH
7  *
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.
12  *
13  */
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"
23 #include <iostream>
24 #include <boost/program_options.hpp>
25 #include <boost/regex.hpp>
26
27 namespace rbd {
28 namespace action {
29 namespace mirror_image {
30
31 namespace at = argument_types;
32 namespace po = boost::program_options;
33
34 namespace {
35
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));
39   if (r < 0) {
40     std::cerr << "rbd: failed to retrieve mirror mode: "
41               << cpp_strerror(r) << std::endl;
42     return r;
43   }
44
45   if (mirror_image.state != RBD_MIRROR_IMAGE_ENABLED) {
46     std::cerr << "rbd: mirroring not enabled on the image" << std::endl;
47     return -EINVAL;
48   }
49   return 0;
50 }
51
52 } // anonymous namespace
53
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);
57 }
58
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);
64 }
65
66 int execute_enable_disable(const po::variables_map &vm, bool enable,
67                            bool force) {
68   size_t arg_index = 0;
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);
75   if (r < 0) {
76     return r;
77   }
78
79   librados::Rados rados;
80   librados::IoCtx io_ctx;
81   librbd::Image image;
82   r = utils::init_and_open_image(pool_name, image_name, "", "", false,
83                                  &rados, &io_ctx, &image);
84   if (r < 0) {
85     return r;
86   }
87
88   r = enable ? image.mirror_image_enable() : image.mirror_image_disable(force);
89   if (r < 0) {
90     return r;
91   }
92
93   std::cout << (enable ? "Mirroring enabled" : "Mirroring disabled")
94     << std::endl;
95
96   return 0;
97 }
98
99 int execute_disable(const po::variables_map &vm) {
100   return execute_enable_disable(vm, false, vm["force"].as<bool>());
101 }
102
103 int execute_enable(const po::variables_map &vm) {
104   return execute_enable_disable(vm, true, false);
105 }
106
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);
112 }
113
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);
122   if (r < 0) {
123     return r;
124   }
125
126   bool force = vm["force"].as<bool>();
127
128   librados::Rados rados;
129   librados::IoCtx io_ctx;
130   librbd::Image image;
131   r = utils::init_and_open_image(pool_name, image_name, "", "", false,
132                                  &rados, &io_ctx, &image);
133   if (r < 0) {
134     return r;
135   }
136
137   r = validate_mirroring_enabled(image);
138   if (r < 0) {
139     return r;
140   }
141
142   r = image.mirror_image_promote(force);
143   if (r < 0) {
144     std::cerr << "rbd: error promoting image to primary" << std::endl;
145     return r;
146   }
147
148   std::cout << "Image promoted to primary" << std::endl;
149   return 0;
150 }
151
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);
160   if (r < 0) {
161     return r;
162   }
163
164   librados::Rados rados;
165   librados::IoCtx io_ctx;
166   librbd::Image image;
167   r = utils::init_and_open_image(pool_name, image_name, "", "", false,
168                                  &rados, &io_ctx, &image);
169   if (r < 0) {
170     return r;
171   }
172
173   r = validate_mirroring_enabled(image);
174   if (r < 0) {
175     return r;
176   }
177
178   r = image.mirror_image_demote();
179   if (r < 0) {
180     std::cerr << "rbd: error demoting image to non-primary" << std::endl;
181     return r;
182   }
183
184   std::cout << "Image demoted to non-primary" << std::endl;
185   return 0;
186 }
187
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);
196   if (r < 0) {
197     return r;
198   }
199
200   librados::Rados rados;
201   librados::IoCtx io_ctx;
202   librbd::Image image;
203   r = utils::init_and_open_image(pool_name, image_name, "", "", false,
204                                  &rados, &io_ctx, &image);
205   if (r < 0) {
206     return r;
207   }
208
209   r = validate_mirroring_enabled(image);
210   if (r < 0) {
211     return r;
212   }
213
214   r = image.mirror_image_resync();
215   if (r < 0) {
216     std::cerr << "rbd: error flagging image resync" << std::endl;
217     return r;
218   }
219
220   std::cout << "Flagged image for resync from primary" << std::endl;
221   return 0;
222 }
223
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);
228 }
229
230 int execute_status(const po::variables_map &vm) {
231   at::Format::Formatter formatter;
232   int r = utils::get_formatter(vm, &formatter);
233   if (r < 0) {
234     return r;
235   }
236
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);
244   if (r < 0) {
245     return r;
246   }
247
248   librados::Rados rados;
249   librados::IoCtx io_ctx;
250   librbd::Image image;
251   r = utils::init_and_open_image(pool_name, image_name, "", "", false,
252                                  &rados, &io_ctx, &image);
253   if (r < 0) {
254     return r;
255   }
256
257   r = validate_mirroring_enabled(image);
258   if (r < 0) {
259     return r;
260   }
261
262   librbd::mirror_image_status_t status;
263   r = image.mirror_image_get_status(&status, sizeof(status));
264   if (r < 0) {
265     std::cerr << "rbd: failed to get status for image " << image_name << ": "
266               << cpp_strerror(r) << std::endl;
267     return r;
268   }
269
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));
273
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);
283   } else {
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;
289   }
290
291   return 0;
292 }
293
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);
318
319 } // namespace mirror_image
320 } // namespace action
321 } // namespace rbd