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 struct timespec create_timestamp
;
134 image
.get_create_timestamp(&create_timestamp
);
136 string create_timestamp_str
= "";
137 if(create_timestamp
.tv_sec
!= 0) {
138 time_t timestamp
= create_timestamp
.tv_sec
;
139 create_timestamp_str
= ctime(×tamp
);
140 create_timestamp_str
= create_timestamp_str
.substr(0,
141 create_timestamp_str
.length() - 1);
145 f
->open_object_section("image");
146 if (!imgname
.empty()) {
147 f
->dump_string("name", imgname
);
149 f
->dump_string("id", imgid
);
151 f
->dump_unsigned("size", info
.size
);
152 f
->dump_unsigned("objects", info
.num_objs
);
153 f
->dump_int("order", info
.order
);
154 f
->dump_unsigned("object_size", info
.obj_size
);
155 if (!data_pool
.empty()) {
156 f
->dump_string("data_pool", data_pool
);
158 f
->dump_string("block_name_prefix", prefix
);
159 f
->dump_int("format", (old_format
? 1 : 2));
161 std::cout
<< "rbd image '" << (imgname
.empty() ? imgid
: imgname
) << "':\n"
162 << "\tsize " << prettybyte_t(info
.size
) << " in "
163 << info
.num_objs
<< " objects"
165 << "\torder " << info
.order
166 << " (" << prettybyte_t(info
.obj_size
) << " objects)"
168 if (!data_pool
.empty()) {
169 std::cout
<< "\tdata_pool: " << data_pool
<< std::endl
;
171 std::cout
<< "\tblock_name_prefix: " << prefix
173 << "\tformat: " << (old_format
? "1" : "2")
178 format_features(f
, features
);
179 format_flags(f
, flags
);
182 if (!create_timestamp_str
.empty()) {
184 f
->dump_string("create_timestamp", create_timestamp_str
);
186 std::cout
<< "\tcreate_timestamp: " << create_timestamp_str
191 // snapshot info, if present
192 if (!snapname
.empty()) {
194 f
->dump_string("protected", snap_protected
? "true" : "false");
196 std::cout
<< "\tprotected: " << (snap_protected
? "True" : "False")
201 if (snap_limit
< UINT64_MAX
) {
203 f
->dump_unsigned("snapshot_limit", snap_limit
);
205 std::cout
<< "\tsnapshot_limit: " << snap_limit
<< std::endl
;
209 // parent info, if present
210 std::string parent_pool
, parent_name
, parent_id
, parent_snapname
;
211 if ((image
.parent_info2(&parent_pool
, &parent_name
, &parent_id
,
212 &parent_snapname
) == 0) &&
213 parent_name
.length() > 0) {
215 librbd::trash_image_info_t trash_image_info
;
217 r
= rbd
.trash_get(io_ctx
, parent_id
.c_str(), &trash_image_info
);
218 bool trash_image_info_valid
= (r
== 0);
221 f
->open_object_section("parent");
222 f
->dump_string("pool", parent_pool
);
223 f
->dump_string("image", parent_name
);
224 f
->dump_string("snapshot", parent_snapname
);
225 if (trash_image_info_valid
) {
226 f
->dump_string("trash", parent_id
);
228 f
->dump_unsigned("overlap", overlap
);
231 std::cout
<< "\tparent: " << parent_pool
<< "/" << parent_name
232 << "@" << parent_snapname
;
233 if (trash_image_info_valid
) {
234 std::cout
<< " (trash " << parent_id
<< ")";
236 std::cout
<< std::endl
;
237 std::cout
<< "\toverlap: " << prettybyte_t(overlap
) << std::endl
;
241 // striping info, if feature is set
242 if (features
& RBD_FEATURE_STRIPINGV2
) {
244 f
->dump_unsigned("stripe_unit", image
.get_stripe_unit());
245 f
->dump_unsigned("stripe_count", image
.get_stripe_count());
247 std::cout
<< "\tstripe unit: " << prettybyte_t(image
.get_stripe_unit())
249 << "\tstripe count: " << image
.get_stripe_count() << std::endl
;
253 if (features
& RBD_FEATURE_JOURNALING
) {
255 f
->dump_string("journal", utils::image_id(image
));
257 std::cout
<< "\tjournal: " << utils::image_id(image
) << std::endl
;
261 if (features
& RBD_FEATURE_JOURNALING
) {
263 f
->open_object_section("mirroring");
264 f
->dump_string("state",
265 utils::mirror_image_state(mirror_image
.state
));
266 if (mirror_image
.state
!= RBD_MIRROR_IMAGE_DISABLED
) {
267 f
->dump_string("global_id", mirror_image
.global_id
);
268 f
->dump_bool("primary", mirror_image
.primary
);
272 std::cout
<< "\tmirroring state: "
273 << utils::mirror_image_state(mirror_image
.state
) << std::endl
;
274 if (mirror_image
.state
!= RBD_MIRROR_IMAGE_DISABLED
) {
275 std::cout
<< "\tmirroring global id: " << mirror_image
.global_id
277 << "\tmirroring primary: "
278 << (mirror_image
.primary
? "true" : "false") <<std::endl
;
291 void get_arguments(po::options_description
*positional
,
292 po::options_description
*options
) {
293 at::add_image_or_snap_spec_options(positional
, options
,
294 at::ARGUMENT_MODIFIER_NONE
);
295 at::add_image_id_option(options
);
296 at::add_format_options(options
);
299 int execute(const po::variables_map
&vm
) {
300 size_t arg_index
= 0;
301 std::string pool_name
;
302 std::string image_name
;
303 std::string snap_name
;
304 std::string image_id
;
306 if (vm
.count(at::IMAGE_ID
)) {
307 image_id
= vm
[at::IMAGE_ID
].as
<std::string
>();
310 bool has_image_spec
= utils::check_if_image_spec_present(
311 vm
, at::ARGUMENT_MODIFIER_NONE
, arg_index
);
313 if (!image_id
.empty() && has_image_spec
) {
314 std::cerr
<< "rbd: trying to access image using both name and id. "
320 if (image_id
.empty()) {
321 r
= utils::get_pool_image_snapshot_names(vm
, at::ARGUMENT_MODIFIER_NONE
,
322 &arg_index
, &pool_name
,
323 &image_name
, &snap_name
,
324 utils::SNAPSHOT_PRESENCE_PERMITTED
,
325 utils::SPEC_VALIDATION_NONE
);
327 r
= utils::get_pool_snapshot_names(vm
, at::ARGUMENT_MODIFIER_NONE
,
328 &arg_index
, &pool_name
, &snap_name
,
329 utils::SNAPSHOT_PRESENCE_PERMITTED
,
330 utils::SPEC_VALIDATION_NONE
);
336 at::Format::Formatter formatter
;
337 r
= utils::get_formatter(vm
, &formatter
);
342 librados::Rados rados
;
343 librados::IoCtx io_ctx
;
345 r
= utils::init_and_open_image(pool_name
, image_name
, image_id
, snap_name
,
346 true, &rados
, &io_ctx
, &image
);
351 r
= do_show_info(io_ctx
, image
, image_name
, image_id
, snap_name
,
354 std::cerr
<< "rbd: info: " << cpp_strerror(r
) << std::endl
;
360 Shell::Action
action(
361 {"info"}, {}, "Show information about image size, striping, etc.", "",
362 &get_arguments
, &execute
);
365 } // namespace action