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