]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
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> | |
10 | #include <boost/algorithm/string.hpp> | |
11 | #include <boost/algorithm/string/predicate.hpp> | |
12 | #include <boost/program_options.hpp> | |
13 | ||
14 | namespace rbd { | |
15 | namespace action { | |
16 | namespace wnbd { | |
17 | ||
18 | namespace at = argument_types; | |
19 | namespace po = boost::program_options; | |
20 | ||
21 | static int call_wnbd_cmd(const po::variables_map &vm, | |
22 | const std::vector<std::string> &args, | |
23 | const std::vector<std::string> &ceph_global_init_args) { | |
24 | char exe_path[PATH_MAX]; | |
25 | ssize_t exe_path_bytes = get_self_exe_path(exe_path, PATH_MAX); | |
26 | ||
27 | if (exe_path_bytes > 4) { | |
28 | // Drop .exe suffix as we're going to add the "-wnbd" suffix. | |
29 | exe_path[strlen(exe_path) - 4] = '\0'; | |
30 | exe_path_bytes -= 4; | |
31 | } | |
32 | ||
33 | if (exe_path_bytes < 0) { | |
34 | strcpy(exe_path, "rbd-wnbd"); | |
35 | } else { | |
36 | if (snprintf(exe_path + exe_path_bytes, | |
37 | sizeof(exe_path) - exe_path_bytes, | |
38 | "-wnbd") < 0) { | |
39 | return -EOVERFLOW; | |
40 | } | |
41 | } | |
42 | ||
43 | SubProcess process(exe_path, SubProcess::KEEP, SubProcess::KEEP, SubProcess::KEEP); | |
44 | ||
45 | for (auto &arg : ceph_global_init_args) { | |
46 | process.add_cmd_arg(arg.c_str()); | |
47 | } | |
48 | ||
49 | for (auto &arg : args) { | |
50 | process.add_cmd_arg(arg.c_str()); | |
51 | } | |
52 | ||
53 | if (process.spawn()) { | |
54 | std::cerr << "rbd: failed to run rbd-wnbd: " << process.err() << std::endl; | |
55 | return -EINVAL; | |
56 | } | |
57 | int exit_code = process.join(); | |
58 | if (exit_code) { | |
59 | std::cerr << "rbd: rbd-wnbd failed with error: " << process.err() << std::endl; | |
60 | return exit_code; | |
61 | } | |
62 | ||
63 | return 0; | |
64 | } | |
65 | ||
66 | int get_image_or_snap_spec(const po::variables_map &vm, std::string *spec) { | |
67 | size_t arg_index = 0; | |
68 | std::string pool_name; | |
69 | std::string nspace_name; | |
70 | std::string image_name; | |
71 | std::string snap_name; | |
72 | int r = utils::get_pool_image_snapshot_names( | |
73 | vm, at::ARGUMENT_MODIFIER_NONE, &arg_index, &pool_name, &nspace_name, | |
74 | &image_name, &snap_name, true, utils::SNAPSHOT_PRESENCE_PERMITTED, | |
75 | utils::SPEC_VALIDATION_NONE); | |
76 | if (r < 0) { | |
77 | return r; | |
78 | } | |
79 | ||
80 | if (!pool_name.empty()) { | |
81 | spec->append(pool_name); | |
82 | spec->append("/"); | |
83 | } | |
84 | if (!nspace_name.empty()) { | |
85 | spec->append(nspace_name); | |
86 | spec->append("/"); | |
87 | } | |
88 | spec->append(image_name); | |
89 | if (!snap_name.empty()) { | |
90 | spec->append("@"); | |
91 | spec->append(snap_name); | |
92 | } | |
93 | ||
94 | return 0; | |
95 | } | |
96 | ||
97 | int parse_options(const std::vector<std::string> &options, | |
98 | std::vector<std::string> *args) { | |
99 | for (auto &opts : options) { | |
100 | std::vector<std::string> args_; | |
101 | boost::split(args_, opts, boost::is_any_of(",")); | |
102 | for (auto &o : args_) { | |
103 | args->push_back("--" + o); | |
104 | } | |
105 | } | |
106 | ||
107 | return 0; | |
108 | } | |
109 | ||
110 | int execute_list(const po::variables_map &vm, | |
111 | const std::vector<std::string> &ceph_global_init_args) { | |
112 | std::vector<std::string> args; | |
113 | ||
114 | args.push_back("list"); | |
115 | ||
116 | if (vm.count("format")) { | |
117 | args.push_back("--format"); | |
118 | args.push_back(vm["format"].as<at::Format>().value); | |
119 | } | |
120 | if (vm["pretty-format"].as<bool>()) { | |
121 | args.push_back("--pretty-format"); | |
122 | } | |
123 | ||
124 | return call_wnbd_cmd(vm, args, ceph_global_init_args); | |
125 | } | |
126 | ||
127 | int execute_map(const po::variables_map &vm, | |
128 | const std::vector<std::string> &ceph_global_init_args) { | |
129 | std::vector<std::string> args; | |
130 | ||
131 | args.push_back("map"); | |
132 | std::string img; | |
133 | int r = get_image_or_snap_spec(vm, &img); | |
134 | if (r < 0) { | |
135 | return r; | |
136 | } | |
137 | args.push_back(img); | |
138 | ||
139 | if (vm["read-only"].as<bool>()) { | |
140 | args.push_back("--read-only"); | |
141 | } | |
142 | ||
143 | if (vm["exclusive"].as<bool>()) { | |
144 | args.push_back("--exclusive"); | |
145 | } | |
146 | ||
147 | if (vm.count("options")) { | |
148 | r = parse_options(vm["options"].as<std::vector<std::string>>(), &args); | |
149 | if (r < 0) { | |
150 | return r; | |
151 | } | |
152 | } | |
153 | ||
154 | return call_wnbd_cmd(vm, args, ceph_global_init_args); | |
155 | } | |
156 | ||
157 | int execute_unmap(const po::variables_map &vm, | |
158 | const std::vector<std::string> &ceph_global_init_args) { | |
159 | std::string device_name = utils::get_positional_argument(vm, 0); | |
160 | ||
161 | std::string image_name; | |
162 | if (device_name.empty()) { | |
163 | int r = get_image_or_snap_spec(vm, &image_name); | |
164 | if (r < 0) { | |
165 | return r; | |
166 | } | |
167 | } | |
168 | ||
169 | if (device_name.empty() && image_name.empty()) { | |
170 | std::cerr << "rbd: unmap requires either image name or device path" | |
171 | << std::endl; | |
172 | return -EINVAL; | |
173 | } | |
174 | ||
175 | std::vector<std::string> args; | |
176 | ||
177 | args.push_back("unmap"); | |
178 | args.push_back(device_name.empty() ? image_name : device_name); | |
179 | ||
180 | if (vm.count("options")) { | |
181 | int r = parse_options(vm["options"].as<std::vector<std::string>>(), &args); | |
182 | if (r < 0) { | |
183 | return r; | |
184 | } | |
185 | } | |
186 | ||
187 | return call_wnbd_cmd(vm, args, ceph_global_init_args); | |
188 | } | |
189 | ||
190 | Shell::SwitchArguments switched_arguments({"read-only", "exclusive"}); | |
191 | ||
192 | } // namespace wnbd | |
193 | } // namespace action | |
194 | } // namespace rbd |