]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crushtool: add --add-bucket
authorKefu Chai <kchai@redhat.com>
Tue, 30 Jan 2018 08:02:35 +0000 (16:02 +0800)
committerKefu Chai <kchai@redhat.com>
Tue, 30 Jan 2018 11:09:09 +0000 (19:09 +0800)
Signed-off-by: Kefu Chai <kchai@redhat.com>
src/test/cli/crushtool/help.t
src/tools/crushtool.cc

index c6f7c0f4d7fa6f55c9c17d1b0076beb3448b18f9..621f92ff6e3c9b6a585c26fb227f5ed1a60776e0 100755 (executable)
@@ -57,6 +57,9 @@
      -i mapfn --reweight-item name weight
                            reweight a given item (and adjust ancestor
                            weights as needed)
+     -i mapfn --add-bucket name type [--loc type name ...]
+                           insert a bucket into the hierachy at the given
+                           location
      -i mapfn --reweight   recalculate all bucket weights
      -i mapfn --create-simple-rule name root type mode
                            create crush rule <name> to start from <root>,
index 61ad4505eb61807935a4d18e5562e5b7350902a9..8d3473c86952747518a213c43ef7df94a8b9bdfa 100644 (file)
@@ -21,6 +21,7 @@
 #include <errno.h>
 
 #include <fstream>
+#include <type_traits>
 
 #include "common/debug.h"
 #include "common/errno.h"
@@ -164,6 +165,9 @@ void usage()
   cout << "   -i mapfn --reweight-item name weight\n";
   cout << "                         reweight a given item (and adjust ancestor\n"
        << "                         weights as needed)\n";
+  cout << "   -i mapfn --add-bucket name type [--loc type name ...]\n"
+       << "                         insert a bucket into the hierachy at the given\n"
+       << "                         location\n";
   cout << "   -i mapfn --reweight   recalculate all bucket weights\n";
   cout << "   -i mapfn --create-simple-rule name root type mode\n"
        << "                         create crush rule <name> to start from <root>,\n"
@@ -238,13 +242,85 @@ struct layer_t {
   int size;
 };
 
+template<typename... Args>
+bool argparse_withargs(std::vector<const char*> &args,
+                      std::vector<const char*>::iterator& i,
+                      std::ostream& oss,
+                      const char* opt,
+                      Args*... opts)
+{
+  if (!ceph_argparse_flag(args, i, opt, nullptr)) {
+    return false;
+  }
+  auto parse = [&](auto& opt) {
+    if (i == args.end()) {
+      oss << "expecting additional argument to " << opt;
+      return false;
+    }
+    using opt_t = std::remove_pointer_t<decay_t<decltype(opt)>>;
+    string err;
+    if constexpr (std::is_same_v<opt_t, string>) {
+      opt->assign(*i);
+    } else if constexpr (is_same_v<opt_t, int>) {
+      *opt = strict_strtol(*i, 10, &err);
+    } else if constexpr (is_same_v<opt_t, float>) {
+      *opt = strict_strtof(*i, &err);
+    }
+    i = args.erase(i);
+    if (err.empty())
+      return true;
+    else {
+      oss << err;
+      return false;
+    }
+  };
+  (... && parse(opts));
+  return true;
+}
+
+int do_add_bucket(CephContext* cct,
+                 const char* me,
+                 CrushWrapper& crush,
+                 const string& add_name,
+                 const string& add_type,
+                 const map<string,string>& add_loc) {
+  int bucketno;
+  if (crush.name_exists(add_name)) {
+    cerr << me << " bucket '" << add_name << "' already exists" << std::endl;
+    return -EEXIST;
+  }
+  int type = crush.get_type_id(add_type);
+  if (type <= 0) {
+    cerr << me << " bad bucket type: " << add_type << std::endl;
+    return -EINVAL;
+  }
+  if (int r = crush.add_bucket(0, 0, CRUSH_HASH_DEFAULT, type, 0, nullptr, nullptr, &bucketno);
+      r < 0) {
+    cerr << me << " unable to add bucket: " << cpp_strerror(r) << std::endl;
+    return r;
+  }
+  if (int r = crush.set_item_name(bucketno, add_name); r < 0) {
+    cerr << me << " bad bucket name: " << add_name << std::endl;
+    return r;
+  }
+  if (!add_loc.empty()) {
+    if (!crush.check_item_loc(cct, bucketno, add_loc, (int*)nullptr)) {
+      if (int r = crush.move_bucket(cct, bucketno, add_loc); r < 0) {
+       cerr << me << " error moving bucket '" << add_name << "' to " << add_loc << std::endl;
+       return r;
+      }
+    }
+  }
+  return 0;
+}
+
 int main(int argc, const char **argv)
 {
   vector<const char*> args;
   argv_to_vec(argc, argv, args);
 
   const char *me = argv[0];
-  std::string infn, srcfn, outfn, add_name, remove_name, reweight_name;
+  std::string infn, srcfn, outfn, add_name, add_type, remove_name, reweight_name;
   bool compile = false;
   bool decompile = false;
   bool check = false;
@@ -261,6 +337,7 @@ int main(int argc, const char **argv)
 
   bool reweight = false;
   int add_item = -1;
+  bool add_bucket = false;
   bool update_item = false;
   bool add_rule = false;
   std::string rule_name, rule_root, rule_type, rule_mode, rule_device_class;
@@ -419,6 +496,13 @@ int main(int argc, const char **argv)
       }
       add_name.assign(*i);
       i = args.erase(i);
+    } else if (argparse_withargs(args, i, err, "--add-bucket",
+                                &add_name, &add_type)) {
+      if (!err.str().empty()) {
+       cerr << err.str() << std::endl;
+       return EXIT_FAILURE;
+      }
+      add_bucket = true;
     } else if (ceph_argparse_witharg(args, i, &val, err, "--create-simple-rule", (char*)NULL)) {
       rule_name.assign(val);
       if (!err.str().empty()) {
@@ -638,7 +722,7 @@ int main(int argc, const char **argv)
     return EXIT_FAILURE;
   }
   if (!check && !compile && !decompile && !build && !test && !reweight && !adjust && !tree && !dump &&
-      add_item < 0 && !add_rule && !del_rule && full_location < 0 &&
+      add_item < 0 && !add_bucket && !add_rule && !del_rule && full_location < 0 &&
       remove_name.empty() && reweight_name.empty()) {
     cerr << "no action specified; -h for help" << std::endl;
     return EXIT_FAILURE;
@@ -931,6 +1015,14 @@ int main(int argc, const char **argv)
     }
   }
 
+  if (add_bucket) {
+    if (int r = do_add_bucket(cct.get(), me, crush, add_name, add_type, add_loc); !r) {
+      modified = true;
+    } else {
+      return r;
+    }
+  }
+
   if (add_rule) {
     if (crush.rule_exists(rule_name)) {
       cerr << "rule " << rule_name << " already exists" << std::endl;