From: Kefu Chai Date: Tue, 30 Jan 2018 08:02:35 +0000 (+0800) Subject: crushtool: add --add-bucket X-Git-Tag: v13.0.2~393^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=4525003908f47dc8162c4778b00d87c87ea81dba;p=ceph.git crushtool: add --add-bucket Signed-off-by: Kefu Chai --- diff --git a/src/test/cli/crushtool/help.t b/src/test/cli/crushtool/help.t index c6f7c0f4d7fa..621f92ff6e3c 100755 --- a/src/test/cli/crushtool/help.t +++ b/src/test/cli/crushtool/help.t @@ -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 to start from , diff --git a/src/tools/crushtool.cc b/src/tools/crushtool.cc index 61ad4505eb61..8d3473c86952 100644 --- a/src/tools/crushtool.cc +++ b/src/tools/crushtool.cc @@ -21,6 +21,7 @@ #include #include +#include #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 to start from ,\n" @@ -238,13 +242,85 @@ struct layer_t { int size; }; +template +bool argparse_withargs(std::vector &args, + std::vector::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>; + string err; + if constexpr (std::is_same_v) { + opt->assign(*i); + } else if constexpr (is_same_v) { + *opt = strict_strtol(*i, 10, &err); + } else if constexpr (is_same_v) { + *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& 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 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;