1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "common/errno.h"
5 #include "common/Formatter.h"
6 #include "tools/rbd/ArgumentTypes.h"
7 #include "tools/rbd/Shell.h"
8 #include "tools/rbd/Utils.h"
9 #include "include/rbd_types.h"
10 #include "include/stringify.h"
12 #include <boost/program_options.hpp>
18 namespace at
= argument_types
;
19 namespace po
= boost::program_options
;
23 const std::string IMAGE_CACHE_STATE
= ".librbd/image_cache_state";
25 } // anonymous namespace
27 static int do_show_status(librados::IoCtx
& io_ctx
, const std::string
&image_name
,
28 librbd::Image
&image
, Formatter
*f
)
31 std::list
<librbd::image_watcher_t
> watchers
;
33 r
= image
.list_watchers(watchers
);
38 r
= image
.features(&features
);
43 librbd::image_migration_status_t migration_status
;
44 std::string source_spec
;
45 std::string source_pool_name
;
46 std::string dest_pool_name
;
47 std::string migration_state
;
48 if ((features
& RBD_FEATURE_MIGRATING
) != 0) {
49 r
= librbd::RBD().migration_status(io_ctx
, image_name
.c_str(),
51 sizeof(migration_status
));
53 std::cerr
<< "rbd: getting migration status failed: " << cpp_strerror(r
)
57 if (migration_status
.source_pool_id
>= 0) {
58 librados::IoCtx src_io_ctx
;
59 r
= librados::Rados(io_ctx
).ioctx_create2(migration_status
.source_pool_id
, src_io_ctx
);
61 source_pool_name
= stringify(migration_status
.source_pool_id
);
63 source_pool_name
= src_io_ctx
.get_pool_name();
66 r
= image
.get_migration_source_spec(&source_spec
);
68 std::cerr
<< "rbd: getting migration source spec failed: "
69 << cpp_strerror(r
) << std::endl
;
73 librados::IoCtx dst_io_ctx
;
74 r
= librados::Rados(io_ctx
).ioctx_create2(migration_status
.dest_pool_id
, dst_io_ctx
);
76 dest_pool_name
= stringify(migration_status
.dest_pool_id
);
78 dest_pool_name
= dst_io_ctx
.get_pool_name();
81 switch (migration_status
.state
) {
82 case RBD_IMAGE_MIGRATION_STATE_ERROR
:
83 migration_state
= "error";
85 case RBD_IMAGE_MIGRATION_STATE_PREPARING
:
86 migration_state
= "preparing";
88 case RBD_IMAGE_MIGRATION_STATE_PREPARED
:
89 migration_state
= "prepared";
91 case RBD_IMAGE_MIGRATION_STATE_EXECUTING
:
92 migration_state
= "executing";
94 case RBD_IMAGE_MIGRATION_STATE_EXECUTED
:
95 migration_state
= "executed";
97 case RBD_IMAGE_MIGRATION_STATE_ABORTING
:
98 migration_state
= "aborting";
101 migration_state
= "unknown";
106 std::string image_cache_str
;
107 if (features
& RBD_FEATURE_DIRTY_CACHE
) {
108 r
= image
.metadata_get(IMAGE_CACHE_STATE
, &image_cache_str
);
110 std::cerr
<< "rbd: getting image cache state failed: " << cpp_strerror(r
)
117 f
->open_object_section("status");
120 f
->open_array_section("watchers");
121 for (auto &watcher
: watchers
) {
122 f
->open_object_section("watcher");
123 f
->dump_string("address", watcher
.addr
);
124 f
->dump_unsigned("client", watcher
.id
);
125 f
->dump_unsigned("cookie", watcher
.cookie
);
128 f
->close_section(); // watchers
129 if (!migration_state
.empty()) {
130 f
->open_object_section("migration");
131 if (!source_spec
.empty()) {
132 f
->dump_string("source_spec", source_spec
);
134 f
->dump_string("source_pool_name", source_pool_name
);
135 f
->dump_string("source_pool_namespace",
136 migration_status
.source_pool_namespace
);
137 f
->dump_string("source_image_name", migration_status
.source_image_name
);
138 f
->dump_string("source_image_id", migration_status
.source_image_id
);
140 f
->dump_string("dest_pool_name", dest_pool_name
);
141 f
->dump_string("dest_pool_namespace",
142 migration_status
.dest_pool_namespace
);
143 f
->dump_string("dest_image_name", migration_status
.dest_image_name
);
144 f
->dump_string("dest_image_id", migration_status
.dest_image_id
);
145 f
->dump_string("state", migration_state
);
146 f
->dump_string("state_description", migration_status
.state_description
);
147 f
->close_section(); // migration
149 if (!image_cache_str
.empty()) {
150 f
->dump_string("image_cache_state", image_cache_str
);
153 if (watchers
.size()) {
154 std::cout
<< "Watchers:" << std::endl
;
155 for (auto &watcher
: watchers
) {
156 std::cout
<< "\twatcher=" << watcher
.addr
<< " client." << watcher
.id
157 << " cookie=" << watcher
.cookie
<< std::endl
;
160 std::cout
<< "Watchers: none" << std::endl
;
162 if (!migration_state
.empty()) {
163 if (!migration_status
.source_pool_namespace
.empty()) {
164 source_pool_name
+= ("/" + migration_status
.source_pool_namespace
);
166 if (!migration_status
.dest_pool_namespace
.empty()) {
167 dest_pool_name
+= ("/" + migration_status
.dest_pool_namespace
);
170 std::cout
<< "Migration:" << std::endl
;
171 std::cout
<< "\tsource: ";
172 if (!source_spec
.empty()) {
173 std::cout
<< source_spec
;
175 std::cout
<< source_pool_name
<< "/"
176 << migration_status
.source_image_name
;
177 if (!migration_status
.source_image_id
.empty()) {
178 std::cout
<< " (" << migration_status
.source_image_id
<< ")";
181 std::cout
<< std::endl
;
182 std::cout
<< "\tdestination: " << dest_pool_name
<< "/"
183 << migration_status
.dest_image_name
<< " ("
184 << migration_status
.dest_image_id
<< ")" << std::endl
;
185 std::cout
<< "\tstate: " << migration_state
;
186 if (!migration_status
.state_description
.empty()) {
187 std::cout
<< " (" << migration_status
.state_description
<< ")";
189 std::cout
<< std::endl
;
192 if (!image_cache_str
.empty()) {
193 std::cout
<< "Image cache state: " << image_cache_str
<< std::endl
;
198 f
->close_section(); // status
205 void get_arguments(po::options_description
*positional
,
206 po::options_description
*options
) {
207 at::add_image_spec_options(positional
, options
, at::ARGUMENT_MODIFIER_NONE
);
208 at::add_format_options(options
);
211 int execute(const po::variables_map
&vm
,
212 const std::vector
<std::string
> &ceph_global_init_args
) {
213 size_t arg_index
= 0;
214 std::string pool_name
;
215 std::string namespace_name
;
216 std::string image_name
;
217 std::string snap_name
;
218 int r
= utils::get_pool_image_snapshot_names(
219 vm
, at::ARGUMENT_MODIFIER_NONE
, &arg_index
, &pool_name
, &namespace_name
,
220 &image_name
, &snap_name
, true, utils::SNAPSHOT_PRESENCE_NONE
,
221 utils::SPEC_VALIDATION_NONE
);
226 at::Format::Formatter formatter
;
227 r
= utils::get_formatter(vm
, &formatter
);
232 librados::Rados rados
;
233 librados::IoCtx io_ctx
;
235 r
= utils::init_and_open_image(pool_name
, namespace_name
, image_name
, "", "",
236 true, &rados
, &io_ctx
, &image
);
241 r
= do_show_status(io_ctx
, image_name
, image
, formatter
.get());
243 std::cerr
<< "rbd: show status failed: " << cpp_strerror(r
) << std::endl
;
249 Shell::Action
action(
250 {"status"}, {}, "Show the status of this image.", "", &get_arguments
,
253 } // namespace status
254 } // namespace action