]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: add `trash purge schedule` commands
authorMykola Golub <mgolub@suse.com>
Tue, 18 Feb 2020 15:35:16 +0000 (15:35 +0000)
committerMykola Golub <mgolub@suse.com>
Tue, 25 Feb 2020 09:52:22 +0000 (09:52 +0000)
Signed-off-by: Mykola Golub <mgolub@suse.com>
doc/man/8/rbd.rst
src/test/cli/rbd/help.t
src/tools/rbd/CMakeLists.txt
src/tools/rbd/action/TrashPurgeSchedule.cc [new file with mode: 0644]

index ad188909f0fbec3ccd0f625a8bf29d0e7a5ec590..b5a373584a213ddfb9ba24e6eeccb74bbef67135 100644 (file)
@@ -651,6 +651,18 @@ Commands
   you can not removed it unless use force. But an actively in-use by clones 
   or has snapshots can not be removed.
 
+:command:`trash purge schedule add` [-p | --pool *pool*] [--namespace *namespace*] *interval* [*start-time*]
+  Add trash purge schedule.
+
+:command:`trash purge schedule list` [-R | --recursive] [--format *format*] [--pretty-format] [-p | --pool *pool*] [--namespace *namespace*]
+  List trash purge schedule.
+
+:command:`trash purge schedule remove` [-p | --pool *pool*] [--namespace *namespace*] *interval* [*start-time*]
+  Remove trash purge schedule.
+
+:command:`trash purge schedule status` [-p | --pool *pool*] [--format *format*] [--pretty-format] [--namespace *namespace*]
+  Show trash purge schedule status.
+
 :command:`watch` *image-spec*
   Watch events on image.
 
index bf08a1410796912dac61f1919ce27273dd601e4b..fe3d4dc3efb1b9554cbc03a5f576b0f1b0402d1e 100644 (file)
       trash list (trash ls)             List trash images.
       trash move (trash mv)             Move an image to the trash.
       trash purge                       Remove all expired images from trash.
+      trash purge schedule add          Add trash purge schedule.
+      trash purge schedule list (... ls)
+                                        List trash purge schedule.
+      trash purge schedule remove (... rm)
+                                        Remove trash purge schedule.
+      trash purge schedule status       Show trash purge schedule status.
       trash remove (trash rm)           Remove an image from trash.
       trash restore                     Restore an image from trash.
       watch                             Watch events on image.
     --threshold arg       purges images until the current pool data usage is
                           reduced to X%, value range: 0.0-1.0
   
+  rbd help trash purge schedule add
+  usage: rbd trash purge schedule add [--pool <pool>] [--namespace <namespace>] 
+                                      <interval> <start-time> 
+  
+  Add trash purge schedule.
+  
+  Positional arguments
+    <interval>           schedule interval
+    <start-time>         schedule start time
+  
+  Optional arguments
+    -p [ --pool ] arg    pool name
+    --namespace arg      namespace name
+  
+  rbd help trash purge schedule list
+  usage: rbd trash purge schedule list [--pool <pool>] [--namespace <namespace>] 
+                                       [--recursive] [--format <format>] 
+                                       [--pretty-format] 
+  
+  List trash purge schedule.
+  
+  Optional arguments
+    -p [ --pool ] arg    pool name
+    --namespace arg      namespace name
+    -R [ --recursive ]   list all schedules
+    --format arg         output format (plain, json, or xml) [default: plain]
+    --pretty-format      pretty formatting (json and xml)
+  
+  rbd help trash purge schedule remove
+  usage: rbd trash purge schedule remove
+                                        [--pool <pool>] [--namespace <namespace>] 
+                                        <interval> <start-time> 
+  
+  Remove trash purge schedule.
+  
+  Positional arguments
+    <interval>           schedule interval
+    <start-time>         schedule start time
+  
+  Optional arguments
+    -p [ --pool ] arg    pool name
+    --namespace arg      namespace name
+  
+  rbd help trash purge schedule status
+  usage: rbd trash purge schedule status
+                                        [--pool <pool>] 
+                                        [--namespace <namespace>] 
+                                        [--format <format>] [--pretty-format] 
+  
+  Show trash purge schedule status.
+  
+  Optional arguments
+    -p [ --pool ] arg    pool name
+    --namespace arg      namespace name
+    --format arg         output format (plain, json, or xml) [default: plain]
+    --pretty-format      pretty formatting (json and xml)
+  
   rbd help trash remove
   usage: rbd trash remove [--pool <pool>] [--namespace <namespace>] 
                           [--image-id <image-id>] [--no-progress] [--force] 
