1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
10 #include <boost/algorithm/string.hpp>
11 #include <boost/algorithm/string/predicate.hpp>
12 #include <boost/program_options.hpp>
18 namespace at
= argument_types
;
19 namespace po
= boost::program_options
;
22 static int call_wnbd_cmd(const po::variables_map
&vm
,
23 const std::vector
<std::string
> &args
,
24 const std::vector
<std::string
> &ceph_global_init_args
) {
25 char exe_path
[PATH_MAX
];
26 ssize_t exe_path_bytes
= get_self_exe_path(exe_path
, PATH_MAX
);
28 if (exe_path_bytes
> 4) {
29 // Drop .exe suffix as we're going to add the "-wnbd" suffix.
30 exe_path
[strlen(exe_path
) - 4] = '\0';
34 if (exe_path_bytes
< 0) {
35 strcpy(exe_path
, "rbd-wnbd");
37 if (snprintf(exe_path
+ exe_path_bytes
,
38 sizeof(exe_path
) - exe_path_bytes
,
44 SubProcess
process(exe_path
, SubProcess::KEEP
, SubProcess::KEEP
, SubProcess::KEEP
);
46 for (auto &arg
: ceph_global_init_args
) {
47 process
.add_cmd_arg(arg
.c_str());
50 for (auto &arg
: args
) {
51 process
.add_cmd_arg(arg
.c_str());
54 if (process
.spawn()) {
55 std::cerr
<< "rbd: failed to run rbd-wnbd: " << process
.err() << std::endl
;
58 int exit_code
= process
.join();
60 std::cerr
<< "rbd: rbd-wnbd failed with error: " << process
.err() << std::endl
;
67 int get_image_or_snap_spec(const po::variables_map
&vm
, std::string
*spec
) {
69 std::string pool_name
;
70 std::string nspace_name
;
71 std::string image_name
;
72 std::string snap_name
;
73 int r
= utils::get_pool_image_snapshot_names(
74 vm
, at::ARGUMENT_MODIFIER_NONE
, &arg_index
, &pool_name
, &nspace_name
,
75 &image_name
, &snap_name
, true, utils::SNAPSHOT_PRESENCE_PERMITTED
,
76 utils::SPEC_VALIDATION_NONE
);
81 if (!pool_name
.empty()) {
82 spec
->append(pool_name
);
85 if (!nspace_name
.empty()) {
86 spec
->append(nspace_name
);
89 spec
->append(image_name
);
90 if (!snap_name
.empty()) {
92 spec
->append(snap_name
);
98 int parse_options(const std::vector
<std::string
> &options
,
99 std::vector
<std::string
> *args
) {
100 for (auto &opts
: options
) {
101 std::vector
<std::string
> args_
;
102 boost::split(args_
, opts
, boost::is_any_of(","));
103 for (auto &o
: args_
) {
104 args
->push_back("--" + o
);
112 int execute_list(const po::variables_map
&vm
,
113 const std::vector
<std::string
> &ceph_global_init_args
) {
115 std::cerr
<< "rbd: wnbd is only supported on Windows" << std::endl
;
118 std::vector
<std::string
> args
;
120 args
.push_back("list");
122 if (vm
.count("format")) {
123 args
.push_back("--format");
124 args
.push_back(vm
["format"].as
<at::Format
>().value
);
126 if (vm
["pretty-format"].as
<bool>()) {
127 args
.push_back("--pretty-format");
130 return call_wnbd_cmd(vm
, args
, ceph_global_init_args
);
134 int execute_map(const po::variables_map
&vm
,
135 const std::vector
<std::string
> &ceph_global_init_args
) {
137 std::cerr
<< "rbd: wnbd is only supported on Windows" << std::endl
;
140 std::vector
<std::string
> args
;
142 args
.push_back("map");
144 int r
= get_image_or_snap_spec(vm
, &img
);
150 if (vm
["read-only"].as
<bool>()) {
151 args
.push_back("--read-only");
154 if (vm
["exclusive"].as
<bool>()) {
155 args
.push_back("--exclusive");
158 if (vm
.count("options")) {
159 r
= parse_options(vm
["options"].as
<std::vector
<std::string
>>(), &args
);
165 return call_wnbd_cmd(vm
, args
, ceph_global_init_args
);
169 int execute_unmap(const po::variables_map
&vm
,
170 const std::vector
<std::string
> &ceph_global_init_args
) {
172 std::cerr
<< "rbd: wnbd is only supported on Windows" << std::endl
;
175 std::string device_name
= utils::get_positional_argument(vm
, 0);
177 std::string image_name
;
178 if (device_name
.empty()) {
179 int r
= get_image_or_snap_spec(vm
, &image_name
);
185 if (device_name
.empty() && image_name
.empty()) {
186 std::cerr
<< "rbd: unmap requires either image name or device path"
191 std::vector
<std::string
> args
;
193 args
.push_back("unmap");
194 args
.push_back(device_name
.empty() ? image_name
: device_name
);
196 if (vm
.count("options")) {
197 int r
= parse_options(vm
["options"].as
<std::vector
<std::string
>>(), &args
);
203 return call_wnbd_cmd(vm
, args
, ceph_global_init_args
);
207 int execute_attach(const po::variables_map
&vm
,
208 const std::vector
<std::string
> &ceph_global_init_args
) {
210 std::cerr
<< "rbd: wnbd is only supported on Windows" << std::endl
;
212 std::cerr
<< "rbd: wnbd attach command not supported" << std::endl
;
217 int execute_detach(const po::variables_map
&vm
,
218 const std::vector
<std::string
> &ceph_global_init_args
) {
220 std::cerr
<< "rbd: wnbd is only supported on Windows" << std::endl
;
222 std::cerr
<< "rbd: wnbd detach command not supported" << std::endl
;
228 } // namespace action