]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/stringify.h" | |
8 | #include "common/errno.h" | |
9 | #include <iostream> | |
10 | #include <map> | |
11 | #include <boost/program_options.hpp> | |
12 | ||
13 | namespace rbd { | |
14 | namespace action { | |
15 | namespace feature { | |
16 | ||
17 | namespace at = argument_types; | |
18 | namespace po = boost::program_options; | |
19 | ||
20 | void get_arguments(po::options_description *positional, | |
21 | po::options_description *options, bool enabled) { | |
22 | at::add_image_spec_options(positional, options, at::ARGUMENT_MODIFIER_NONE); | |
23 | positional->add_options() | |
24 | ("features", po::value<at::ImageFeatures>()->multitoken(), | |
25 | ("image features\n" + at::get_short_features_help(false)).c_str()); | |
26 | if (enabled) { | |
27 | at::add_create_journal_options(options); | |
28 | } | |
29 | } | |
30 | ||
31 | void get_arguments_disable(po::options_description *positional, | |
32 | po::options_description *options) { | |
33 | get_arguments(positional, options, false); | |
34 | } | |
35 | ||
36 | void get_arguments_enable(po::options_description *positional, | |
37 | po::options_description *options) { | |
38 | get_arguments(positional, options, true); | |
39 | } | |
40 | ||
41 | int execute(const po::variables_map &vm, bool enabled) { | |
42 | size_t arg_index = 0; | |
43 | std::string pool_name; | |
44 | std::string image_name; | |
45 | std::string snap_name; | |
46 | int r = utils::get_pool_image_snapshot_names( | |
47 | vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &image_name, | |
48 | &snap_name, utils::SNAPSHOT_PRESENCE_NONE, utils::SPEC_VALIDATION_NONE); | |
49 | if (r < 0) { | |
50 | return r; | |
51 | } | |
52 | ||
53 | librbd::ImageOptions opts; | |
54 | r = utils::get_journal_options(vm, &opts); | |
55 | if (r < 0) { | |
56 | return r; | |
57 | } | |
58 | ||
31f18b77 FG |
59 | std::vector<std::string> feature_names; |
60 | if (vm.count(at::POSITIONAL_ARGUMENTS)) { | |
61 | const std::vector<std::string> &args = | |
62 | vm[at::POSITIONAL_ARGUMENTS].as<std::vector<std::string> >(); | |
63 | feature_names.insert(feature_names.end(), args.begin() + arg_index, | |
64 | args.end()); | |
65 | } | |
66 | ||
7c673cae FG |
67 | if (feature_names.empty()) { |
68 | std::cerr << "rbd: at least one feature name must be specified" | |
69 | << std::endl; | |
70 | return -EINVAL; | |
71 | } | |
72 | ||
73 | boost::any features_any(static_cast<uint64_t>(0)); | |
74 | at::ImageFeatures image_features; | |
75 | at::validate(features_any, feature_names, &image_features, 0); | |
76 | ||
77 | librados::Rados rados; | |
78 | librados::IoCtx io_ctx; | |
79 | librbd::Image image; | |
80 | r = utils::init_and_open_image(pool_name, image_name, "", "", false, | |
81 | &rados, &io_ctx, &image); | |
82 | if (r < 0) { | |
83 | return r; | |
84 | } | |
85 | ||
86 | r = image.update_features(boost::any_cast<uint64_t>(features_any), enabled); | |
87 | if (r < 0) { | |
88 | std::cerr << "rbd: failed to update image features: " << cpp_strerror(r) | |
89 | << std::endl; | |
90 | return r; | |
91 | } | |
92 | return 0; | |
93 | } | |
94 | ||
95 | int execute_disable(const po::variables_map &vm) { | |
96 | return execute(vm, false); | |
97 | } | |
98 | ||
99 | int execute_enable(const po::variables_map &vm) { | |
100 | return execute(vm, true); | |
101 | } | |
102 | ||
103 | Shell::Action action_disable( | |
104 | {"feature", "disable"}, {}, "Disable the specified image feature.", "", | |
105 | &get_arguments_disable, &execute_disable); | |
106 | Shell::Action action_enable( | |
107 | {"feature", "enable"}, {}, "Enable the specified image feature.", "", | |
108 | &get_arguments_enable, &execute_enable); | |
109 | ||
110 | } // namespace feature | |
111 | } // namespace action | |
112 | } // namespace rbd |