1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
12 #include <boost/program_options.hpp>
18 namespace at
= argument_types
;
19 namespace po
= boost::program_options
;
21 static void format_bitmask(Formatter
*f
, const std::string
&name
,
22 const std::map
<uint64_t, std::string
>& mapping
,
26 std::string
group_name(name
+ "s");
28 std::cout
<< "\t" << group_name
<< ": ";
30 f
->open_array_section(group_name
.c_str());
32 for (std::map
<uint64_t, std::string
>::const_iterator it
= mapping
.begin();
33 it
!= mapping
.end(); ++it
) {
34 if ((it
->first
& bitmask
) == 0) {
42 std::cout
<< it
->second
;
44 f
->dump_string(name
.c_str(), it
->second
);
48 std::cout
<< std::endl
;
54 static void format_features(Formatter
*f
, uint64_t features
)
56 format_bitmask(f
, "feature", at::ImageFeatures::FEATURE_MAPPING
, features
);
59 static void format_flags(Formatter
*f
, uint64_t flags
)
61 std::map
<uint64_t, std::string
> mapping
= {
62 {RBD_FLAG_OBJECT_MAP_INVALID
, "object map invalid"},
63 {RBD_FLAG_FAST_DIFF_INVALID
, "fast diff invalid"}};
64 format_bitmask(f
, "flag", mapping
, flags
);
67 static int do_show_info(librados::IoCtx
&io_ctx
, librbd::Image
& image
,
68 const std::string
&imgname
, const std::string
&imgid
,
69 const std::string
&snapname
, Formatter
*f
)
71 librbd::image_info_t info
;
73 uint64_t overlap
, features
, flags
, snap_limit
;
74 bool snap_protected
= false;
75 librbd::mirror_image_info_t mirror_image
;
78 r
= image
.stat(info
, sizeof(info
));
82 r
= image
.old_format(&old_format
);
86 std::string data_pool
;
88 int64_t data_pool_id
= image
.get_data_pool_id();
89 if (data_pool_id
!= io_ctx
.get_id()) {
90 librados::Rados
rados(io_ctx
);
91 librados::IoCtx data_io_ctx
;
92 r
= rados
.ioctx_create2(data_pool_id
, data_io_ctx
);
94 data_pool
= "<missing data pool " + stringify(data_pool_id
) + ">";
96 data_pool
= data_io_ctx
.get_pool_name();
101 r
= image
.overlap(&overlap
);
105 r
= image
.features(&features
);
109 r
= image
.get_flags(&flags
);
114 if (!snapname
.empty()) {
115 r
= image
.snap_is_protected(snapname
.c_str(), &snap_protected
);
120 if (features
& RBD_FEATURE_JOURNALING
) {
121 r
= image
.mirror_image_get_info(&mirror_image
, sizeof(mirror_image
));
127 r
= image
.snap_get_limit(&snap_limit
);
131 std::string prefix
= image
.get_block_name_prefix();
133 librbd::group_spec_t group_spec
;
134 r
= image
.get_group(&group_spec
);
139 std::string group_string
= "";
140 if (-1 != group_spec
.pool
)
141 group_string
= stringify(group_spec
.pool
) + "." + group_spec
.name
;
144 f
->open_object_section("image");
145 if (!imgname
.empty()) {
146 f
->dump_string("name", imgname
);
148 f
->dump_string("id", imgid
);
150 f
->dump_unsigned("size", info
.size
);
151 f
->dump_unsigned("objects", info
.num_objs
);
152 f
->dump_int("order", info
.order
);
153 f
->dump_unsigned("object_size", info
.obj_size
);
154 if (!data_pool
.empty()) {
155 f
->dump_string("data_pool", data_pool
);
157 f
->dump_string("block_name_prefix", prefix
);
158 f
->dump_int("format", (old_format
? 1 : 2));
160 std::cout
<< "rbd image '" << (imgname
.empty() ? imgid
: imgname
) << "':\n"
161 << "\tsize " << prettybyte_t(info
.size
) << " in "
162 << info
.num_objs
<< " objects"
164 << "\torder " << info
.order
165 << " (" << prettybyte_t(info
.obj_size
) << " objects)"
167 if (!data_pool
.empty()) {
168 std::cout
<< "\tdata_pool: " << data_pool
<< std::endl
;
170 std::cout
<< "\tblock_name_prefix: " << prefix
172 << "\tformat: " << (old_format
? "1" : "2")
177 format_features(f
, features
);
178 format_flags(f
, flags
);
181 if (!group_string
.empty()) {
183 f
->dump_string("group", group_string
);
185 std::cout
<< "\tconsistency group: " << group_string
190 // snapshot info, if present
191 if (!snapname
.empty()) {
193 f
->dump_string("protected", snap_protected
? "true" : "false");
195 std::cout
<< "\tprotected: " << (snap_protected
? "True" : "False")
200 if (snap_limit
< UINT64_MAX
) {
202 f
->dump_unsigned("snapshot_limit", snap_limit
);
204 std::cout
<< "\tsnapshot_limit: " << snap_limit
<< std::endl
;
208 // parent info, if present
209 std::string parent_pool
, parent_name
, parent_id
, parent_snapname
;
210 if ((image
.parent_info2(&parent_pool
, &parent_name
, &parent_id
,
211 &parent_snapname
) == 0) &&
212 parent_name
.length() > 0) {
214 librbd::trash_image_info_t trash_image_info
;
216 r
= rbd
.trash_get(io_ctx
, parent_id
.c_str(), &trash_image_info
);
217 bool trash_image_info_valid
= (r
== 0);
220 f
->open_object_section("parent");
221 f
->dump_string("pool", parent_pool
);
222 f
->dump_string("image", parent_name
);
223 f
->dump_string("snapshot", parent_snapname
);
224 if (trash_image_info_valid
) {
225 f
->dump_string("trash", parent_id
);
227 f
->dump_unsigned("overlap", overlap
);
230 std::cout
<< "\tparent: " << parent_pool
<< "/" << parent_name
231 << "@" << parent_snapname
;
232 if (trash_image_info_valid
) {
233 std::cout
<< " (trash " << parent_id
<< ")";
235 std::cout
<< std::endl
;
236 std::cout
<< "\toverlap: " << prettybyte_t(overlap
) << std::endl
;
240 // striping info, if feature is set
241 if (features
& RBD_FEATURE_STRIPINGV2
) {
243 f
->dump_unsigned("stripe_unit", image
.get_stripe_unit());
244 f
->dump_unsigned("stripe_count", image
.get_stripe_count());
246 std::cout
<< "\tstripe unit: " << prettybyte_t(image
.get_stripe_unit())
248 << "\tstripe count: " << image
.get_stripe_count() << std::endl
;
252 if (features
& RBD_FEATURE_JOURNALING
) {
254 f
->dump_string("journal", utils::image_id(image
));
256 std::cout
<< "\tjournal: " << utils::image_id(image
) << std::endl
;
260 if (features
& RBD_FEATURE_JOURNALING
) {
262 f
->open_object_section("mirroring");
263 f
->dump_string("state",
264 utils::mirror_image_state(mirror_image
.state
));
265 if (mirror_image
.state
!= RBD_MIRROR_IMAGE_DISABLED
) {
266 f
->dump_string("global_id", mirror_image
.global_id
);
267 f
->dump_bool("primary", mirror_image
.primary
);
271 std::cout
<< "\tmirroring state: "
272 << utils::mirror_image_state(mirror_image
.state
) << std::endl
;
273 if (mirror_image
.state
!= RBD_MIRROR_IMAGE_DISABLED
) {
274 std::cout
<< "\tmirroring global id: " << mirror_image
.global_id
276 << "\tmirroring primary: "
277 << (mirror_image
.primary
? "true" : "false") <<std::endl
;
290 void get_arguments(po::options_description
*positional
,
291 po::options_description
*options
) {
292 at::add_image_or_snap_spec_options(positional
, options
,
293 at::ARGUMENT_MODIFIER_NONE
);
294 at::add_image_id_option(options
);
295 at::add_format_options(options
);
298 int execute(const po::variables_map
&vm
) {
299 size_t arg_index
= 0;
300 std::string pool_name
;
301 std::string image_name
;
302 std::string snap_name
;
303 std::string image_id
;
305 if (vm
.count(at::IMAGE_ID
)) {
306 image_id
= vm
[at::IMAGE_ID
].as
<std::string
>();
309 bool has_image_spec
= utils::check_if_image_spec_present(
310 vm
, at::ARGUMENT_MODIFIER_NONE
, arg_index
);
312 if (!image_id
.empty() && has_image_spec
) {
313 std::cerr
<< "rbd: trying to access image using both name and id. "
319 if (image_id
.empty()) {
320 r
= utils::get_pool_image_snapshot_names(vm
, at::ARGUMENT_MODIFIER_NONE
,
321 &arg_index
, &pool_name
,
322 &image_name
, &snap_name
,
323 utils::SNAPSHOT_PRESENCE_PERMITTED
,
324 utils::SPEC_VALIDATION_NONE
);
326 r
= utils::get_pool_snapshot_names(vm
, at::ARGUMENT_MODIFIER_NONE
,
327 &arg_index
, &pool_name
, &snap_name
,
328 utils::SNAPSHOT_PRESENCE_PERMITTED
,
329 utils::SPEC_VALIDATION_NONE
);
335 at::Format::Formatter formatter
;
336 r
= utils::get_formatter(vm
, &formatter
);
341 librados::Rados rados
;
342 librados::IoCtx io_ctx
;
344 r
= utils::init_and_open_image(pool_name
, image_name
, image_id
, snap_name
,
345 true, &rados
, &io_ctx
, &image
);
350 r
= do_show_info(io_ctx
, image
, image_name
, image_id
, snap_name
,
353 std::cerr
<< "rbd: info: " << cpp_strerror(r
) << std::endl
;
359 Shell::Action
action(
360 {"info"}, {}, "Show information about image size, striping, etc.", "",
361 &get_arguments
, &execute
);
364 } // namespace action