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 "common/errno.h"
8 #include "common/Formatter.h"
10 #include <boost/program_options.hpp>
16 namespace at
= argument_types
;
17 namespace po
= boost::program_options
;
19 int do_list_children(librados::IoCtx
&io_ctx
, librbd::Image
&image
,
20 bool all_flag
, bool descendants_flag
, Formatter
*f
)
22 std::vector
<librbd::linked_image_spec_t
> children
;
25 if (descendants_flag
) {
26 r
= image
.list_descendants(&children
);
28 r
= image
.list_children3(&children
);
34 f
->open_array_section("children");
36 for (auto& child
: children
) {
37 bool trash
= child
.trash
;
40 f
->open_object_section("child");
41 f
->dump_string("pool", child
.pool_name
);
42 f
->dump_string("pool_namespace", child
.pool_namespace
);
43 f
->dump_string("image", child
.image_name
);
44 f
->dump_string("id", child
.image_id
);
45 f
->dump_bool("trash", child
.trash
);
48 f
->open_object_section("child");
49 f
->dump_string("pool", child
.pool_name
);
50 f
->dump_string("pool_namespace", child
.pool_namespace
);
51 f
->dump_string("image", child
.image_name
);
54 } else if (all_flag
|| !trash
) {
55 if (child
.pool_name
.empty()) {
56 std::cout
<< "(child missing " << child
.pool_id
<< "/";
58 std::cout
<< child
.pool_name
<< "/";
60 if (!child
.pool_namespace
.empty()) {
61 std::cout
<< child
.pool_namespace
<< "/";
63 if (child
.image_name
.empty()) {
64 std::cout
<< child
.image_id
<< ")";
66 std::cout
<< child
.image_name
;
68 std::cout
<< " (trash " << child
.image_id
<< ")";
71 std::cout
<< std::endl
;
83 void get_arguments(po::options_description
*positional
,
84 po::options_description
*options
) {
85 at::add_image_or_snap_spec_options(positional
, options
,
86 at::ARGUMENT_MODIFIER_NONE
);
87 at::add_snap_id_option(options
);
88 options
->add_options()
89 ("all,a", po::bool_switch(), "list all children (include trash)");
90 options
->add_options()
91 ("descendants", po::bool_switch(), "include all descendants");
92 at::add_format_options(options
);
95 int execute(const po::variables_map
&vm
,
96 const std::vector
<std::string
> &ceph_global_init_args
) {
97 uint64_t snap_id
= LIBRADOS_SNAP_HEAD
;
98 if (vm
.count(at::SNAPSHOT_ID
)) {
99 snap_id
= vm
[at::SNAPSHOT_ID
].as
<uint64_t>();
102 size_t arg_index
= 0;
103 std::string pool_name
;
104 std::string namespace_name
;
105 std::string image_name
;
106 std::string snap_name
;
107 int r
= utils::get_pool_image_snapshot_names(
108 vm
, at::ARGUMENT_MODIFIER_NONE
, &arg_index
, &pool_name
, &namespace_name
,
109 &image_name
, &snap_name
, true, utils::SNAPSHOT_PRESENCE_PERMITTED
,
110 utils::SPEC_VALIDATION_NONE
);
115 if (snap_id
!= LIBRADOS_SNAP_HEAD
&& !snap_name
.empty()) {
116 std::cerr
<< "rbd: trying to access snapshot using both name and id."
121 at::Format::Formatter formatter
;
122 r
= utils::get_formatter(vm
, &formatter
);
127 librados::Rados rados
;
128 librados::IoCtx io_ctx
;
130 r
= utils::init_and_open_image(pool_name
, namespace_name
, image_name
, "", "",
131 true, &rados
, &io_ctx
, &image
);
136 if (!snap_name
.empty()) {
137 r
= image
.snap_set(snap_name
.c_str());
138 } else if (snap_id
!= LIBRADOS_SNAP_HEAD
) {
139 r
= image
.snap_set_by_id(snap_id
);
142 std::cerr
<< "rbd: snapshot does not exist." << std::endl
;
145 std::cerr
<< "rbd: error setting snapshot: " << cpp_strerror(r
)
150 r
= do_list_children(io_ctx
, image
, vm
["all"].as
<bool>(),
151 vm
["descendants"].as
<bool>(), formatter
.get());
153 std::cerr
<< "rbd: listing children failed: " << cpp_strerror(r
)
160 Shell::SwitchArguments
switched_arguments({"all", "a", "descendants"});
161 Shell::Action
action(
162 {"children"}, {}, "Display children of an image or its snapshot.", "",
163 &get_arguments
, &execute
);
165 } // namespace children
166 } // namespace action