]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd/action/Info.cc
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / tools / rbd / action / Info.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
4#include "tools/rbd/ArgumentTypes.h"
5#include "tools/rbd/Shell.h"
6#include "tools/rbd/Utils.h"
7#include "include/types.h"
8#include "include/stringify.h"
9#include "common/errno.h"
10#include "common/Formatter.h"
11#include <iostream>
12#include <boost/program_options.hpp>
13
11fdf7f2
TL
14#include "common/Clock.h"
15
7c673cae
FG
16namespace rbd {
17namespace action {
18namespace info {
19
20namespace at = argument_types;
21namespace po = boost::program_options;
22
23static void format_bitmask(Formatter *f, const std::string &name,
24 const std::map<uint64_t, std::string>& mapping,
25 uint64_t bitmask)
26{
27 int count = 0;
28 std::string group_name(name + "s");
29 if (f == NULL) {
30 std::cout << "\t" << group_name << ": ";
31 } else {
32 f->open_array_section(group_name.c_str());
33 }
34 for (std::map<uint64_t, std::string>::const_iterator it = mapping.begin();
35 it != mapping.end(); ++it) {
36 if ((it->first & bitmask) == 0) {
37 continue;
38 }
39
40 if (f == NULL) {
41 if (count++ > 0) {
42 std::cout << ", ";
43 }
44 std::cout << it->second;
45 } else {
46 f->dump_string(name.c_str(), it->second);
47 }
48 }
49 if (f == NULL) {
50 std::cout << std::endl;
51 } else {
52 f->close_section();
53 }
54}
55
56static void format_features(Formatter *f, uint64_t features)
57{
58 format_bitmask(f, "feature", at::ImageFeatures::FEATURE_MAPPING, features);
59}
60
11fdf7f2
TL
61static void format_op_features(Formatter *f, uint64_t op_features)
62{
63 static std::map<uint64_t, std::string> mapping = {
64 {RBD_OPERATION_FEATURE_CLONE_PARENT, RBD_OPERATION_FEATURE_NAME_CLONE_PARENT},
65 {RBD_OPERATION_FEATURE_CLONE_CHILD, RBD_OPERATION_FEATURE_NAME_CLONE_CHILD},
66 {RBD_OPERATION_FEATURE_GROUP, RBD_OPERATION_FEATURE_NAME_GROUP},
67 {RBD_OPERATION_FEATURE_SNAP_TRASH, RBD_OPERATION_FEATURE_NAME_SNAP_TRASH}};
68 format_bitmask(f, "op_feature", mapping, op_features);
69}
70
7c673cae
FG
71static void format_flags(Formatter *f, uint64_t flags)
72{
73 std::map<uint64_t, std::string> mapping = {
74 {RBD_FLAG_OBJECT_MAP_INVALID, "object map invalid"},
75 {RBD_FLAG_FAST_DIFF_INVALID, "fast diff invalid"}};
76 format_bitmask(f, "flag", mapping, flags);
77}
78
11fdf7f2
TL
79void format_timestamp(struct timespec timestamp, std::string &timestamp_str) {
80 if(timestamp.tv_sec != 0) {
81 time_t ts = timestamp.tv_sec;
82 timestamp_str = ctime(&ts);
83 timestamp_str = timestamp_str.substr(0, timestamp_str.length() - 1);
84 }
85}
86
7c673cae 87static int do_show_info(librados::IoCtx &io_ctx, librbd::Image& image,
7c673cae
FG
88 const std::string &snapname, Formatter *f)
89{
90 librbd::image_info_t info;
91 uint8_t old_format;
92 uint64_t overlap, features, flags, snap_limit;
93 bool snap_protected = false;
94 librbd::mirror_image_info_t mirror_image;
9f95a23c 95 librbd::mirror_image_mode_t mirror_mode = RBD_MIRROR_IMAGE_MODE_JOURNAL;
11fdf7f2 96 std::vector<librbd::snap_info_t> snaps;
7c673cae
FG
97 int r;
98
11fdf7f2
TL
99 std::string imgname;
100 r = image.get_name(&imgname);
101 if (r < 0)
102 return r;
103
104 r = image.snap_list(snaps);
105 if (r < 0)
106 return r;
107
7c673cae
FG
108 r = image.stat(info, sizeof(info));
109 if (r < 0)
110 return r;
111
112 r = image.old_format(&old_format);
113 if (r < 0)
114 return r;
115
11fdf7f2
TL
116 std::string imgid;
117 if (!old_format) {
118 r = image.get_id(&imgid);
119 if (r < 0)
120 return r;
121 }
122
7c673cae
FG
123 std::string data_pool;
124 if (!old_format) {
125 int64_t data_pool_id = image.get_data_pool_id();
126 if (data_pool_id != io_ctx.get_id()) {
127 librados::Rados rados(io_ctx);
128 librados::IoCtx data_io_ctx;
129 r = rados.ioctx_create2(data_pool_id, data_io_ctx);
130 if (r < 0) {
131 data_pool = "<missing data pool " + stringify(data_pool_id) + ">";
132 } else {
133 data_pool = data_io_ctx.get_pool_name();
134 }
135 }
136 }
137
138 r = image.overlap(&overlap);
139 if (r < 0)
140 return r;
141
142 r = image.features(&features);
143 if (r < 0)
144 return r;
145
11fdf7f2
TL
146 uint64_t op_features;
147 r = image.get_op_features(&op_features);
148 if (r < 0) {
149 return r;
150 }
151
7c673cae
FG
152 r = image.get_flags(&flags);
153 if (r < 0) {
154 return r;
155 }
156
157 if (!snapname.empty()) {
158 r = image.snap_is_protected(snapname.c_str(), &snap_protected);
159 if (r < 0)
160 return r;
161 }
162
9f95a23c
TL
163 mirror_image.state = RBD_MIRROR_IMAGE_DISABLED;
164 r = image.mirror_image_get_info(&mirror_image, sizeof(mirror_image));
165 if (r < 0) {
166 return r;
167 }
168
169 if (mirror_image.state != RBD_MIRROR_IMAGE_DISABLED) {
170 r = image.mirror_image_get_mode(&mirror_mode);
7c673cae
FG
171 if (r < 0) {
172 return r;
173 }
174 }
175
176 r = image.snap_get_limit(&snap_limit);
177 if (r < 0)
178 return r;
179
180 std::string prefix = image.get_block_name_prefix();
181
11fdf7f2
TL
182 librbd::group_info_t group_info;
183 r = image.get_group(&group_info, sizeof(group_info));
184 if (r < 0) {
185 return r;
186 }
187
188 std::string group_string = "";
189 if (RBD_GROUP_INVALID_POOL != group_info.pool) {
190 std::string group_pool;
191 librados::Rados rados(io_ctx);
192 librados::IoCtx group_io_ctx;
193 r = rados.ioctx_create2(group_info.pool, group_io_ctx);
194 if (r < 0) {
195 group_pool = "<missing group pool " + stringify(group_info.pool) + ">";
196 } else {
197 group_pool = group_io_ctx.get_pool_name();
198 }
199
200 group_string = group_pool + "/";
201 if (!io_ctx.get_namespace().empty()) {
202 group_string += io_ctx.get_namespace() + "/";
203 }
204 group_string += group_info.name;
205 }
206
31f18b77
FG
207 struct timespec create_timestamp;
208 image.get_create_timestamp(&create_timestamp);
209
11fdf7f2
TL
210 std::string create_timestamp_str = "";
211 format_timestamp(create_timestamp, create_timestamp_str);
212
213 struct timespec access_timestamp;
214 image.get_access_timestamp(&access_timestamp);
215
216 std::string access_timestamp_str = "";
217 format_timestamp(access_timestamp, access_timestamp_str);
218
219 struct timespec modify_timestamp;
220 image.get_modify_timestamp(&modify_timestamp);
221
222 std::string modify_timestamp_str = "";
223 format_timestamp(modify_timestamp, modify_timestamp_str);
31f18b77 224
7c673cae
FG
225 if (f) {
226 f->open_object_section("image");
11fdf7f2
TL
227 f->dump_string("name", imgname);
228 f->dump_string("id", imgid);
7c673cae
FG
229 f->dump_unsigned("size", info.size);
230 f->dump_unsigned("objects", info.num_objs);
231 f->dump_int("order", info.order);
232 f->dump_unsigned("object_size", info.obj_size);
11fdf7f2 233 f->dump_int("snapshot_count", snaps.size());
7c673cae
FG
234 if (!data_pool.empty()) {
235 f->dump_string("data_pool", data_pool);
236 }
237 f->dump_string("block_name_prefix", prefix);
238 f->dump_int("format", (old_format ? 1 : 2));
239 } else {
11fdf7f2 240 std::cout << "rbd image '" << imgname << "':\n"
1adf2230 241 << "\tsize " << byte_u_t(info.size) << " in "
7c673cae
FG
242 << info.num_objs << " objects"
243 << std::endl
244 << "\torder " << info.order
1adf2230 245 << " (" << byte_u_t(info.obj_size) << " objects)"
11fdf7f2
TL
246 << std::endl
247 << "\tsnapshot_count: " << snaps.size()
7c673cae 248 << std::endl;
11fdf7f2
TL
249 if (!imgid.empty()) {
250 std::cout << "\tid: " << imgid << std::endl;
251 }
7c673cae
FG
252 if (!data_pool.empty()) {
253 std::cout << "\tdata_pool: " << data_pool << std::endl;
254 }
255 std::cout << "\tblock_name_prefix: " << prefix
256 << std::endl
257 << "\tformat: " << (old_format ? "1" : "2")
258 << std::endl;
259 }
260
261 if (!old_format) {
262 format_features(f, features);
11fdf7f2 263 format_op_features(f, op_features);
7c673cae
FG
264 format_flags(f, flags);
265 }
266
11fdf7f2
TL
267 if (!group_string.empty()) {
268 if (f) {
269 f->dump_string("group", group_string);
270 } else {
271 std::cout << "\tgroup: " << group_string
272 << std::endl;
273 }
274 }
275
31f18b77
FG
276 if (!create_timestamp_str.empty()) {
277 if (f) {
278 f->dump_string("create_timestamp", create_timestamp_str);
279 } else {
280 std::cout << "\tcreate_timestamp: " << create_timestamp_str
281 << std::endl;
282 }
283 }
284
11fdf7f2
TL
285 if (!access_timestamp_str.empty()) {
286 if (f) {
287 f->dump_string("access_timestamp", access_timestamp_str);
288 } else {
289 std::cout << "\taccess_timestamp: " << access_timestamp_str
290 << std::endl;
291 }
292 }
293
294 if (!modify_timestamp_str.empty()) {
295 if (f) {
296 f->dump_string("modify_timestamp", modify_timestamp_str);
297 } else {
298 std::cout << "\tmodify_timestamp: " << modify_timestamp_str
299 << std::endl;
300 }
301 }
302
7c673cae
FG
303 // snapshot info, if present
304 if (!snapname.empty()) {
305 if (f) {
306 f->dump_string("protected", snap_protected ? "true" : "false");
307 } else {
308 std::cout << "\tprotected: " << (snap_protected ? "True" : "False")
309 << std::endl;
310 }
311 }
312
313 if (snap_limit < UINT64_MAX) {
314 if (f) {
315 f->dump_unsigned("snapshot_limit", snap_limit);
316 } else {
317 std::cout << "\tsnapshot_limit: " << snap_limit << std::endl;
318 }
319 }
320
321 // parent info, if present
11fdf7f2
TL
322 librbd::linked_image_spec_t parent_image_spec;
323 librbd::snap_spec_t parent_snap_spec;
324 if ((image.get_parent(&parent_image_spec, &parent_snap_spec) == 0) &&
325 (parent_image_spec.image_name.length() > 0)) {
7c673cae
FG
326 if (f) {
327 f->open_object_section("parent");
11fdf7f2
TL
328 f->dump_string("pool", parent_image_spec.pool_name);
329 f->dump_string("pool_namespace", parent_image_spec.pool_namespace);
330 f->dump_string("image", parent_image_spec.image_name);
331 f->dump_string("id", parent_image_spec.image_id);
332 f->dump_string("snapshot", parent_snap_spec.name);
333 f->dump_bool("trash", parent_image_spec.trash);
7c673cae
FG
334 f->dump_unsigned("overlap", overlap);
335 f->close_section();
336 } else {
11fdf7f2
TL
337 std::cout << "\tparent: " << parent_image_spec.pool_name << "/";
338 if (!parent_image_spec.pool_namespace.empty()) {
339 std::cout << parent_image_spec.pool_namespace << "/";
340 }
341 std::cout << parent_image_spec.image_name << "@"
342 << parent_snap_spec.name;
343 if (parent_image_spec.trash) {
344 std::cout << " (trash " << parent_image_spec.image_id << ")";
7c673cae
FG
345 }
346 std::cout << std::endl;
1adf2230 347 std::cout << "\toverlap: " << byte_u_t(overlap) << std::endl;
7c673cae
FG
348 }
349 }
350
351 // striping info, if feature is set
352 if (features & RBD_FEATURE_STRIPINGV2) {
353 if (f) {
354 f->dump_unsigned("stripe_unit", image.get_stripe_unit());
355 f->dump_unsigned("stripe_count", image.get_stripe_count());
356 } else {
1adf2230 357 std::cout << "\tstripe unit: " << byte_u_t(image.get_stripe_unit())
7c673cae
FG
358 << std::endl
359 << "\tstripe count: " << image.get_stripe_count() << std::endl;
360 }
361 }
362
363 if (features & RBD_FEATURE_JOURNALING) {
364 if (f) {
365 f->dump_string("journal", utils::image_id(image));
366 } else {
367 std::cout << "\tjournal: " << utils::image_id(image) << std::endl;
368 }
369 }
370
9f95a23c
TL
371 if (features & RBD_FEATURE_JOURNALING ||
372 mirror_image.state != RBD_MIRROR_IMAGE_DISABLED) {
7c673cae
FG
373 if (f) {
374 f->open_object_section("mirroring");
9f95a23c
TL
375 f->dump_string("mode",
376 utils::mirror_image_mode(mirror_mode));
7c673cae
FG
377 f->dump_string("state",
378 utils::mirror_image_state(mirror_image.state));
379 if (mirror_image.state != RBD_MIRROR_IMAGE_DISABLED) {
380 f->dump_string("global_id", mirror_image.global_id);
381 f->dump_bool("primary", mirror_image.primary);
382 }
383 f->close_section();
384 } else {
385 std::cout << "\tmirroring state: "
386 << utils::mirror_image_state(mirror_image.state) << std::endl;
387 if (mirror_image.state != RBD_MIRROR_IMAGE_DISABLED) {
9f95a23c
TL
388 std::cout << "\tmirroring mode: "
389 << utils::mirror_image_mode(mirror_mode) << std::endl
390 << "\tmirroring global id: " << mirror_image.global_id
7c673cae
FG
391 << std::endl
392 << "\tmirroring primary: "
393 << (mirror_image.primary ? "true" : "false") <<std::endl;
394 }
395 }
396 }
397
398 if (f) {
399 f->close_section();
400 f->flush(std::cout);
401 }
402
403 return 0;
404}
405
406void get_arguments(po::options_description *positional,
407 po::options_description *options) {
408 at::add_image_or_snap_spec_options(positional, options,
409 at::ARGUMENT_MODIFIER_NONE);
410 at::add_image_id_option(options);
411 at::add_format_options(options);
412}
413
11fdf7f2
TL
414int execute(const po::variables_map &vm,
415 const std::vector<std::string> &ceph_global_init_args) {
7c673cae
FG
416 size_t arg_index = 0;
417 std::string pool_name;
11fdf7f2 418 std::string namespace_name;
7c673cae
FG
419 std::string image_name;
420 std::string snap_name;
421 std::string image_id;
422
423 if (vm.count(at::IMAGE_ID)) {
424 image_id = vm[at::IMAGE_ID].as<std::string>();
425 }
426
11fdf7f2
TL
427 int r = utils::get_pool_image_snapshot_names(
428 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
429 &image_name, &snap_name, image_id.empty(),
430 utils::SNAPSHOT_PRESENCE_PERMITTED, utils::SPEC_VALIDATION_NONE);
431 if (r < 0) {
432 return r;
433 }
7c673cae 434
11fdf7f2 435 if (!image_id.empty() && !image_name.empty()) {
7c673cae
FG
436 std::cerr << "rbd: trying to access image using both name and id. "
437 << std::endl;
438 return -EINVAL;
439 }
440
7c673cae
FG
441 at::Format::Formatter formatter;
442 r = utils::get_formatter(vm, &formatter);
443 if (r < 0) {
444 return r;
445 }
446
447 librados::Rados rados;
448 librados::IoCtx io_ctx;
449 librbd::Image image;
11fdf7f2
TL
450 r = utils::init_and_open_image(pool_name, namespace_name, image_name,
451 image_id, snap_name, true, &rados, &io_ctx,
452 &image);
7c673cae
FG
453 if (r < 0) {
454 return r;
455 }
456
11fdf7f2 457 r = do_show_info(io_ctx, image, snap_name, formatter.get());
7c673cae
FG
458 if (r < 0) {
459 std::cerr << "rbd: info: " << cpp_strerror(r) << std::endl;
460 return r;
461 }
462 return 0;
463}
464
465Shell::Action action(
466 {"info"}, {}, "Show information about image size, striping, etc.", "",
467 &get_arguments, &execute);
468
469} // namespace info
470} // namespace action
471} // namespace rbd