]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd/action/Status.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / tools / rbd / action / Status.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
f67539c2
TL
4#include "common/ceph_json.h"
5#include "common/errno.h"
6#include "common/Formatter.h"
7c673cae
FG
7#include "tools/rbd/ArgumentTypes.h"
8#include "tools/rbd/Shell.h"
9#include "tools/rbd/Utils.h"
10#include "include/rbd_types.h"
11fdf7f2 11#include "include/stringify.h"
7c673cae
FG
12#include <iostream>
13#include <boost/program_options.hpp>
14
15namespace rbd {
16namespace action {
17namespace status {
18
19namespace at = argument_types;
20namespace po = boost::program_options;
21
f67539c2
TL
22namespace {
23
24const std::string IMAGE_CACHE_STATE = ".librbd/image_cache_state";
25
26struct ImageCacheState {
27 bool present = false;
28 bool clean = false;
29 int size = 0;
30 std::string host;
31 std::string path;
32};
33
34bool image_cache_parse(const std::string& s, ImageCacheState &cache_state) {
35 JSONParser p;
36 JSONFormattable f;
37 bool success = p.parse(s.c_str(), s.size());
38 if (success) {
39 decode_json_obj(f, &p);
40 if ((success = f.exists("present"))) {
41 cache_state.present = (bool)f["present"];
42 }
43 if (success && (success = f.exists("clean"))) {
44 cache_state.present = (bool)f["clean"];
45 }
46 if (success && (success = f.exists("pwl_size"))) {
47 cache_state.size = (int)f["pwl_size"];
48 }
49 if (success && (success = f.exists("pwl_host"))) {
50 cache_state.host = (std::string)f["pwl_host"];
51 }
52 if (success && (success = f.exists("pwl_path"))) {
53 cache_state.path = (std::string)f["pwl_path"];
54 }
55 }
56 return success;
57}
58
59} // anonymous namespace
60
11fdf7f2
TL
61static int do_show_status(librados::IoCtx& io_ctx, const std::string &image_name,
62 librbd::Image &image, Formatter *f)
7c673cae 63{
7c673cae 64 int r;
11fdf7f2 65 std::list<librbd::image_watcher_t> watchers;
7c673cae 66
11fdf7f2 67 r = image.list_watchers(watchers);
7c673cae
FG
68 if (r < 0)
69 return r;
70
11fdf7f2
TL
71 uint64_t features;
72 r = image.features(&features);
73 if (r < 0) {
74 return r;
75 }
76
77 librbd::image_migration_status_t migration_status;
f67539c2 78 std::string source_spec;
11fdf7f2
TL
79 std::string source_pool_name;
80 std::string dest_pool_name;
81 std::string migration_state;
82 if ((features & RBD_FEATURE_MIGRATING) != 0) {
83 r = librbd::RBD().migration_status(io_ctx, image_name.c_str(),
84 &migration_status,
85 sizeof(migration_status));
7c673cae 86 if (r < 0) {
11fdf7f2
TL
87 std::cerr << "rbd: getting migration status failed: " << cpp_strerror(r)
88 << std::endl;
89 // not fatal
90 } else {
f67539c2
TL
91 if (migration_status.source_pool_id >= 0) {
92 librados::IoCtx src_io_ctx;
93 r = librados::Rados(io_ctx).ioctx_create2(migration_status.source_pool_id, src_io_ctx);
94 if (r < 0) {
95 source_pool_name = stringify(migration_status.source_pool_id);
96 } else {
97 source_pool_name = src_io_ctx.get_pool_name();
98 }
11fdf7f2 99 } else {
f67539c2
TL
100 r = image.get_migration_source_spec(&source_spec);
101 if (r < 0) {
102 std::cerr << "rbd: getting migration source spec failed: "
103 << cpp_strerror(r) << std::endl;
104 }
11fdf7f2 105 }
7c673cae 106
11fdf7f2
TL
107 librados::IoCtx dst_io_ctx;
108 r = librados::Rados(io_ctx).ioctx_create2(migration_status.dest_pool_id, dst_io_ctx);
109 if (r < 0) {
110 dest_pool_name = stringify(migration_status.dest_pool_id);
111 } else {
112 dest_pool_name = dst_io_ctx.get_pool_name();
113 }
7c673cae 114
11fdf7f2
TL
115 switch (migration_status.state) {
116 case RBD_IMAGE_MIGRATION_STATE_ERROR:
117 migration_state = "error";
118 break;
119 case RBD_IMAGE_MIGRATION_STATE_PREPARING:
120 migration_state = "preparing";
121 break;
122 case RBD_IMAGE_MIGRATION_STATE_PREPARED:
123 migration_state = "prepared";
124 break;
125 case RBD_IMAGE_MIGRATION_STATE_EXECUTING:
126 migration_state = "executing";
127 break;
128 case RBD_IMAGE_MIGRATION_STATE_EXECUTED:
129 migration_state = "executed";
130 break;
f91f0fd5
TL
131 case RBD_IMAGE_MIGRATION_STATE_ABORTING:
132 migration_state = "aborting";
133 break;
11fdf7f2
TL
134 default:
135 migration_state = "unknown";
136 }
137 }
138 }
7c673cae 139
f67539c2
TL
140 ImageCacheState cache_state;
141 if (features & RBD_FEATURE_DIRTY_CACHE) {
142 std::string image_cache_str;
143 r = image.metadata_get(IMAGE_CACHE_STATE, &image_cache_str);
144 if (r < 0) {
145 std::cerr << "rbd: getting image cache status failed: " << cpp_strerror(r)
146 << std::endl;
147 } else {
148 r = image_cache_parse(image_cache_str, cache_state);
149 if (r < 0) {
150 std::cerr << "rbd: image cache metadata is corrupted: " << cpp_strerror(r)
151 << std::endl;
152 }
153 }
154 }
155
7c673cae
FG
156 if (f)
157 f->open_object_section("status");
158
159 if (f) {
160 f->open_array_section("watchers");
11fdf7f2 161 for (auto &watcher : watchers) {
7c673cae 162 f->open_object_section("watcher");
11fdf7f2
TL
163 f->dump_string("address", watcher.addr);
164 f->dump_unsigned("client", watcher.id);
165 f->dump_unsigned("cookie", watcher.cookie);
7c673cae
FG
166 f->close_section();
167 }
11fdf7f2
TL
168 f->close_section(); // watchers
169 if (!migration_state.empty()) {
170 f->open_object_section("migration");
f67539c2
TL
171 if (!source_spec.empty()) {
172 f->dump_string("source_spec", source_spec);
173 } else {
174 f->dump_string("source_pool_name", source_pool_name);
175 f->dump_string("source_pool_namespace",
176 migration_status.source_pool_namespace);
177 f->dump_string("source_image_name", migration_status.source_image_name);
178 f->dump_string("source_image_id", migration_status.source_image_id);
179 }
11fdf7f2
TL
180 f->dump_string("dest_pool_name", dest_pool_name);
181 f->dump_string("dest_pool_namespace",
182 migration_status.dest_pool_namespace);
183 f->dump_string("dest_image_name", migration_status.dest_image_name);
184 f->dump_string("dest_image_id", migration_status.dest_image_id);
185 f->dump_string("state", migration_state);
186 f->dump_string("state_description", migration_status.state_description);
187 f->close_section(); // migration
188 }
f67539c2
TL
189 if (cache_state.present) {
190 f->open_object_section("image_cache_state");
191 f->dump_bool("clean", cache_state.clean);
192 f->dump_int("size", cache_state.size);
193 f->dump_string("host", cache_state.host);
194 f->dump_string("path", cache_state.path);
195 f->close_section(); // image_cache_state
196 }
7c673cae
FG
197 } else {
198 if (watchers.size()) {
199 std::cout << "Watchers:" << std::endl;
11fdf7f2
TL
200 for (auto &watcher : watchers) {
201 std::cout << "\twatcher=" << watcher.addr << " client." << watcher.id
202 << " cookie=" << watcher.cookie << std::endl;
7c673cae
FG
203 }
204 } else {
205 std::cout << "Watchers: none" << std::endl;
206 }
11fdf7f2
TL
207 if (!migration_state.empty()) {
208 if (!migration_status.source_pool_namespace.empty()) {
209 source_pool_name += ("/" + migration_status.source_pool_namespace);
210 }
211 if (!migration_status.dest_pool_namespace.empty()) {
212 dest_pool_name += ("/" + migration_status.dest_pool_namespace);
213 }
214
215 std::cout << "Migration:" << std::endl;
f67539c2
TL
216 std::cout << "\tsource: ";
217 if (!source_spec.empty()) {
218 std::cout << source_spec;
219 } else {
220 std::cout << source_pool_name << "/"
221 << migration_status.source_image_name;
222 if (!migration_status.source_image_id.empty()) {
223 std::cout << " (" << migration_status.source_image_id << ")";
224 }
11fdf7f2
TL
225 }
226 std::cout << std::endl;
227 std::cout << "\tdestination: " << dest_pool_name << "/"
228 << migration_status.dest_image_name << " ("
229 << migration_status.dest_image_id << ")" << std::endl;
230 std::cout << "\tstate: " << migration_state;
231 if (!migration_status.state_description.empty()) {
232 std::cout << " (" << migration_status.state_description << ")";
233 }
234 std::cout << std::endl;
235 }
f67539c2
TL
236
237 if (cache_state.present) {
238 std::cout << "Image cache state:" << std::endl;
239 std::cout << "\tclean: " << (cache_state.clean ? "true" : "false")
240 << std::endl
241 << "\tsize: " << byte_u_t(cache_state.size) << std::endl
242 << "\thost: " << cache_state.host << std::endl
243 << "\tpath: " << cache_state.path << std::endl;
244 }
7c673cae 245 }
11fdf7f2 246
7c673cae 247 if (f) {
11fdf7f2 248 f->close_section(); // status
7c673cae
FG
249 f->flush(std::cout);
250 }
251
252 return 0;
253}
254
255void get_arguments(po::options_description *positional,
256 po::options_description *options) {
257 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
258 at::add_format_options(options);
259}
260
11fdf7f2
TL
261int execute(const po::variables_map &vm,
262 const std::vector<std::string> &ceph_global_init_args) {
7c673cae
FG
263 size_t arg_index = 0;
264 std::string pool_name;
11fdf7f2 265 std::string namespace_name;
7c673cae
FG
266 std::string image_name;
267 std::string snap_name;
268 int r = utils::get_pool_image_snapshot_names(
11fdf7f2
TL
269 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
270 &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_NONE,
271 utils::SPEC_VALIDATION_NONE);
7c673cae
FG
272 if (r < 0) {
273 return r;
274 }
275
276 at::Format::Formatter formatter;
277 r = utils::get_formatter(vm, &formatter);
278 if (r < 0) {
279 return r;
280 }
281
282 librados::Rados rados;
283 librados::IoCtx io_ctx;
284 librbd::Image image;
11fdf7f2
TL
285 r = utils::init_and_open_image(pool_name, namespace_name, image_name, "", "",
286 true, &rados, &io_ctx, &image);
7c673cae
FG
287 if (r < 0) {
288 return r;
289 }
290
11fdf7f2 291 r = do_show_status(io_ctx, image_name, image, formatter.get());
7c673cae
FG
292 if (r < 0) {
293 std::cerr << "rbd: show status failed: " << cpp_strerror(r) << std::endl;
294 return r;
295 }
296 return 0;
297}
298
299Shell::Action action(
300 {"status"}, {}, "Show the status of this image.", "", &get_arguments,
301 &execute);
302
303} // namespace status
304} // namespace action
305} // namespace rbd