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