]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd/action/ImageMeta.cc
update sources to v12.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, 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