1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
8 #include "include/stringify.h"
9 #include "common/SubProcess.h"
11 #include "tools/rbd/ArgumentTypes.h"
12 #include "tools/rbd/Shell.h"
13 #include "tools/rbd/Utils.h"
15 #include <boost/algorithm/string.hpp>
16 #include <boost/algorithm/string/predicate.hpp>
17 #include <boost/program_options.hpp>
25 namespace at
= argument_types
;
26 namespace po
= boost::program_options
;
28 #if defined(__FreeBSD__)
29 static int call_ggate_cmd(const po::variables_map
&vm
,
30 const std::vector
<std::string
> &args
,
31 const std::vector
<std::string
> &ceph_global_args
) {
32 SubProcess
process("rbd-ggate", SubProcess::KEEP
, SubProcess::KEEP
,
35 for (auto &arg
: ceph_global_args
) {
36 process
.add_cmd_arg(arg
.c_str());
39 for (auto &arg
: args
) {
40 process
.add_cmd_arg(arg
.c_str());
43 if (process
.spawn()) {
44 std::cerr
<< "rbd: failed to run rbd-ggate: " << process
.err() << std::endl
;
46 } else if (process
.join()) {
47 std::cerr
<< "rbd: rbd-ggate failed with error: " << process
.err()
55 int get_image_or_snap_spec(const po::variables_map
&vm
, std::string
*spec
) {
57 std::string pool_name
;
58 std::string nspace_name
;
59 std::string image_name
;
60 std::string snap_name
;
61 int r
= utils::get_pool_image_snapshot_names(
62 vm
, at::ARGUMENT_MODIFIER_NONE
, &arg_index
, &pool_name
, &nspace_name
,
63 &image_name
, &snap_name
, true,
64 utils::SNAPSHOT_PRESENCE_PERMITTED
, utils::SPEC_VALIDATION_NONE
);
69 if (pool_name
.empty()) {
70 // connect to the cluster to get the default pool
71 librados::Rados rados
;
72 r
= utils::init_rados(&rados
);
77 utils::normalize_pool_name(&pool_name
);
80 spec
->append(pool_name
);
82 if (!nspace_name
.empty()) {
83 spec
->append(nspace_name
);
86 spec
->append(image_name
);
87 if (!snap_name
.empty()) {
89 spec
->append(snap_name
);
95 int parse_options(const std::vector
<std::string
> &options
,
96 std::vector
<std::string
> *args
) {
97 for (auto &opts
: options
) {
98 std::vector
<std::string
> args_
;
99 boost::split(args_
, opts
, boost::is_any_of(","));
100 for (auto &o
: args_
) {
101 args
->push_back("--" + o
);
109 int execute_list(const po::variables_map
&vm
,
110 const std::vector
<std::string
> &ceph_global_init_args
) {
111 #if !defined(__FreeBSD__)
112 std::cerr
<< "rbd: ggate is only supported on FreeBSD" << std::endl
;
115 std::vector
<std::string
> args
;
117 args
.push_back("list");
119 if (vm
.count("format")) {
120 args
.push_back("--format");
121 args
.push_back(vm
["format"].as
<at::Format
>().value
);
123 if (vm
["pretty-format"].as
<bool>()) {
124 args
.push_back("--pretty-format");
127 return call_ggate_cmd(vm
, args
, ceph_global_init_args
);
131 int execute_map(const po::variables_map
&vm
,
132 const std::vector
<std::string
> &ceph_global_init_args
) {
133 #if !defined(__FreeBSD__)
134 std::cerr
<< "rbd: ggate is only supported on FreeBSD" << std::endl
;
137 std::vector
<std::string
> args
;
139 args
.push_back("map");
141 int r
= get_image_or_snap_spec(vm
, &img
);
147 if (vm
["quiesce"].as
<bool>()) {
148 std::cerr
<< "rbd: warning: quiesce is not supported" << std::endl
;
151 if (vm
["read-only"].as
<bool>()) {
152 args
.push_back("--read-only");
155 if (vm
["exclusive"].as
<bool>()) {
156 args
.push_back("--exclusive");
159 if (vm
.count("quiesce-hook")) {
160 std::cerr
<< "rbd: warning: quiesce-hook is not supported" << std::endl
;
163 if (vm
.count("options")) {
164 r
= parse_options(vm
["options"].as
<std::vector
<std::string
>>(), &args
);
170 return call_ggate_cmd(vm
, args
, ceph_global_init_args
);
174 int execute_unmap(const po::variables_map
&vm
,
175 const std::vector
<std::string
> &ceph_global_init_args
) {
176 #if !defined(__FreeBSD__)
177 std::cerr
<< "rbd: ggate is only supported on FreeBSD" << std::endl
;
180 std::string device_name
= utils::get_positional_argument(vm
, 0);
181 if (!boost::starts_with(device_name
, "/dev/")) {
185 std::string image_name
;
186 if (device_name
.empty()) {
187 int r
= get_image_or_snap_spec(vm
, &image_name
);
193 if (device_name
.empty() && image_name
.empty()) {
194 std::cerr
<< "rbd: unmap requires either image name or device path"
199 std::vector
<std::string
> args
;
201 args
.push_back("unmap");
202 args
.push_back(device_name
.empty() ? image_name
: device_name
);
204 if (vm
.count("options")) {
205 int r
= parse_options(vm
["options"].as
<std::vector
<std::string
>>(), &args
);
211 return call_ggate_cmd(vm
, args
, ceph_global_init_args
);
215 int execute_attach(const po::variables_map
&vm
,
216 const std::vector
<std::string
> &ceph_global_init_args
) {
217 #if !defined(__FreeBSD__)
218 std::cerr
<< "rbd: ggate is only supported on FreeBSD" << std::endl
;
220 std::cerr
<< "rbd: ggate attach command not supported" << std::endl
;
225 int execute_detach(const po::variables_map
&vm
,
226 const std::vector
<std::string
> &ceph_global_init_args
) {
227 #if !defined(__FreeBSD__)
228 std::cerr
<< "rbd: ggate is only supported on FreeBSD" << std::endl
;
230 std::cerr
<< "rbd: ggate detach command not supported" << std::endl
;
236 } // namespace action