]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd/action/Snap.cc
update sources to 12.2.8
[ceph.git] / ceph / src / tools / rbd / action / Snap.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 "include/types.h"
8 #include "include/stringify.h"
9 #include "common/errno.h"
10 #include "common/Formatter.h"
11 #include "common/TextTable.h"
12 #include <iostream>
13 #include <boost/program_options.hpp>
14
15 namespace rbd {
16 namespace action {
17 namespace snap {
18
19 namespace at = argument_types;
20 namespace po = boost::program_options;
21
22 int do_list_snaps(librbd::Image& image, Formatter *f)
23 {
24 std::vector<librbd::snap_info_t> snaps;
25 TextTable t;
26 int r;
27
28 r = image.snap_list(snaps);
29 if (r < 0)
30 return r;
31
32 if (f) {
33 f->open_array_section("snapshots");
34 } else {
35 t.define_column("SNAPID", TextTable::RIGHT, TextTable::RIGHT);
36 t.define_column("NAME", TextTable::LEFT, TextTable::LEFT);
37 t.define_column("SIZE", TextTable::RIGHT, TextTable::RIGHT);
38 t.define_column("TIMESTAMP", TextTable::LEFT, TextTable::LEFT);
39 }
40
41 for (std::vector<librbd::snap_info_t>::iterator s = snaps.begin();
42 s != snaps.end(); ++s) {
43 struct timespec timestamp;
44 image.snap_get_timestamp(s->id, &timestamp);
45 string tt_str = "";
46 if(timestamp.tv_sec != 0) {
47 time_t tt = timestamp.tv_sec;
48 tt_str = ctime(&tt);
49 tt_str = tt_str.substr(0, tt_str.length() - 1);
50 }
51
52 if (f) {
53 f->open_object_section("snapshot");
54 f->dump_unsigned("id", s->id);
55 f->dump_string("name", s->name);
56 f->dump_unsigned("size", s->size);
57 f->dump_string("timestamp", tt_str);
58 f->close_section();
59 } else {
60 t << s->id << s->name << stringify(byte_u_t(s->size)) << tt_str
61 << TextTable::endrow;
62 }
63 }
64
65 if (f) {
66 f->close_section();
67 f->flush(std::cout);
68 } else if (snaps.size()) {
69 std::cout << t;
70 }
71
72 return 0;
73 }
74
75 int do_add_snap(librbd::Image& image, const char *snapname)
76 {
77 int r = image.snap_create(snapname);
78 if (r < 0)
79 return r;
80
81 return 0;
82 }
83
84 int do_remove_snap(librbd::Image& image, const char *snapname, bool force,
85 bool no_progress)
86 {
87 uint32_t flags = force? RBD_SNAP_REMOVE_FORCE : 0;
88 int r = 0;
89 utils::ProgressContext pc("Removing snap", no_progress);
90
91 r = image.snap_remove2(snapname, flags, pc);
92 if (r < 0) {
93 pc.fail();
94 return r;
95 }
96
97 pc.finish();
98 return 0;
99 }
100
101 int do_rollback_snap(librbd::Image& image, const char *snapname,
102 bool no_progress)
103 {
104 utils::ProgressContext pc("Rolling back to snapshot", no_progress);
105 int r = image.snap_rollback_with_progress(snapname, pc);
106 if (r < 0) {
107 pc.fail();
108 return r;
109 }
110 pc.finish();
111 return 0;
112 }
113
114 int do_purge_snaps(librbd::Image& image, bool no_progress)
115 {
116 utils::ProgressContext pc("Removing all snapshots", no_progress);
117 std::vector<librbd::snap_info_t> snaps;
118 bool is_protected = false;
119 int r = image.snap_list(snaps);
120 if (r < 0) {
121 pc.fail();
122 return r;
123 } else if (0 == snaps.size()) {
124 return 0;
125 } else {
126 for (size_t i = 0; i < snaps.size(); ++i) {
127 r = image.snap_is_protected(snaps[i].name.c_str(), &is_protected);
128 if (r < 0) {
129 pc.fail();
130 return r;
131 } else if (is_protected == true) {
132 pc.fail();
133 std::cerr << "\r" << "rbd: snapshot '" << snaps[i].name.c_str()
134 << "' is protected from removal." << std::endl;
135 return -EBUSY;
136 }
137 }
138 for (size_t i = 0; i < snaps.size(); ++i) {
139 r = image.snap_remove(snaps[i].name.c_str());
140 if (r < 0) {
141 pc.fail();
142 return r;
143 }
144 pc.update_progress(i + 1, snaps.size());
145 }
146
147 pc.finish();
148 return 0;
149 }
150 }
151
152 int do_protect_snap(librbd::Image& image, const char *snapname)
153 {
154 int r = image.snap_protect(snapname);
155 if (r < 0)
156 return r;
157
158 return 0;
159 }
160
161 int do_unprotect_snap(librbd::Image& image, const char *snapname)
162 {
163 int r = image.snap_unprotect(snapname);
164 if (r < 0)
165 return r;
166
167 return 0;
168 }
169
170 int do_set_limit(librbd::Image& image, uint64_t limit)
171 {
172 return image.snap_set_limit(limit);
173 }
174
175 int do_clear_limit(librbd::Image& image)
176 {
177 return image.snap_set_limit(UINT64_MAX);
178 }
179
180 void get_list_arguments(po::options_description *positional,
181 po::options_description *options) {
182 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
183 at::add_image_id_option(options);
184 at::add_format_options(options);
185 }
186
187 int execute_list(const po::variables_map &vm) {
188 size_t arg_index = 0;
189 std::string pool_name;
190 std::string image_name;
191 std::string snap_name;
192 std::string image_id;
193
194 if (vm.count(at::IMAGE_ID)) {
195 image_id = vm[at::IMAGE_ID].as<std::string>();
196 }
197
198 bool has_image_spec = utils::check_if_image_spec_present(
199 vm, at::ARGUMENT_MODIFIER_NONE, arg_index);
200
201 if (!image_id.empty() && has_image_spec) {
202 std::cerr << "rbd: trying to access image using both name and id. "
203 << std::endl;
204 return -EINVAL;
205 }
206
207 int r;
208 if (image_id.empty()) {
209 r = utils::get_pool_image_snapshot_names(vm, at::ARGUMENT_MODIFIER_NONE,
210 &arg_index, &pool_name,
211 &image_name, &snap_name,
212 utils::SNAPSHOT_PRESENCE_NONE,
213 utils::SPEC_VALIDATION_NONE);
214 } else {
215 r = utils::get_pool_snapshot_names(vm, at::ARGUMENT_MODIFIER_NONE,
216 &arg_index, &pool_name, &snap_name,
217 utils::SNAPSHOT_PRESENCE_NONE,
218 utils::SPEC_VALIDATION_NONE);
219 }
220 if (r < 0) {
221 return r;
222 }
223
224 at::Format::Formatter formatter;
225 r = utils::get_formatter(vm, &formatter);
226 if (r < 0) {
227 return r;
228 }
229
230 librados::Rados rados;
231 librados::IoCtx io_ctx;
232 librbd::Image image;
233 r = utils::init_and_open_image(pool_name, image_name, image_id, "", true,
234 &rados, &io_ctx, &image);
235 if (r < 0) {
236 return r;
237 }
238
239 r = do_list_snaps(image, formatter.get());
240 if (r < 0) {
241 cerr << "rbd: failed to list snapshots: " << cpp_strerror(r)
242 << std::endl;
243 return r;
244 }
245 return 0;
246 }
247
248 void get_create_arguments(po::options_description *positional,
249 po::options_description *options) {
250 at::add_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
251 }
252
253 int execute_create(const po::variables_map &vm) {
254 size_t arg_index = 0;
255 std::string pool_name;
256 std::string image_name;
257 std::string snap_name;
258 int r = utils::get_pool_image_snapshot_names(
259 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
260 &snap_name, utils::SNAPSHOT_PRESENCE_REQUIRED, utils::SPEC_VALIDATION_SNAP);
261 if (r < 0) {
262 return r;
263 }
264
265 librados::Rados rados;
266 librados::IoCtx io_ctx;
267 librbd::Image image;
268 r = utils::init_and_open_image(pool_name, image_name, "", "", false, &rados,
269 &io_ctx, &image);
270 if (r < 0) {
271 return r;
272 }
273
274 r = do_add_snap(image, snap_name.c_str());
275 if (r < 0) {
276 cerr << "rbd: failed to create snapshot: " << 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_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
286 at::add_no_progress_option(options);
287 at::add_image_id_option(options);
288
289 options->add_options()
290 ("force", po::bool_switch(), "flatten children and unprotect snapshot if needed.");
291 }
292
293 int execute_remove(const po::variables_map &vm) {
294 size_t arg_index = 0;
295 std::string pool_name;
296 std::string image_name;
297 std::string snap_name;
298 std::string image_id;
299 bool force = vm["force"].as<bool>();
300
301 if (vm.count(at::IMAGE_ID)) {
302 image_id = vm[at::IMAGE_ID].as<std::string>();
303 }
304
305 bool has_image_spec = utils::check_if_image_spec_present(
306 vm, at::ARGUMENT_MODIFIER_NONE, arg_index);
307
308 if (!image_id.empty() && has_image_spec) {
309 std::cerr << "rbd: trying to access image using both name and id. "
310 << std::endl;
311 return -EINVAL;
312 }
313
314 int r;
315 if (image_id.empty()) {
316 r = utils::get_pool_image_snapshot_names(vm, at::ARGUMENT_MODIFIER_NONE,
317 &arg_index, &pool_name,
318 &image_name, &snap_name,
319 utils::SNAPSHOT_PRESENCE_REQUIRED,
320 utils::SPEC_VALIDATION_NONE);
321 } else {
322 r = utils::get_pool_snapshot_names(vm, at::ARGUMENT_MODIFIER_NONE,
323 &arg_index, &pool_name, &snap_name,
324 utils::SNAPSHOT_PRESENCE_REQUIRED,
325 utils::SPEC_VALIDATION_NONE);
326 }
327 if (r < 0) {
328 return r;
329 }
330
331 librados::Rados rados;
332 librados::IoCtx io_ctx;
333 librbd::Image image;
334 r = utils::init(pool_name, &rados, &io_ctx);
335 if (r < 0) {
336 return r;
337 }
338
339 io_ctx.set_osdmap_full_try();
340 if (image_id.empty()) {
341 r = utils::open_image(io_ctx, image_name, false, &image);
342 } else {
343 r = utils::open_image_by_id(io_ctx, image_id, false, &image);
344 }
345 if (r < 0) {
346 return r;
347 }
348
349 r = do_remove_snap(image, snap_name.c_str(), force, vm[at::NO_PROGRESS].as<bool>());
350 if (r < 0) {
351 if (r == -EBUSY) {
352 std::cerr << "rbd: snapshot '" << snap_name << "' "
353 << "is protected from removal." << std::endl;
354 } else {
355 std::cerr << "rbd: failed to remove snapshot: " << cpp_strerror(r)
356 << std::endl;
357 }
358 return r;
359 }
360 return 0;
361 }
362
363 void get_purge_arguments(po::options_description *positional,
364 po::options_description *options) {
365 at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
366 at::add_image_id_option(options);
367 at::add_no_progress_option(options);
368 }
369
370 int execute_purge(const po::variables_map &vm) {
371 size_t arg_index = 0;
372 std::string pool_name;
373 std::string image_name;
374 std::string snap_name;
375 std::string image_id;
376
377 if (vm.count(at::IMAGE_ID)) {
378 image_id = vm[at::IMAGE_ID].as<std::string>();
379 }
380
381 bool has_image_spec = utils::check_if_image_spec_present(
382 vm, at::ARGUMENT_MODIFIER_NONE, arg_index);
383
384 if (!image_id.empty() && has_image_spec) {
385 std::cerr << "rbd: trying to access image using both name and id. "
386 << std::endl;
387 return -EINVAL;
388 }
389
390 int r;
391 if (image_id.empty()) {
392 r = utils::get_pool_image_snapshot_names(vm, at::ARGUMENT_MODIFIER_NONE,
393 &arg_index, &pool_name,
394 &image_name, &snap_name,
395 utils::SNAPSHOT_PRESENCE_NONE,
396 utils::SPEC_VALIDATION_NONE);
397 } else {
398 r = utils::get_pool_snapshot_names(vm, at::ARGUMENT_MODIFIER_NONE,
399 &arg_index, &pool_name, &snap_name,
400 utils::SNAPSHOT_PRESENCE_NONE,
401 utils::SPEC_VALIDATION_NONE);
402 }
403 if (r < 0) {
404 return r;
405 }
406
407 librados::Rados rados;
408 librados::IoCtx io_ctx;
409 librbd::Image image;
410 r = utils::init(pool_name, &rados, &io_ctx);
411 if (r < 0) {
412 return r;
413 }
414
415 io_ctx.set_osdmap_full_try();
416 if (image_id.empty()) {
417 r = utils::open_image(io_ctx, image_name, false, &image);
418 } else {
419 r = utils::open_image_by_id(io_ctx, image_id, false, &image);
420 }
421 if (r < 0) {
422 return r;
423 }
424
425 r = do_purge_snaps(image, vm[at::NO_PROGRESS].as<bool>());
426 if (r < 0) {
427 if (r != -EBUSY) {
428 std::cerr << "rbd: removing snaps failed: " << cpp_strerror(r)
429 << std::endl;
430 }
431 return r;
432 }
433 return 0;
434 }
435
436 void get_rollback_arguments(po::options_description *positional,
437 po::options_description *options) {
438 at::add_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
439 at::add_no_progress_option(options);
440 }
441
442 int execute_rollback(const po::variables_map &vm) {
443 size_t arg_index = 0;
444 std::string pool_name;
445 std::string image_name;
446 std::string snap_name;
447 int r = utils::get_pool_image_snapshot_names(
448 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
449 &snap_name, utils::SNAPSHOT_PRESENCE_REQUIRED, utils::SPEC_VALIDATION_NONE);
450 if (r < 0) {
451 return r;
452 }
453
454 librados::Rados rados;
455 librados::IoCtx io_ctx;
456 librbd::Image image;
457 r = utils::init_and_open_image(pool_name, image_name, "", "", false, &rados,
458 &io_ctx, &image);
459 if (r < 0) {
460 return r;
461 }
462
463 r = do_rollback_snap(image, snap_name.c_str(),
464 vm[at::NO_PROGRESS].as<bool>());
465 if (r < 0) {
466 std::cerr << "rbd: rollback failed: " << cpp_strerror(r) << std::endl;
467 return r;
468 }
469 return 0;
470 }
471
472 void get_protect_arguments(po::options_description *positional,
473 po::options_description *options) {
474 at::add_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
475 }
476
477 int execute_protect(const po::variables_map &vm) {
478 size_t arg_index = 0;
479 std::string pool_name;
480 std::string image_name;
481 std::string snap_name;
482 int r = utils::get_pool_image_snapshot_names(
483 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
484 &snap_name, utils::SNAPSHOT_PRESENCE_REQUIRED, utils::SPEC_VALIDATION_NONE);
485 if (r < 0) {
486 return r;
487 }
488
489 librados::Rados rados;
490 librados::IoCtx io_ctx;
491 librbd::Image image;
492 r = utils::init_and_open_image(pool_name, image_name, "", "", false, &rados,
493 &io_ctx, &image);
494 if (r < 0) {
495 return r;
496 }
497
498 bool is_protected = false;
499 r = image.snap_is_protected(snap_name.c_str(), &is_protected);
500 if (r < 0) {
501 std::cerr << "rbd: protecting snap failed: " << cpp_strerror(r)
502 << std::endl;
503 return r;
504 } else if (is_protected) {
505 std::cerr << "rbd: snap is already protected" << std::endl;
506 return -EBUSY;
507 }
508
509 r = do_protect_snap(image, snap_name.c_str());
510 if (r < 0) {
511 std::cerr << "rbd: protecting snap failed: " << cpp_strerror(r)
512 << std::endl;
513 return r;
514 }
515 return 0;
516 }
517
518 void get_unprotect_arguments(po::options_description *positional,
519 po::options_description *options) {
520 at::add_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE);
521 at::add_image_id_option(options);
522 }
523
524 int execute_unprotect(const po::variables_map &vm) {
525 size_t arg_index = 0;
526 std::string pool_name;
527 std::string image_name;
528 std::string snap_name;
529 std::string image_id;
530
531 if (vm.count(at::IMAGE_ID)) {
532 image_id = vm[at::IMAGE_ID].as<std::string>();
533 }
534
535 bool has_image_spec = utils::check_if_image_spec_present(
536 vm, at::ARGUMENT_MODIFIER_NONE, arg_index);
537
538 if (!image_id.empty() && has_image_spec) {
539 std::cerr << "rbd: trying to access image using both name and id. "
540 << std::endl;
541 return -EINVAL;
542 }
543
544 int r;
545 if (image_id.empty()) {
546 r = utils::get_pool_image_snapshot_names(vm, at::ARGUMENT_MODIFIER_NONE,
547 &arg_index, &pool_name,
548 &image_name, &snap_name,
549 utils::SNAPSHOT_PRESENCE_REQUIRED,
550 utils::SPEC_VALIDATION_NONE);
551 } else {
552 r = utils::get_pool_snapshot_names(vm, at::ARGUMENT_MODIFIER_NONE,
553 &arg_index, &pool_name, &snap_name,
554 utils::SNAPSHOT_PRESENCE_REQUIRED,
555 utils::SPEC_VALIDATION_NONE);
556 }
557 if (r < 0) {
558 return r;
559 }
560
561 librados::Rados rados;
562 librados::IoCtx io_ctx;
563 librbd::Image image;
564 r = utils::init(pool_name, &rados, &io_ctx);
565 if (r < 0) {
566 return r;
567 }
568
569 io_ctx.set_osdmap_full_try();
570 if (image_id.empty()) {
571 r = utils::open_image(io_ctx, image_name, false, &image);
572 } else {
573 r = utils::open_image_by_id(io_ctx, image_id, false, &image);
574 }
575 if (r < 0) {
576 return r;
577 }
578
579 bool is_protected = false;
580 r = image.snap_is_protected(snap_name.c_str(), &is_protected);
581 if (r < 0) {
582 std::cerr << "rbd: unprotecting snap failed: " << cpp_strerror(r)
583 << std::endl;
584 return r;
585 } else if (!is_protected) {
586 std::cerr << "rbd: snap is already unprotected" << std::endl;
587 return -EINVAL;
588 }
589
590 r = do_unprotect_snap(image, snap_name.c_str());
591 if (r < 0) {
592 std::cerr << "rbd: unprotecting snap failed: " << cpp_strerror(r)
593 << std::endl;
594 return r;
595 }
596 return 0;
597 }
598
599 void get_set_limit_arguments(po::options_description *pos,
600 po::options_description *opt) {
601 at::add_image_spec_options(pos, opt, at::ARGUMENT_MODIFIER_NONE);
602 at::add_limit_option(opt);
603 }
604
605 int execute_set_limit(const po::variables_map &vm) {
606 size_t arg_index = 0;
607 std::string pool_name;
608 std::string image_name;
609 std::string snap_name;
610 uint64_t limit;
611
612 int r = utils::get_pool_image_snapshot_names(
613 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
614 &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE);
615 if (r < 0) {
616 return r;
617 }
618
619 if (vm.count(at::LIMIT)) {
620 limit = vm[at::LIMIT].as<uint64_t>();
621 } else {
622 std::cerr << "rbd: must specify --limit <num>" << std::endl;
623 return -ERANGE;
624 }
625
626 librados::Rados rados;
627 librados::IoCtx io_ctx;
628 librbd::Image image;
629 r = utils::init_and_open_image(pool_name, image_name, "", "", false, &rados,
630 &io_ctx, &image);
631 if (r < 0) {
632 return r;
633 }
634
635 r = do_set_limit(image, limit);
636 if (r < 0) {
637 std::cerr << "rbd: setting snapshot limit failed: " << cpp_strerror(r)
638 << std::endl;
639 return r;
640 }
641 return 0;
642 }
643
644 void get_clear_limit_arguments(po::options_description *pos,
645 po::options_description *opt) {
646 at::add_image_spec_options(pos, opt, at::ARGUMENT_MODIFIER_NONE);
647 }
648
649 int execute_clear_limit(const po::variables_map &vm) {
650 size_t arg_index = 0;
651 std::string pool_name;
652 std::string image_name;
653 std::string snap_name;
654
655 int r = utils::get_pool_image_snapshot_names(
656 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name,
657 &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE);
658 if (r < 0) {
659 return r;
660 }
661
662 librados::Rados rados;
663 librados::IoCtx io_ctx;
664 librbd::Image image;
665 r = utils::init_and_open_image(pool_name, image_name, "", "", false, &rados,
666 &io_ctx, &image);
667 if (r < 0) {
668 return r;
669 }
670
671 r = do_clear_limit(image);
672 if (r < 0) {
673 std::cerr << "rbd: clearing snapshot limit failed: " << cpp_strerror(r)
674 << std::endl;
675 return r;
676 }
677 return 0;
678 }
679
680 void get_rename_arguments(po::options_description *positional,
681 po::options_description *options) {
682 at::add_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_SOURCE);
683 at::add_snap_spec_options(positional, options, at::ARGUMENT_MODIFIER_DEST);
684 }
685
686 int execute_rename(const po::variables_map &vm) {
687 size_t arg_index = 0;
688 std::string pool_name;
689 std::string image_name;
690 std::string src_snap_name;
691 int r = utils::get_pool_image_snapshot_names(
692 vm, at::ARGUMENT_MODIFIER_SOURCE, &arg_index, &pool_name, &image_name,
693 &src_snap_name, utils::SNAPSHOT_PRESENCE_REQUIRED,
694 utils::SPEC_VALIDATION_NONE);
695 if (r < 0) {
696 return -r;
697 }
698
699 std::string dest_pool_name(pool_name);
700 std::string dest_image_name;
701 std::string dest_snap_name;
702 r = utils::get_pool_image_snapshot_names(
703 vm, at::ARGUMENT_MODIFIER_DEST, &arg_index, &dest_pool_name,
704 &dest_image_name, &dest_snap_name, utils::SNAPSHOT_PRESENCE_REQUIRED,
705 utils::SPEC_VALIDATION_SNAP);
706 if (r < 0) {
707 return -r;
708 }
709
710 if (pool_name != dest_pool_name) {
711 std::cerr << "rbd: source and destination pool must be the same"
712 << std::endl;
713 return -EINVAL;
714 } else if (image_name != dest_image_name) {
715 std::cerr << "rbd: source and destination image name must be the same"
716 << std::endl;
717 return -EINVAL;
718 }
719
720 librados::Rados rados;
721 librados::IoCtx io_ctx;
722 librbd::Image image;
723 r = utils::init_and_open_image(pool_name, image_name, "", "", false, &rados,
724 &io_ctx, &image);
725 if (r < 0) {
726 return r;
727 }
728
729 r = image.snap_rename(src_snap_name.c_str(), dest_snap_name.c_str());
730 if (r < 0) {
731 std::cerr << "rbd: renaming snap failed: " << cpp_strerror(r)
732 << std::endl;
733 return r;
734 }
735 return 0;
736 }
737
738 Shell::Action action_list(
739 {"snap", "list"}, {"snap", "ls"}, "Dump list of image snapshots.", "",
740 &get_list_arguments, &execute_list);
741 Shell::Action action_create(
742 {"snap", "create"}, {"snap", "add"}, "Create a snapshot.", "",
743 &get_create_arguments, &execute_create);
744 Shell::Action action_remove(
745 {"snap", "remove"}, {"snap", "rm"}, "Delete a snapshot.", "",
746 &get_remove_arguments, &execute_remove);
747 Shell::Action action_purge(
748 {"snap", "purge"}, {}, "Delete all snapshots.", "",
749 &get_purge_arguments, &execute_purge);
750 Shell::Action action_rollback(
751 {"snap", "rollback"}, {"snap", "revert"}, "Rollback image to snapshot.", "",
752 &get_rollback_arguments, &execute_rollback);
753 Shell::Action action_protect(
754 {"snap", "protect"}, {}, "Prevent a snapshot from being deleted.", "",
755 &get_protect_arguments, &execute_protect);
756 Shell::Action action_unprotect(
757 {"snap", "unprotect"}, {}, "Allow a snapshot to be deleted.", "",
758 &get_unprotect_arguments, &execute_unprotect);
759 Shell::Action action_set_limit(
760 {"snap", "limit", "set"}, {}, "Limit the number of snapshots.", "",
761 &get_set_limit_arguments, &execute_set_limit);
762 Shell::Action action_clear_limit(
763 {"snap", "limit", "clear"}, {}, "Remove snapshot limit.", "",
764 &get_clear_limit_arguments, &execute_clear_limit);
765 Shell::Action action_rename(
766 {"snap", "rename"}, {}, "Rename a snapshot.", "",
767 &get_rename_arguments, &execute_rename);
768
769 } // namespace snap
770 } // namespace action
771 } // namespace rbd