]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd/action/ImageMeta.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / tools / rbd / action / ImageMeta.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 "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"
9 #include "common/TextTable.h"
10 #include <iostream>
11 #include <boost/program_options.hpp>
12
13 namespace rbd {
14 namespace action {
15 namespace image_meta {
16
17 namespace at = argument_types;
18 namespace po = boost::program_options;
19
20 namespace {
21
22 void add_key_option(po::options_description *positional) {
23 positional->add_options()
24 ("key", "image meta key");
25 }
26
27 int get_key(const po::variables_map &vm, size_t *arg_index,
28 std::string *key) {
29 *key = utils::get_positional_argument(vm, *arg_index);
30 if (key->empty()) {
31 std::cerr << "rbd: metadata key was not specified" << std::endl;
32 return -EINVAL;
33 } else {
34 ++(*arg_index);
35 }
36 return 0;
37 }
38
39 const uint32_t MAX_KEYS = 64;
40
41 } // anonymous namespace
42
43 static int do_metadata_list(librbd::Image& image, Formatter *f)
44 {
45 int r;
46 TextTable tbl;
47
48 size_t count = 0;
49 std::string last_key;
50 bool more_results = true;
51 while (more_results) {
52 std::map<std::string, bufferlist> pairs;
53 r = image.metadata_list(last_key, MAX_KEYS, &pairs);
54 if (r < 0) {
55 std::cerr << "failed to list metadata of image : " << cpp_strerror(r)
56 << std::endl;
57 return r;
58 }
59
60 more_results = (pairs.size() == MAX_KEYS);
61 if (!pairs.empty()) {
62 if (count == 0) {
63 if (f) {
64 f->open_object_section("metadatas");
65 } else {
66 tbl.define_column("Key", TextTable::LEFT, TextTable::LEFT);
67 tbl.define_column("Value", TextTable::LEFT, TextTable::LEFT);
68 }
69 }
70
71 last_key = pairs.rbegin()->first;
72 count += pairs.size();
73
74 for (auto kv : pairs) {
75 std::string val(kv.second.c_str(), kv.second.length());
76 if (f) {
77 f->dump_string(kv.first.c_str(), val.c_str());
78 } else {
79 tbl << kv.first << val << TextTable::endrow;
80 }
81 }
82 }
83 }
84
85 if (f == nullptr) {
86 bool single = (count == 1);
87 std::cout << "There " << (single ? "is" : "are") << " " << count << " "
88 << (single ? "metadatum" : "metadata") << " on this image"
89 << (count == 0 ? "." : ":") << std::endl;
90 }
91
92 if (count > 0) {
93 if (f) {
94 f->close_section();
95 f->flush(std::cout);
96 } else {
97 std::cout << std::endl << tbl;
98 }
99 }
100 return 0;
101 }
102
103 static int do_metadata_set(librbd::Image& image, std::string &key,
104 std::string &value)
105 {
106 int r = image.metadata_set(key, value);
107 if (r < 0) {
108 std::cerr << "failed to set metadata " << key << " of image : "
109 << cpp_strerror(r) << std::endl;
110 }
111 return r;
112 }
113
114 static int do_metadata_remove(librbd::Image& image, std::string &key)
115 {
116 int r = image.metadata_remove(key);
117 if (r == -ENOENT) {
118 std::cerr << "rbd: no existing metadata key " << key << " of image : "
119 << cpp_strerror(r) << std::endl;
120 } else if(r < 0) {
121 std::cerr << "failed to remove metadata " << key << " of image : "
122 << cpp_strerror(r) << std::endl;
123 }
124 return r;
125 }
126
127 static int do_metadata_get(librbd::Image& image, std::string &key)
128 {
129 std::string s;
130 int r = image.metadata_get(key, &s);
131 if (r < 0) {
132 std::cerr << "failed to get metadata " << key << " of image : "
133 << cpp_strerror(r) << std::endl;
134 return r;
135 }
136 std::cout << s << std::endl;
137 return r;
138 }
139
140 void get_list_arguments(po::options_description *positional,
141 po::options_description *options) {
142 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
143 at::add_format_options(options);
144 }
145
146 int execute_list(const po::variables_map &vm,
147 const std::vector<std::string> &ceph_global_init_args) {
148 size_t arg_index = 0;
149 std::string pool_name;
150 std::string namespace_name;
151 std::string image_name;
152 std::string snap_name;
153 int r = utils::get_pool_image_snapshot_names(
154 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
155 &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_NONE,
156 utils::SPEC_VALIDATION_NONE);
157 if (r < 0) {
158 return r;
159 }
160
161 at::Format::Formatter formatter;
162 r = utils::get_formatter(vm, &formatter);
163 if (r < 0) {
164 return r;
165 }
166
167 librados::Rados rados;
168 librados::IoCtx io_ctx;
169 librbd::Image image;
170 r = utils::init_and_open_image(pool_name, namespace_name, image_name, "", "",
171 false, &rados, &io_ctx, &image);
172 if (r < 0) {
173 return r;
174 }
175
176 r = do_metadata_list(image, formatter.get());
177 if (r < 0) {
178 std::cerr << "rbd: listing metadata failed: " << cpp_strerror(r)
179 << std::endl;
180 return r;
181 }
182 return 0;
183 }
184
185 void get_get_arguments(po::options_description *positional,
186 po::options_description *options) {
187 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
188 add_key_option(positional);
189 }
190
191 int execute_get(const po::variables_map &vm,
192 const std::vector<std::string> &ceph_global_init_args) {
193 size_t arg_index = 0;
194 std::string pool_name;
195 std::string namespace_name;
196 std::string image_name;
197 std::string snap_name;
198 int r = utils::get_pool_image_snapshot_names(
199 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
200 &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_NONE,
201 utils::SPEC_VALIDATION_NONE);
202 if (r < 0) {
203 return r;
204 }
205
206 std::string key;
207 r = get_key(vm, &arg_index, &key);
208 if (r < 0) {
209 return r;
210 }
211
212 librados::Rados rados;
213 librados::IoCtx io_ctx;
214 librbd::Image image;
215 r = utils::init_and_open_image(pool_name, namespace_name, image_name, "", "",
216 false, &rados, &io_ctx, &image);
217 if (r < 0) {
218 return r;
219 }
220
221 r = do_metadata_get(image, key);
222 if (r < 0) {
223 std::cerr << "rbd: getting metadata failed: " << cpp_strerror(r)
224 << std::endl;
225 return r;
226 }
227 return 0;
228 }
229
230 void get_set_arguments(po::options_description *positional,
231 po::options_description *options) {
232 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
233 add_key_option(positional);
234 positional->add_options()
235 ("value", "image meta value");
236 }
237
238 int execute_set(const po::variables_map &vm,
239 const std::vector<std::string> &ceph_global_init_args) {
240 size_t arg_index = 0;
241 std::string pool_name;
242 std::string namespace_name;
243 std::string image_name;
244 std::string snap_name;
245 int r = utils::get_pool_image_snapshot_names(
246 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
247 &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_NONE,
248 utils::SPEC_VALIDATION_NONE);
249 if (r < 0) {
250 return r;
251 }
252
253 std::string key;
254 r = get_key(vm, &arg_index, &key);
255 if (r < 0) {
256 return r;
257 }
258
259 std::string value = utils::get_positional_argument(vm, 2);
260 if (value.empty()) {
261 std::cerr << "rbd: metadata value was not specified" << std::endl;
262 return -EINVAL;
263 }
264
265 librados::Rados rados;
266 librados::IoCtx io_ctx;
267 librbd::Image image;
268 r = utils::init_and_open_image(pool_name, namespace_name, image_name, "", "",
269 false, &rados, &io_ctx, &image);
270 if (r < 0) {
271 return r;
272 }
273
274 r = do_metadata_set(image, key, value);
275 if (r < 0) {
276 std::cerr << "rbd: setting metadata failed: " << cpp_strerror(r)
277 << std::endl;
278 return r;
279 }
280 return 0;
281 }
282
283 void get_remove_arguments(po::options_description *positional,
284 po::options_description *options) {
285 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
286 add_key_option(positional);
287 }
288
289 int execute_remove(const po::variables_map &vm,
290 const std::vector<std::string> &ceph_global_init_args) {
291 size_t arg_index = 0;
292 std::string pool_name;
293 std::string namespace_name;
294 std::string image_name;
295 std::string snap_name;
296 int r = utils::get_pool_image_snapshot_names(
297 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &namespace_name,
298 &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_NONE,
299 utils::SPEC_VALIDATION_NONE);
300 if (r < 0) {
301 return r;
302 }
303
304 std::string key;
305 r = get_key(vm, &arg_index, &key);
306 if (r < 0) {
307 return r;
308 }
309
310 librados::Rados rados;
311 librados::IoCtx io_ctx;
312 librbd::Image image;
313 r = utils::init_and_open_image(pool_name, namespace_name, image_name, "", "",
314 false, &rados, &io_ctx, &image);
315 if (r < 0) {
316 return r;
317 }
318
319 r = do_metadata_remove(image, key);
320 if (r < 0) {
321 std::cerr << "rbd: removing metadata failed: " << cpp_strerror(r)
322 << std::endl;
323 return r;
324 }
325 return 0;
326 }
327
328 Shell::Action action_list(
329 {"image-meta", "list"}, {"image-meta", "ls"}, "Image metadata list keys with values.", "",
330 &get_list_arguments, &execute_list);
331 Shell::Action action_get(
332 {"image-meta", "get"}, {},
333 "Image metadata get the value associated with the key.", "",
334 &get_get_arguments, &execute_get);
335 Shell::Action action_set(
336 {"image-meta", "set"}, {}, "Image metadata set key with value.", "",
337 &get_set_arguments, &execute_set);
338 Shell::Action action_remove(
339 {"image-meta", "remove"}, {"image-meta", "rm"},
340 "Image metadata remove the key and value associated.", "",
341 &get_remove_arguments, &execute_remove);
342
343 } // namespace image_meta
344 } // namespace action
345 } // namespace rbd