]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd/action/Status.cc
import ceph pacific 16.2.5
[ceph.git] / ceph / src / tools / rbd / action / Status.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
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"
11 #include <iostream>
12 #include <boost/program_options.hpp>
13
14 namespace rbd {
15 namespace action {
16 namespace status {
17
18 namespace at = argument_types;
19 namespace po = boost::program_options;
20
21 namespace {
22
23 const std::string IMAGE_CACHE_STATE = ".librbd/image_cache_state";
24
25 } // anonymous namespace
26
27 static int do_show_status(librados::IoCtx& io_ctx, const std::string &image_name,
28 librbd::Image &image, Formatter *f)
29 {
30 int r;
31 std::list<librbd::image_watcher_t> watchers;
32
33 r = image.list_watchers(watchers);
34 if (r < 0)
35 return r;
36
37 uint64_t features;
38 r = image.features(&features);
39 if (r < 0) {
40 return r;
41 }
42
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(),
50 &migration_status,
51 sizeof(migration_status));
52 if (r < 0) {
53 std::cerr << "rbd: getting migration status failed: " << cpp_strerror(r)
54 << std::endl;
55 // not fatal
56 } else {
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);
60 if (r < 0) {
61 source_pool_name = stringify(migration_status.source_pool_id);
62 } else {
63 source_pool_name = src_io_ctx.get_pool_name();
64 }
65 } else {
66 r = image.get_migration_source_spec(&source_spec);
67 if (r < 0) {
68 std::cerr << "rbd: getting migration source spec failed: "
69 << cpp_strerror(r) << std::endl;
70 }
71 }
72
73 librados::IoCtx dst_io_ctx;
74 r = librados::Rados(io_ctx).ioctx_create2(migration_status.dest_pool_id, dst_io_ctx);
75 if (r < 0) {
76 dest_pool_name = stringify(migration_status.dest_pool_id);
77 } else {
78 dest_pool_name = dst_io_ctx.get_pool_name();
79 }
80
81 switch (migration_status.state) {
82 case RBD_IMAGE_MIGRATION_STATE_ERROR:
83 migration_state = "error";
84 break;
85 case RBD_IMAGE_MIGRATION_STATE_PREPARING:
86 migration_state = "preparing";
87 break;
88 case RBD_IMAGE_MIGRATION_STATE_PREPARED:
89 migration_state = "prepared";
90 break;
91 case RBD_IMAGE_MIGRATION_STATE_EXECUTING:
92 migration_state = "executing";
93 break;
94 case RBD_IMAGE_MIGRATION_STATE_EXECUTED:
95 migration_state = "executed";
96 break;
97 case RBD_IMAGE_MIGRATION_STATE_ABORTING:
98 migration_state = "aborting";
99 break;
100 default:
101 migration_state = "unknown";
102 }
103 }
104 }
105
106 std::string image_cache_str;
107 if (features & RBD_FEATURE_DIRTY_CACHE) {
108 r = image.metadata_get(IMAGE_CACHE_STATE, &image_cache_str);
109 if (r < 0) {
110 std::cerr << "rbd: getting image cache state failed: " << cpp_strerror(r)
111 << std::endl;
112 // not fatal
113 }
114 }
115
116 if (f)
117 f->open_object_section("status");
118
119 if (f) {
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);
126 f->close_section();
127 }
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);
133 } else {
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);
139 }
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
148 }
149 if (!image_cache_str.empty()) {
150 f->dump_string("image_cache_state", image_cache_str);
151 }
152 } else {
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;
158 }
159 } else {
160 std::cout << "Watchers: none" << std::endl;
161 }
162 if (!migration_state.empty()) {
163 if (!migration_status.source_pool_namespace.empty()) {
164 source_pool_name += ("/" + migration_status.source_pool_namespace);
165 }
166 if (!migration_status.dest_pool_namespace.empty()) {
167 dest_pool_name += ("/" + migration_status.dest_pool_namespace);
168 }
169
170 std::cout << "Migration:" << std::endl;
171 std::cout << "\tsource: ";
172 if (!source_spec.empty()) {
173 std::cout << source_spec;
174 } else {
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 << ")";
179 }
180 }
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 << ")";
188 }
189 std::cout << std::endl;
190 }
191
192 if (!image_cache_str.empty()) {
193 std::cout << "Image cache state: " << image_cache_str << std::endl;
194 }
195 }
196
197 if (f) {
198 f->close_section(); // status
199 f->flush(std::cout);
200 }
201
202 return 0;
203 }
204
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);
209 }
210
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);
222 if (r < 0) {
223 return r;
224 }
225
226 at::Format::Formatter formatter;
227 r = utils::get_formatter(vm, &formatter);
228 if (r < 0) {
229 return r;
230 }
231
232 librados::Rados rados;
233 librados::IoCtx io_ctx;
234 librbd::Image image;
235 r = utils::init_and_open_image(pool_name, namespace_name, image_name, "", "",
236 true, &rados, &io_ctx, &image);
237 if (r < 0) {
238 return r;
239 }
240
241 r = do_show_status(io_ctx, image_name, image, formatter.get());
242 if (r < 0) {
243 std::cerr << "rbd: show status failed: " << cpp_strerror(r) << std::endl;
244 return r;
245 }
246 return 0;
247 }
248
249 Shell::Action action(
250 {"status"}, {}, "Show the status of this image.", "", &get_arguments,
251 &execute);
252
253 } // namespace status
254 } // namespace action
255 } // namespace rbd