]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd/action/TrashPurgeSchedule.cc
import quincy 17.2.0
[ceph.git] / ceph / src / tools / rbd / action / TrashPurgeSchedule.cc
CommitLineData
9f95a23c
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/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"
15
16#include <iostream>
17#include <list>
18#include <map>
19#include <set>
20#include <string>
21#include <boost/program_options.hpp>
22
23#include "json_spirit/json_spirit.h"
24
25namespace rbd {
26namespace action {
27namespace trash_purge_schedule {
28
29namespace at = argument_types;
30namespace po = boost::program_options;
31
32namespace {
33
34class ScheduleStatus {
35public:
36 ScheduleStatus() {
37 }
38
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;
43 return -EBADMSG;
44 }
45
46 try {
47 auto &s = json_root.get_obj();
48
49 if (s["scheduled"].type() != json_spirit::array_type) {
50 std::cerr << "rbd: unexpected schedule JSON received: "
51 << "scheduled is not array" << std::endl;
52 return -EBADMSG;
53 }
54
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;
59 return -EBADMSG;
60 }
61
62 auto &item = item_val.get_obj();
63
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;
67 return -EBADMSG;
68 }
69 auto pool_name = item["pool_name"].get_str();
70
71 if (item["namespace"].type() != json_spirit::str_type) {
72 std::cerr << "rbd: unexpected schedule JSON received: "
73 << "namespace is not string" << std::endl;
74 return -EBADMSG;
75 }
76 auto namespace_name = item["namespace"].get_str();
77
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;
81 return -EBADMSG;
82 }
83 auto schedule_time = item["schedule_time"].get_str();
84
85 scheduled.insert({pool_name, namespace_name, schedule_time});
86 }
87
88 } catch (std::runtime_error &) {
89 std::cerr << "rbd: invalid schedule JSON received" << std::endl;
90 return -EBADMSG;
91 }
92
93 return 0;
94 }
95
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);
1d09f67e 101 f->dump_string("namespace", item.namespace_name);
9f95a23c
TL
102 f->dump_string("schedule_time", item.schedule_time);
103 f->close_section(); // item
104 }
105 f->close_section(); // scheduled
106 }
107
108 friend std::ostream& operator<<(std::ostream& os, ScheduleStatus &d);
109
110private:
111
112 struct Item {
113 std::string pool_name;
114 std::string namespace_name;
115 std::string schedule_time;
116
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) {
121 }
122
123 bool operator<(const Item &rhs) const {
124 if (pool_name != rhs.pool_name) {
125 return pool_name < rhs.pool_name;
126 }
127 return namespace_name < rhs.namespace_name;
128 }
129 };
130
131 std::set<Item> scheduled;
132};
133
134std::ostream& operator<<(std::ostream& os, ScheduleStatus &s) {
135 TextTable tbl;
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);
139
140 for (auto &item : s.scheduled) {
141 tbl << item.pool_name << item.namespace_name << item.schedule_time
142 << TextTable::endrow;
143 }
144
145 os << tbl;
146 return os;
147}
148
149} // anonymous namespace
150
151void get_arguments_add(po::options_description *positional,
152 po::options_description *options) {
153 add_level_spec_options(options, false);
20effc67 154 add_schedule_options(positional, true);
9f95a23c
TL
155}
156
157int 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;
160
161 int r = get_level_spec_args(vm, &args);
162 if (r < 0) {
163 return r;
164 }
165 r = get_schedule_args(vm, true, &args);
166 if (r < 0) {
167 return r;
168 }
169
170 librados::Rados rados;
171 r = utils::init_rados(&rados);
172 if (r < 0) {
173 return r;
174 }
175
f67539c2 176 normalize_level_spec_args(&args);
9f95a23c
TL
177 r = utils::mgr_command(rados, "rbd trash purge schedule add", args,
178 &std::cout, &std::cerr);
179 if (r < 0) {
180 return r;
181 }
182
183 return 0;
184}
185
186void get_arguments_remove(po::options_description *positional,
187 po::options_description *options) {
188 add_level_spec_options(options, false);
20effc67 189 add_schedule_options(positional, false);
9f95a23c
TL
190}
191
192int 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;
195
196 int r = get_level_spec_args(vm, &args);
197 if (r < 0) {
198 return r;
199 }
200 r = get_schedule_args(vm, false, &args);
201 if (r < 0) {
202 return r;
203 }
204
205 librados::Rados rados;
206 r = utils::init_rados(&rados);
207 if (r < 0) {
208 return r;
209 }
210
f67539c2 211 normalize_level_spec_args(&args);
9f95a23c
TL
212 r = utils::mgr_command(rados, "rbd trash purge schedule remove", args,
213 &std::cout, &std::cerr);
214 if (r < 0) {
215 return r;
216 }
217
218 return 0;
219}
220
221void 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);
227}
228
229int 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;
232
233 int r = get_level_spec_args(vm, &args);
234 if (r < 0) {
235 return r;
236 }
237
238 at::Format::Formatter formatter;
239 r = utils::get_formatter(vm, &formatter);
240 if (r < 0) {
241 return r;
242 }
243
244 librados::Rados rados;
245 r = utils::init_rados(&rados);
246 if (r < 0) {
247 return r;
248 }
249
f67539c2 250 normalize_level_spec_args(&args);
9f95a23c
TL
251 std::stringstream out;
252 r = utils::mgr_command(rados, "rbd trash purge schedule list", args, &out,
253 &std::cerr);
254 if (r < 0) {
255 return r;
256 }
257
258 ScheduleList schedule_list(false);
259 r = schedule_list.parse(out.str());
260 if (r < 0) {
261 return r;
262 }
263
264 if (vm["recursive"].as<bool>()) {
265 if (formatter.get()) {
266 schedule_list.dump(formatter.get());
267 formatter->flush(std::cout);
268 } else {
269 std::cout << schedule_list;
270 }
271 } else {
272 auto schedule = schedule_list.find(args["level_spec"]);
273 if (schedule == nullptr) {
274 return -ENOENT;
275 }
276
277 if (formatter.get()) {
278 schedule->dump(formatter.get());
279 formatter->flush(std::cout);
280 } else {
281 std::cout << *schedule << std::endl;
282 }
283 }
284
285 return 0;
286}
287
288void 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);
292}
293
294int 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;
297
298 int r = get_level_spec_args(vm, &args);
299 if (r < 0) {
300 return r;
301 }
302
303 at::Format::Formatter formatter;
304 r = utils::get_formatter(vm, &formatter);
305 if (r < 0) {
306 return r;
307 }
308
309 librados::Rados rados;
310 r = utils::init_rados(&rados);
311 if (r < 0) {
312 return r;
313 }
314
f67539c2 315 normalize_level_spec_args(&args);
9f95a23c
TL
316 std::stringstream out;
317 r = utils::mgr_command(rados, "rbd trash purge schedule status", args, &out,
318 &std::cerr);
319 ScheduleStatus schedule_status;
320 r = schedule_status.parse(out.str());
321 if (r < 0) {
322 return r;
323 }
324
325 if (formatter.get()) {
326 schedule_status.dump(formatter.get());
327 formatter->flush(std::cout);
328 } else {
329 std::cout << schedule_status;
330 }
331
332 return 0;
333}
334
20effc67
TL
335Shell::SwitchArguments switched_arguments({"recursive", "R"});
336
9f95a23c
TL
337Shell::Action add_action(
338 {"trash", "purge", "schedule", "add"}, {}, "Add trash purge schedule.", "",
339 &get_arguments_add, &execute_add);
340Shell::Action remove_action(
341 {"trash", "purge", "schedule", "remove"},
342 {"trash", "purge", "schedule", "rm"}, "Remove trash purge schedule.",
343 "", &get_arguments_remove, &execute_remove);
344Shell::Action list_action(
345 {"trash", "purge", "schedule", "list"},
346 {"trash", "purge", "schedule", "ls"}, "List trash purge schedule.",
347 "", &get_arguments_list, &execute_list);
348Shell::Action status_action(
349 {"trash", "purge", "schedule", "status"}, {},
350 "Show trash purge schedule status.", "", &get_arguments_status,
351 &execute_status);
352
353} // namespace trash_purge_schedule
354} // namespace action
355} // namespace rbd