]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd/action/Device.cc
bfe60c273df79728b63de6fcd9d59cb05c2fa306
[ceph.git] / ceph / src / tools / rbd / action / Device.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 "acconfig.h"
5 #include "tools/rbd/ArgumentTypes.h"
6 #include "tools/rbd/Shell.h"
7
8 #include <boost/program_options.hpp>
9
10 #include "include/ceph_assert.h"
11
12 namespace rbd {
13 namespace action {
14
15 namespace at = argument_types;
16 namespace po = boost::program_options;
17
18 #define DECLARE_DEVICE_OPERATIONS(ns) \
19 namespace ns { \
20 int execute_list(const po::variables_map &vm, \
21 const std::vector<std::string> &ceph_global_args); \
22 int execute_map(const po::variables_map &vm, \
23 const std::vector<std::string> &ceph_global_args); \
24 int execute_unmap(const po::variables_map &vm, \
25 const std::vector<std::string> &ceph_global_args); \
26 int execute_attach(const po::variables_map &vm, \
27 const std::vector<std::string> &ceph_global_args); \
28 int execute_detach(const po::variables_map &vm, \
29 const std::vector<std::string> &ceph_global_args); \
30 }
31
32 DECLARE_DEVICE_OPERATIONS(ggate);
33 DECLARE_DEVICE_OPERATIONS(kernel);
34 DECLARE_DEVICE_OPERATIONS(nbd);
35 DECLARE_DEVICE_OPERATIONS(wnbd);
36
37 namespace device {
38
39 namespace {
40
41 struct DeviceOperations {
42 int (*execute_list)(const po::variables_map &vm,
43 const std::vector<std::string> &ceph_global_args);
44 int (*execute_map)(const po::variables_map &vm,
45 const std::vector<std::string> &ceph_global_args);
46 int (*execute_unmap)(const po::variables_map &vm,
47 const std::vector<std::string> &ceph_global_args);
48 int (*execute_attach)(const po::variables_map &vm,
49 const std::vector<std::string> &ceph_global_args);
50 int (*execute_detach)(const po::variables_map &vm,
51 const std::vector<std::string> &ceph_global_args);
52 };
53
54 const DeviceOperations ggate_operations = {
55 ggate::execute_list,
56 ggate::execute_map,
57 ggate::execute_unmap,
58 ggate::execute_attach,
59 ggate::execute_detach,
60 };
61
62 const DeviceOperations krbd_operations = {
63 kernel::execute_list,
64 kernel::execute_map,
65 kernel::execute_unmap,
66 kernel::execute_attach,
67 kernel::execute_detach,
68 };
69
70 const DeviceOperations nbd_operations = {
71 nbd::execute_list,
72 nbd::execute_map,
73 nbd::execute_unmap,
74 nbd::execute_attach,
75 nbd::execute_detach,
76 };
77
78 const DeviceOperations wnbd_operations = {
79 wnbd::execute_list,
80 wnbd::execute_map,
81 wnbd::execute_unmap,
82 wnbd::execute_attach,
83 wnbd::execute_detach,
84 };
85
86 enum device_type_t {
87 DEVICE_TYPE_GGATE,
88 DEVICE_TYPE_KRBD,
89 DEVICE_TYPE_NBD,
90 DEVICE_TYPE_WNBD,
91 };
92
93 struct DeviceType {};
94
95 void validate(boost::any& v, const std::vector<std::string>& values,
96 DeviceType *target_type, int) {
97 po::validators::check_first_occurrence(v);
98 const std::string &s = po::validators::get_single_string(values);
99
100 #ifdef _WIN32
101 if (s == "wnbd") {
102 v = boost::any(DEVICE_TYPE_WNBD);
103 #else
104 if (s == "nbd") {
105 v = boost::any(DEVICE_TYPE_NBD);
106 } else if (s == "ggate") {
107 v = boost::any(DEVICE_TYPE_GGATE);
108 } else if (s == "krbd") {
109 v = boost::any(DEVICE_TYPE_KRBD);
110 #endif /* _WIN32 */
111 } else {
112 throw po::validation_error(po::validation_error::invalid_option_value);
113 }
114 }
115
116 void add_device_type_option(po::options_description *options) {
117 options->add_options()
118 ("device-type,t", po::value<DeviceType>(),
119 #ifdef _WIN32
120 "device type [wnbd]");
121 #else
122 "device type [ggate, krbd (default), nbd]");
123 #endif
124 }
125
126 void add_device_specific_options(po::options_description *options) {
127 options->add_options()
128 ("options,o", po::value<std::vector<std::string>>(),
129 "device specific options");
130 }
131
132 device_type_t get_device_type(const po::variables_map &vm) {
133 if (vm.count("device-type")) {
134 return vm["device-type"].as<device_type_t>();
135 }
136 #ifndef _WIN32
137 return DEVICE_TYPE_KRBD;
138 #else
139 return DEVICE_TYPE_WNBD;
140 #endif
141 }
142
143 const DeviceOperations *get_device_operations(const po::variables_map &vm) {
144 switch (get_device_type(vm)) {
145 case DEVICE_TYPE_GGATE:
146 return &ggate_operations;
147 case DEVICE_TYPE_KRBD:
148 return &krbd_operations;
149 case DEVICE_TYPE_NBD:
150 return &nbd_operations;
151 case DEVICE_TYPE_WNBD:
152 return &wnbd_operations;
153 default:
154 ceph_abort();
155 return nullptr;
156 }
157 }
158
159 } // anonymous namespace
160
161 void get_list_arguments(po::options_description *positional,
162 po::options_description *options) {
163 add_device_type_option(options);
164 at::add_format_options(options);
165 }
166
167 int execute_list(const po::variables_map &vm,
168 const std::vector<std::string> &ceph_global_init_args) {
169 return (*get_device_operations(vm)->execute_list)(vm, ceph_global_init_args);
170 }
171
172 void get_map_arguments(po::options_description *positional,
173 po::options_description *options) {
174 add_device_type_option(options);
175 at::add_image_or_snap_spec_options(positional, options,
176 at::ARGUMENT_MODIFIER_NONE);
177 options->add_options()
178 ("show-cookie", po::bool_switch(), "show device cookie")
179 ("cookie", po::value<std::string>(), "specify device cookie")
180 ("read-only", po::bool_switch(), "map read-only")
181 ("exclusive", po::bool_switch(), "disable automatic exclusive lock transitions")
182 ("quiesce", po::bool_switch(), "use quiesce hooks")
183 ("quiesce-hook", po::value<std::string>(), "quiesce hook path");
184 add_device_specific_options(options);
185 }
186
187 int execute_map(const po::variables_map &vm,
188 const std::vector<std::string> &ceph_global_init_args) {
189 return (*get_device_operations(vm)->execute_map)(vm, ceph_global_init_args);
190 }
191
192 void get_unmap_arguments(po::options_description *positional,
193 po::options_description *options) {
194 add_device_type_option(options);
195 positional->add_options()
196 ("image-or-snap-or-device-spec",
197 "image, snapshot, or device specification\n"
198 "[<pool-name>/]<image-name>[@<snap-name>] or <device-path>");
199 at::add_pool_option(options, at::ARGUMENT_MODIFIER_NONE);
200 at::add_image_option(options, at::ARGUMENT_MODIFIER_NONE);
201 at::add_snap_option(options, at::ARGUMENT_MODIFIER_NONE);
202 add_device_specific_options(options);
203 }
204
205 int execute_unmap(const po::variables_map &vm,
206 const std::vector<std::string> &ceph_global_init_args) {
207 return (*get_device_operations(vm)->execute_unmap)(vm, ceph_global_init_args);
208 }
209
210 void get_attach_arguments(po::options_description *positional,
211 po::options_description *options) {
212 add_device_type_option(options);
213 at::add_image_or_snap_spec_options(positional, options,
214 at::ARGUMENT_MODIFIER_NONE);
215 options->add_options()
216 ("device", po::value<std::string>()->required(), "specify device path")
217 ("show-cookie", po::bool_switch(), "show device cookie")
218 ("cookie", po::value<std::string>(), "specify device cookie")
219 ("read-only", po::bool_switch(), "attach read-only")
220 ("force", po::bool_switch(), "force attach")
221 ("exclusive", po::bool_switch(), "disable automatic exclusive lock transitions")
222 ("quiesce", po::bool_switch(), "use quiesce hooks")
223 ("quiesce-hook", po::value<std::string>(), "quiesce hook path");
224 add_device_specific_options(options);
225 }
226
227 int execute_attach(const po::variables_map &vm,
228 const std::vector<std::string> &ceph_global_init_args) {
229 return (*get_device_operations(vm)->execute_attach)(vm, ceph_global_init_args);
230 }
231
232 void get_detach_arguments(po::options_description *positional,
233 po::options_description *options) {
234 add_device_type_option(options);
235 positional->add_options()
236 ("image-or-snap-or-device-spec",
237 "image, snapshot, or device specification\n"
238 "[<pool-name>/]<image-name>[@<snap-name>] or <device-path>");
239 at::add_pool_option(options, at::ARGUMENT_MODIFIER_NONE);
240 at::add_image_option(options, at::ARGUMENT_MODIFIER_NONE);
241 at::add_snap_option(options, at::ARGUMENT_MODIFIER_NONE);
242 add_device_specific_options(options);
243 }
244
245 int execute_detach(const po::variables_map &vm,
246 const std::vector<std::string> &ceph_global_init_args) {
247 return (*get_device_operations(vm)->execute_detach)(vm, ceph_global_init_args);
248 }
249
250 Shell::SwitchArguments switched_arguments({"exclusive", "force", "quiesce",
251 "read-only", "show-cookie"});
252
253 Shell::Action action_list(
254 {"device", "list"}, {"showmapped"}, "List mapped rbd images.", "",
255 &get_list_arguments, &execute_list);
256 // yet another alias for list command
257 Shell::Action action_ls(
258 {"device", "ls"}, {}, "List mapped rbd images.", "",
259 &get_list_arguments, &execute_list, false);
260
261 Shell::Action action_map(
262 {"device", "map"}, {"map"}, "Map an image to a block device.", "",
263 &get_map_arguments, &execute_map);
264
265 Shell::Action action_unmap(
266 {"device", "unmap"}, {"unmap"}, "Unmap a rbd device.", "",
267 &get_unmap_arguments, &execute_unmap);
268
269 Shell::Action action_attach(
270 {"device", "attach"}, {}, "Attach image to device.", "",
271 &get_attach_arguments, &execute_attach);
272
273 Shell::Action action_detach(
274 {"device", "detach"}, {}, "Detach image from device.", "",
275 &get_detach_arguments, &execute_detach);
276
277 } // namespace device
278 } // namespace action
279 } // namespace rbd