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/Schedule.h"
6 #include "tools/rbd/Shell.h"
7 #include "tools/rbd/Utils.h"
8 #include "common/ceph_context.h"
9 #include "common/ceph_json.h"
10 #include "common/errno.h"
11 #include "common/Formatter.h"
12 #include "common/TextTable.h"
13 #include "global/global_context.h"
14 #include "include/stringify.h"
21 #include <boost/program_options.hpp>
23 #include "json_spirit/json_spirit.h"
27 namespace trash_purge_schedule
{
29 namespace at
= argument_types
;
30 namespace po
= boost::program_options
;
34 class ScheduleStatus
{
39 int parse(const std::string
&status
) {
40 json_spirit::mValue json_root
;
41 if(!json_spirit::read(status
, json_root
)) {
42 std::cerr
<< "rbd: invalid schedule status JSON received" << std::endl
;
47 auto &s
= json_root
.get_obj();
49 if (s
["scheduled"].type() != json_spirit::array_type
) {
50 std::cerr
<< "rbd: unexpected schedule JSON received: "
51 << "scheduled is not array" << std::endl
;
55 for (auto &item_val
: s
["scheduled"].get_array()) {
56 if (item_val
.type() != json_spirit::obj_type
) {
57 std::cerr
<< "rbd: unexpected schedule status JSON received: "
58 << "schedule item is not object" << std::endl
;
62 auto &item
= item_val
.get_obj();
64 if (item
["pool_name"].type() != json_spirit::str_type
) {
65 std::cerr
<< "rbd: unexpected schedule JSON received: "
66 << "pool_name is not string" << std::endl
;
69 auto pool_name
= item
["pool_name"].get_str();
71 if (item
["namespace"].type() != json_spirit::str_type
) {
72 std::cerr
<< "rbd: unexpected schedule JSON received: "
73 << "namespace is not string" << std::endl
;
76 auto namespace_name
= item
["namespace"].get_str();
78 if (item
["schedule_time"].type() != json_spirit::str_type
) {
79 std::cerr
<< "rbd: unexpected schedule JSON received: "
80 << "schedule_time is not string" << std::endl
;
83 auto schedule_time
= item
["schedule_time"].get_str();
85 scheduled
.insert({pool_name
, namespace_name
, schedule_time
});
88 } catch (std::runtime_error
&) {
89 std::cerr
<< "rbd: invalid schedule JSON received" << std::endl
;
96 void dump(Formatter
*f
) {
97 f
->open_array_section("scheduled");
98 for (auto &item
: scheduled
) {
99 f
->open_object_section("item");
100 f
->dump_string("pool", item
.pool_name
);
101 f
->dump_string("namespce", item
.namespace_name
);
102 f
->dump_string("schedule_time", item
.schedule_time
);
103 f
->close_section(); // item
105 f
->close_section(); // scheduled
108 friend std::ostream
& operator<<(std::ostream
& os
, ScheduleStatus
&d
);
113 std::string pool_name
;
114 std::string namespace_name
;
115 std::string schedule_time
;
117 Item(const std::string
&pool_name
, const std::string
&namespace_name
,
118 const std::string
&schedule_time
)
119 : pool_name(pool_name
), namespace_name(namespace_name
),
120 schedule_time(schedule_time
) {
123 bool operator<(const Item
&rhs
) const {
124 if (pool_name
!= rhs
.pool_name
) {
125 return pool_name
< rhs
.pool_name
;
127 return namespace_name
< rhs
.namespace_name
;
131 std::set
<Item
> scheduled
;
134 std::ostream
& operator<<(std::ostream
& os
, ScheduleStatus
&s
) {
136 tbl
.define_column("POOL", TextTable::LEFT
, TextTable::LEFT
);
137 tbl
.define_column("NAMESPACE", TextTable::LEFT
, TextTable::LEFT
);
138 tbl
.define_column("SCHEDULE TIME", TextTable::LEFT
, TextTable::LEFT
);
140 for (auto &item
: s
.scheduled
) {
141 tbl
<< item
.pool_name
<< item
.namespace_name
<< item
.schedule_time
142 << TextTable::endrow
;
149 } // anonymous namespace
151 void get_arguments_add(po::options_description
*positional
,
152 po::options_description
*options
) {
153 add_level_spec_options(options
, false);
154 add_schedule_options(positional
, true);
157 int execute_add(const po::variables_map
&vm
,
158 const std::vector
<std::string
> &ceph_global_init_args
) {
159 std::map
<std::string
, std::string
> args
;
161 int r
= get_level_spec_args(vm
, &args
);
165 r
= get_schedule_args(vm
, true, &args
);
170 librados::Rados rados
;
171 r
= utils::init_rados(&rados
);
176 normalize_level_spec_args(&args
);
177 r
= utils::mgr_command(rados
, "rbd trash purge schedule add", args
,
178 &std::cout
, &std::cerr
);
186 void get_arguments_remove(po::options_description
*positional
,
187 po::options_description
*options
) {
188 add_level_spec_options(options
, false);
189 add_schedule_options(positional
, false);
192 int execute_remove(const po::variables_map
&vm
,
193 const std::vector
<std::string
> &ceph_global_init_args
) {
194 std::map
<std::string
, std::string
> args
;
196 int r
= get_level_spec_args(vm
, &args
);
200 r
= get_schedule_args(vm
, false, &args
);
205 librados::Rados rados
;
206 r
= utils::init_rados(&rados
);
211 normalize_level_spec_args(&args
);
212 r
= utils::mgr_command(rados
, "rbd trash purge schedule remove", args
,
213 &std::cout
, &std::cerr
);
221 void get_arguments_list(po::options_description
*positional
,
222 po::options_description
*options
) {
223 add_level_spec_options(options
, false);
224 options
->add_options()
225 ("recursive,R", po::bool_switch(), "list all schedules");
226 at::add_format_options(options
);
229 int execute_list(const po::variables_map
&vm
,
230 const std::vector
<std::string
> &ceph_global_init_args
) {
231 std::map
<std::string
, std::string
> args
;
233 int r
= get_level_spec_args(vm
, &args
);
238 at::Format::Formatter formatter
;
239 r
= utils::get_formatter(vm
, &formatter
);
244 librados::Rados rados
;
245 r
= utils::init_rados(&rados
);
250 normalize_level_spec_args(&args
);
251 std::stringstream out
;
252 r
= utils::mgr_command(rados
, "rbd trash purge schedule list", args
, &out
,
258 ScheduleList
schedule_list(false);
259 r
= schedule_list
.parse(out
.str());
264 if (vm
["recursive"].as
<bool>()) {
265 if (formatter
.get()) {
266 schedule_list
.dump(formatter
.get());
267 formatter
->flush(std::cout
);
269 std::cout
<< schedule_list
;
272 auto schedule
= schedule_list
.find(args
["level_spec"]);
273 if (schedule
== nullptr) {
277 if (formatter
.get()) {
278 schedule
->dump(formatter
.get());
279 formatter
->flush(std::cout
);
281 std::cout
<< *schedule
<< std::endl
;
288 void get_arguments_status(po::options_description
*positional
,
289 po::options_description
*options
) {
290 add_level_spec_options(options
, false);
291 at::add_format_options(options
);
294 int execute_status(const po::variables_map
&vm
,
295 const std::vector
<std::string
> &ceph_global_init_args
) {
296 std::map
<std::string
, std::string
> args
;
298 int r
= get_level_spec_args(vm
, &args
);
303 at::Format::Formatter formatter
;
304 r
= utils::get_formatter(vm
, &formatter
);
309 librados::Rados rados
;
310 r
= utils::init_rados(&rados
);
315 normalize_level_spec_args(&args
);
316 std::stringstream out
;
317 r
= utils::mgr_command(rados
, "rbd trash purge schedule status", args
, &out
,
319 ScheduleStatus schedule_status
;
320 r
= schedule_status
.parse(out
.str());
325 if (formatter
.get()) {
326 schedule_status
.dump(formatter
.get());
327 formatter
->flush(std::cout
);
329 std::cout
<< schedule_status
;
335 Shell::SwitchArguments
switched_arguments({"recursive", "R"});
337 Shell::Action
add_action(
338 {"trash", "purge", "schedule", "add"}, {}, "Add trash purge schedule.", "",
339 &get_arguments_add
, &execute_add
);
340 Shell::Action
remove_action(
341 {"trash", "purge", "schedule", "remove"},
342 {"trash", "purge", "schedule", "rm"}, "Remove trash purge schedule.",
343 "", &get_arguments_remove
, &execute_remove
);
344 Shell::Action
list_action(
345 {"trash", "purge", "schedule", "list"},
346 {"trash", "purge", "schedule", "ls"}, "List trash purge schedule.",
347 "", &get_arguments_list
, &execute_list
);
348 Shell::Action
status_action(
349 {"trash", "purge", "schedule", "status"}, {},
350 "Show trash purge schedule status.", "", &get_arguments_status
,
353 } // namespace trash_purge_schedule
354 } // namespace action