index 2abf9341363eaf5630089fe8b84d7a94595d4308..2a185f05204dda7830ec3476fd24a61c363ebc9e 100644 (file)
@@ -47,6 +47,7 @@ set(rbd_srcs
   action/Snap.cc
   action/Sparsify.cc
   action/Status.cc
+  action/TrashPurgeSchedule.cc
   action/Trash.cc
   action/Watch.cc)
 
diff --git a/src/tools/rbd/action/TrashPurgeSchedule.cc b/src/tools/rbd/action/TrashPurgeSchedule.cc
new file mode 100644 (file)
index 0000000..b6282f9
--- /dev/null
@@ -0,0 +1,349 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "tools/rbd/ArgumentTypes.h"
+#include "tools/rbd/Schedule.h"
+#include "tools/rbd/Shell.h"
+#include "tools/rbd/Utils.h"
+#include "common/ceph_context.h"
+#include "common/ceph_json.h"
+#include "common/errno.h"
+#include "common/Formatter.h"
+#include "common/TextTable.h"
+#include "global/global_context.h"
+#include "include/stringify.h"
+
+#include <iostream>
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+#include <boost/program_options.hpp>
+
+#include "json_spirit/json_spirit.h"
+
+namespace rbd {
+namespace action {
+namespace trash_purge_schedule {
+
+namespace at = argument_types;
+namespace po = boost::program_options;
+
+namespace {
+
+class ScheduleStatus {
+public:
+  ScheduleStatus() {
+  }
+
+  int parse(const std::string &status) {
+    json_spirit::mValue json_root;
+    if(!json_spirit::read(status, json_root)) {
+      std::cerr << "rbd: invalid schedule status JSON received" << std::endl;
+      return -EBADMSG;
+    }
+
+    try {
+      auto &s = json_root.get_obj();
+
+      if (s["scheduled"].type() != json_spirit::array_type) {
+        std::cerr << "rbd: unexpected schedule JSON received: "
+                  << "scheduled is not array" << std::endl;
+        return -EBADMSG;
+      }
+
+      for (auto &item_val : s["scheduled"].get_array()) {
+        if (item_val.type() != json_spirit::obj_type) {
+          std::cerr << "rbd: unexpected schedule status JSON received: "
+                    << "schedule item is not object" << std::endl;
+          return -EBADMSG;
+        }
+
+        auto &item = item_val.get_obj();
+
+        if (item["pool_name"].type() != json_spirit::str_type) {
+          std::cerr << "rbd: unexpected schedule JSON received: "
+                    << "pool_name is not string" << std::endl;
+          return -EBADMSG;
+        }
+        auto pool_name = item["pool_name"].get_str();
+
+        if (item["namespace"].type() != json_spirit::str_type) {
+          std::cerr << "rbd: unexpected schedule JSON received: "
+                    << "namespace is not string" << std::endl;
+          return -EBADMSG;
+        }
+        auto namespace_name = item["namespace"].get_str();
+
+        if (item["schedule_time"].type() != json_spirit::str_type) {
+          std::cerr << "rbd: unexpected schedule JSON received: "
+                    << "schedule_time is not string" << std::endl;
+          return -EBADMSG;
+        }
+        auto schedule_time = item["schedule_time"].get_str();
+
+        scheduled.insert({pool_name, namespace_name, schedule_time});
+      }
+
+    } catch (std::runtime_error &) {
+      std::cerr << "rbd: invalid schedule JSON received" << std::endl;
+      return -EBADMSG;
+    }
+
+    return 0;
+  }
+
+  void dump(Formatter *f) {
+    f->open_array_section("scheduled");
+    for (auto &item : scheduled) {
+      f->open_object_section("item");
+      f->dump_string("pool", item.pool_name);
+      f->dump_string("namespce", item.namespace_name);
+      f->dump_string("schedule_time", item.schedule_time);
+      f->close_section(); // item
+    }
+    f->close_section(); // scheduled
+  }
+
+  friend std::ostream& operator<<(std::ostream& os, ScheduleStatus &d);
+
+private:
+
+  struct Item {
+    std::string pool_name;
+    std::string namespace_name;
+    std::string schedule_time;
+
+    Item(const std::string &pool_name, const std::string &namespace_name,
+         const std::string &schedule_time)
+      : pool_name(pool_name), namespace_name(namespace_name),
+        schedule_time(schedule_time) {
+    }
+
+    bool operator<(const Item &rhs) const {
+      if (pool_name != rhs.pool_name) {
+        return pool_name < rhs.pool_name;
+      }
+      return namespace_name < rhs.namespace_name;
+    }
+  };
+
+  std::set<Item> scheduled;
+};
+
+std::ostream& operator<<(std::ostream& os, ScheduleStatus &s) {
+  TextTable tbl;
+  tbl.define_column("POOL", TextTable::LEFT, TextTable::LEFT);
+  tbl.define_column("NAMESPACE", TextTable::LEFT, TextTable::LEFT);
+  tbl.define_column("SCHEDULE TIME", TextTable::LEFT, TextTable::LEFT);
+
+  for (auto &item : s.scheduled) {
+    tbl << item.pool_name << item.namespace_name << item.schedule_time
+        << TextTable::endrow;
+  }
+
+  os << tbl;
+  return os;
+}
+
+} // anonymous namespace
+
+void get_arguments_add(po::options_description *positional,
+                       po::options_description *options) {
+  add_level_spec_options(options, false);
+  add_schedule_options(positional);
+}
+
+int execute_add(const po::variables_map &vm,
+                const std::vector<std::string> &ceph_global_init_args) {
+  std::map<std::string, std::string> args;
+
+  int r = get_level_spec_args(vm, &args);
+  if (r < 0) {
+    return r;
+  }
+  r = get_schedule_args(vm, true, &args);
+  if (r < 0) {
+    return r;
+  }
+
+  librados::Rados rados;
+  r = utils::init_rados(&rados);
+  if (r < 0) {
+    return r;
+  }
+
+  r = utils::mgr_command(rados, "rbd trash purge schedule add", args,
+                         &std::cout, &std::cerr);
+  if (r < 0) {
+    return r;
+  }
+
+  return 0;
+}
+
+void get_arguments_remove(po::options_description *positional,
+                          po::options_description *options) {
+  add_level_spec_options(options, false);
+  add_schedule_options(positional);
+}
+
+int execute_remove(const po::variables_map &vm,
+                   const std::vector<std::string> &ceph_global_init_args) {
+  std::map<std::string, std::string> args;
+
+  int r = get_level_spec_args(vm, &args);
+  if (r < 0) {
+    return r;
+  }
+  r = get_schedule_args(vm, false, &args);
+  if (r < 0) {
+    return r;
+  }
+
+  librados::Rados rados;
+  r = utils::init_rados(&rados);
+  if (r < 0) {
+    return r;
+  }
+
+  r = utils::mgr_command(rados, "rbd trash purge schedule remove", args,
+                         &std::cout, &std::cerr);
+  if (r < 0) {
+    return r;
+  }
+
+  return 0;
+}
+
+void get_arguments_list(po::options_description *positional,
+                        po::options_description *options) {
+  add_level_spec_options(options, false);
+  options->add_options()
+    ("recursive,R", po::bool_switch(), "list all schedules");
+  at::add_format_options(options);
+}
+
+int execute_list(const po::variables_map &vm,
+                 const std::vector<std::string> &ceph_global_init_args) {
+  std::map<std::string, std::string> args;
+
+  int r = get_level_spec_args(vm, &args);
+  if (r < 0) {
+    return r;
+  }
+
+  at::Format::Formatter formatter;
+  r = utils::get_formatter(vm, &formatter);
+  if (r < 0) {
+    return r;
+  }
+
+  librados::Rados rados;
+  r = utils::init_rados(&rados);
+  if (r < 0) {
+    return r;
+  }
+
+  std::stringstream out;
+  r = utils::mgr_command(rados, "rbd trash purge schedule list", args, &out,
+                         &std::cerr);
+  if (r < 0) {
+    return r;
+  }
+
+  ScheduleList schedule_list(false);
+  r = schedule_list.parse(out.str());
+  if (r < 0) {
+    return r;
+  }
+
+  if (vm["recursive"].as<bool>()) {
+    if (formatter.get()) {
+      schedule_list.dump(formatter.get());
+      formatter->flush(std::cout);
+    } else {
+      std::cout << schedule_list;
+    }
+  } else {
+    auto schedule = schedule_list.find(args["level_spec"]);
+    if (schedule == nullptr) {
+      return -ENOENT;
+    }
+
+    if (formatter.get()) {
+      schedule->dump(formatter.get());
+      formatter->flush(std::cout);
+    } else {
+      std::cout << *schedule << std::endl;
+    }
+  }
+
+  return 0;
+}
+
+void get_arguments_status(po::options_description *positional,
+                          po::options_description *options) {
+  add_level_spec_options(options, false);
+  at::add_format_options(options);
+}
+
+int execute_status(const po::variables_map &vm,
+                   const std::vector<std::string> &ceph_global_init_args) {
+  std::map<std::string, std::string> args;
+
+  int r = get_level_spec_args(vm, &args);
+  if (r < 0) {
+    return r;
+  }
+
+  at::Format::Formatter formatter;
+  r = utils::get_formatter(vm, &formatter);
+  if (r < 0) {
+    return r;
+  }
+
+  librados::Rados rados;
+  r = utils::init_rados(&rados);
+  if (r < 0) {
+    return r;
+  }
+
+  std::stringstream out;
+  r = utils::mgr_command(rados, "rbd trash purge schedule status", args, &out,
+                         &std::cerr);
+  ScheduleStatus schedule_status;
+  r = schedule_status.parse(out.str());
+  if (r < 0) {
+    return r;
+  }
+
+  if (formatter.get()) {
+    schedule_status.dump(formatter.get());
+    formatter->flush(std::cout);
+  } else {
+    std::cout << schedule_status;
+  }
+
+  return 0;
+}
+
+Shell::Action add_action(
+  {"trash", "purge", "schedule", "add"}, {}, "Add trash purge schedule.", "",
+  &get_arguments_add, &execute_add);
+Shell::Action remove_action(
+  {"trash", "purge", "schedule", "remove"},
+  {"trash", "purge", "schedule", "rm"}, "Remove trash purge schedule.",
+  "", &get_arguments_remove, &execute_remove);
+Shell::Action list_action(
+  {"trash", "purge", "schedule", "list"},
+  {"trash", "purge", "schedule", "ls"}, "List trash purge schedule.",
+  "", &get_arguments_list, &execute_list);
+Shell::Action status_action(
+  {"trash", "purge", "schedule", "status"}, {},
+  "Show trash purge schedule status.", "", &get_arguments_status,
+  &execute_status);
+
+} // namespace trash_purge_schedule
+} // namespace action
+} // namespace rbd