]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd/action/Nbd.cc
import ceph 16.2.6
[ceph.git] / ceph / src / tools / rbd / action / Nbd.cc
CommitLineData
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/SubProcess.h"
9#include <iostream>
11fdf7f2 10#include <boost/algorithm/string.hpp>
7c673cae 11#include <boost/algorithm/string/predicate.hpp>
7c673cae
FG
12#include <boost/program_options.hpp>
13
14namespace rbd {
15namespace action {
16namespace nbd {
17
18namespace at = argument_types;
19namespace po = boost::program_options;
20
21static int call_nbd_cmd(const po::variables_map &vm,
11fdf7f2
TL
22 const std::vector<std::string> &args,
23 const std::vector<std::string> &ceph_global_init_args) {
f67539c2
TL
24 #ifdef _WIN32
25 std::cerr << "rbd: nbd device is not supported" << std::endl;
26 return -EOPNOTSUPP;
27 #else
7c673cae
FG
28 char exe_path[PATH_MAX];
29 ssize_t exe_path_bytes = readlink("/proc/self/exe", exe_path,
30 sizeof(exe_path) - 1);
31 if (exe_path_bytes < 0) {
32 strcpy(exe_path, "rbd-nbd");
33 } else {
34 if (snprintf(exe_path + exe_path_bytes,
35 sizeof(exe_path) - exe_path_bytes,
36 "-nbd") < 0) {
37 return -EOVERFLOW;
38 }
39 }
40
41 SubProcess process(exe_path, SubProcess::KEEP, SubProcess::KEEP, SubProcess::KEEP);
42
11fdf7f2
TL
43 for (auto &arg : ceph_global_init_args) {
44 process.add_cmd_arg(arg.c_str());
7c673cae
FG
45 }
46
11fdf7f2
TL
47 for (auto &arg : args) {
48 process.add_cmd_arg(arg.c_str());
49 }
7c673cae
FG
50
51 if (process.spawn()) {
52 std::cerr << "rbd: failed to run rbd-nbd: " << process.err() << std::endl;
53 return -EINVAL;
54 } else if (process.join()) {
55 std::cerr << "rbd: rbd-nbd failed with error: " << process.err() << std::endl;
56 return -EINVAL;
57 }
58
59 return 0;
f67539c2 60 #endif
7c673cae
FG
61}
62
11fdf7f2 63int get_image_or_snap_spec(const po::variables_map &vm, std::string *spec) {
7c673cae
FG
64 size_t arg_index = 0;
65 std::string pool_name;
11fdf7f2 66 std::string nspace_name;
7c673cae
FG
67 std::string image_name;
68 std::string snap_name;
69 int r = utils::get_pool_image_snapshot_names(
11fdf7f2
TL
70 vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &nspace_name,
71 &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_PERMITTED,
7c673cae
FG
72 utils::SPEC_VALIDATION_NONE);
73 if (r < 0) {
74 return r;
75 }
76
522d829b
TL
77 if (pool_name.empty()) {
78 // connect to the cluster to get the default pool
79 librados::Rados rados;
80 r = utils::init_rados(&rados);
81 if (r < 0) {
82 return r;
83 }
84
85 utils::normalize_pool_name(&pool_name);
86 }
87
11fdf7f2
TL
88 spec->append(pool_name);
89 spec->append("/");
90 if (!nspace_name.empty()) {
91 spec->append(nspace_name);
92 spec->append("/");
93 }
94 spec->append(image_name);
95 if (!snap_name.empty()) {
96 spec->append("@");
97 spec->append(snap_name);
98 }
99
100 return 0;
101}
102
103int parse_options(const std::vector<std::string> &options,
104 std::vector<std::string> *args) {
105 for (auto &opts : options) {
106 std::vector<std::string> args_;
107 boost::split(args_, opts, boost::is_any_of(","));
108 for (auto &o : args_) {
109 args->push_back("--" + o);
110 }
111 }
112
113 return 0;
114}
115
116int execute_list(const po::variables_map &vm,
117 const std::vector<std::string> &ceph_global_init_args) {
f67539c2 118#if defined(__FreeBSD__) || defined(_WIN32)
11fdf7f2
TL
119 std::cerr << "rbd: nbd device is not supported" << std::endl;
120 return -EOPNOTSUPP;
121#endif
122 std::vector<std::string> args;
123
124 args.push_back("list-mapped");
125
126 if (vm.count("format")) {
127 args.push_back("--format");
128 args.push_back(vm["format"].as<at::Format>().value);
129 }
130 if (vm["pretty-format"].as<bool>()) {
131 args.push_back("--pretty-format");
132 }
133
134 return call_nbd_cmd(vm, args, ceph_global_init_args);
135}
136
137int execute_map(const po::variables_map &vm,
138 const std::vector<std::string> &ceph_global_init_args) {
f67539c2 139#if defined(__FreeBSD__) || defined(_WIN32)
11fdf7f2
TL
140 std::cerr << "rbd: nbd device is not supported" << std::endl;
141 return -EOPNOTSUPP;
142#endif
143 std::vector<std::string> args;
7c673cae
FG
144
145 args.push_back("map");
146 std::string img;
11fdf7f2
TL
147 int r = get_image_or_snap_spec(vm, &img);
148 if (r < 0) {
149 return r;
7c673cae 150 }
11fdf7f2 151 args.push_back(img);
7c673cae 152
f67539c2
TL
153 if (vm["quiesce"].as<bool>()) {
154 args.push_back("--quiesce");
155 }
156
11fdf7f2 157 if (vm["read-only"].as<bool>()) {
7c673cae 158 args.push_back("--read-only");
11fdf7f2 159 }
7c673cae 160
11fdf7f2 161 if (vm["exclusive"].as<bool>()) {
7c673cae 162 args.push_back("--exclusive");
7c673cae
FG
163 }
164
f67539c2
TL
165 if (vm.count("quiesce-hook")) {
166 args.push_back("--quiesce-hook");
167 args.push_back(vm["quiesce-hook"].as<std::string>());
168 }
169
11fdf7f2
TL
170 if (vm.count("options")) {
171 r = parse_options(vm["options"].as<std::vector<std::string>>(), &args);
172 if (r < 0) {
173 return r;
174 }
175 }
7c673cae 176
11fdf7f2 177 return call_nbd_cmd(vm, args, ceph_global_init_args);
7c673cae
FG
178}
179
11fdf7f2
TL
180int execute_unmap(const po::variables_map &vm,
181 const std::vector<std::string> &ceph_global_init_args) {
f67539c2 182#if defined(__FreeBSD__) || defined(_WIN32)
11fdf7f2
TL
183 std::cerr << "rbd: nbd device is not supported" << std::endl;
184 return -EOPNOTSUPP;
185#endif
7c673cae
FG
186 std::string device_name = utils::get_positional_argument(vm, 0);
187 if (!boost::starts_with(device_name, "/dev/")) {
188 device_name.clear();
189 }
190
11fdf7f2 191 std::string image_name;
7c673cae 192 if (device_name.empty()) {
11fdf7f2
TL
193 int r = get_image_or_snap_spec(vm, &image_name);
194 if (r < 0) {
195 return r;
196 }
197 }
198
199 if (device_name.empty() && image_name.empty()) {
200 std::cerr << "rbd: unmap requires either image name or device path"
201 << std::endl;
7c673cae
FG
202 return -EINVAL;
203 }
204
11fdf7f2 205 std::vector<std::string> args;
7c673cae
FG
206
207 args.push_back("unmap");
11fdf7f2
TL
208 args.push_back(device_name.empty() ? image_name : device_name);
209
210 if (vm.count("options")) {
211 int r = parse_options(vm["options"].as<std::vector<std::string>>(), &args);
212 if (r < 0) {
213 return r;
214 }
215 }
216
217 return call_nbd_cmd(vm, args, ceph_global_init_args);
218}
219
220void get_list_arguments_deprecated(po::options_description *positional,
221 po::options_description *options) {
222 at::add_format_options(options);
223}
224
225int execute_list_deprecated(const po::variables_map &vm,
226 const std::vector<std::string> &ceph_global_args) {
227 std::cerr << "rbd: 'nbd list' command is deprecated, "
228 << "use 'device list -t nbd' instead" << std::endl;
229 return execute_list(vm, ceph_global_args);
230}
231
232void get_map_arguments_deprecated(po::options_description *positional,
233 po::options_description *options) {
234 at::add_image_or_snap_spec_options(positional, options,
235 at::ARGUMENT_MODIFIER_NONE);
236 options->add_options()
237 ("read-only", po::bool_switch(), "map read-only")
238 ("exclusive", po::bool_switch(), "forbid writes by other clients")
239 ("device", po::value<std::string>(), "specify nbd device")
240 ("nbds_max", po::value<std::string>(), "override module param nbds_max")
241 ("max_part", po::value<std::string>(), "override module param max_part")
242 ("timeout", po::value<std::string>(), "set nbd request timeout (seconds)");
243}
244
245int execute_map_deprecated(const po::variables_map &vm_deprecated,
246 const std::vector<std::string> &ceph_global_args) {
247 std::cerr << "rbd: 'nbd map' command is deprecated, "
248 << "use 'device map -t nbd' instead" << std::endl;
249
250 po::options_description options;
251 options.add_options()
252 ("options,o", po::value<std::vector<std::string>>()
253 ->default_value(std::vector<std::string>(), ""), "");
254
255 po::variables_map vm = vm_deprecated;
256 po::store(po::command_line_parser({}).options(options).run(), vm);
257
258 std::vector<std::string> opts;
259 if (vm_deprecated.count("device")) {
260 opts.push_back("device=" + vm_deprecated["device"].as<std::string>());
261 }
262 if (vm_deprecated.count("nbds_max")) {
263 opts.push_back("nbds_max=" + vm_deprecated["nbds_max"].as<std::string>());
264 }
265 if (vm_deprecated.count("max_part")) {
266 opts.push_back("max_part=" + vm_deprecated["max_part"].as<std::string>());
267 }
268 if (vm_deprecated.count("timeout")) {
269 opts.push_back("timeout=" + vm_deprecated["timeout"].as<std::string>());
270 }
271
272 vm.at("options").value() = boost::any(opts);
273
274 return execute_map(vm, ceph_global_args);
275}
276
277void get_unmap_arguments_deprecated(po::options_description *positional,
278 po::options_description *options) {
279 positional->add_options()
280 ("image-or-snap-or-device-spec",
281 "image, snapshot, or device specification\n"
f67539c2 282 "[<pool-name>/]<image-name>[@<snap-name>] or <device-path>");
11fdf7f2
TL
283 at::add_pool_option(options, at::ARGUMENT_MODIFIER_NONE);
284 at::add_image_option(options, at::ARGUMENT_MODIFIER_NONE);
285 at::add_snap_option(options, at::ARGUMENT_MODIFIER_NONE);
286}
7c673cae 287
11fdf7f2
TL
288int execute_unmap_deprecated(const po::variables_map &vm,
289 const std::vector<std::string> &ceph_global_args) {
290 std::cerr << "rbd: 'nbd unmap' command is deprecated, "
291 << "use 'device unmap -t nbd' instead" << std::endl;
292 return execute_unmap(vm, ceph_global_args);
7c673cae
FG
293}
294
11fdf7f2 295Shell::SwitchArguments switched_arguments({"read-only", "exclusive"});
7c673cae 296
11fdf7f2 297Shell::Action action_show_deprecated(
7c673cae 298 {"nbd", "list"}, {"nbd", "ls"}, "List the nbd devices already used.", "",
11fdf7f2 299 &get_list_arguments_deprecated, &execute_list_deprecated, false);
7c673cae 300
11fdf7f2 301Shell::Action action_map_deprecated(
7c673cae 302 {"nbd", "map"}, {}, "Map image to a nbd device.", "",
11fdf7f2 303 &get_map_arguments_deprecated, &execute_map_deprecated, false);
7c673cae 304
11fdf7f2 305Shell::Action action_unmap_deprecated(
7c673cae 306 {"nbd", "unmap"}, {}, "Unmap a nbd device.", "",
11fdf7f2 307 &get_unmap_arguments_deprecated, &execute_unmap_deprecated, false);
7c673cae
FG
308
309} // namespace nbd
310} // namespace action
311} // namespace rbd