$ crushtool -i "$TESTDIR/simple.template" --add-item 0 1.0 device0 --loc host host0 --loc cluster cluster0 -o one > /dev/null
$ crushtool -i one --add-item 1 1.0 device1 --loc host host0 --loc cluster cluster0 -o two > /dev/null
+ $ crushtool -i two --create-simple-rule simple-rule cluster0 host firstn -o two > /dev/null
+ $ crushtool -d two
+ # begin crush map
+
+ # devices
+ device 0 device0
+ device 1 device1
+
+ # types
+ type 0 device
+ type 1 host
+ type 2 cluster
+
+ # buckets
+ host host0 {
+ \tid -2\t\t# do not change unnecessarily (esc)
+ \t# weight 2.000 (esc)
+ \talg straw (esc)
+ \thash 0\t# rjenkins1 (esc)
+ \titem device0 weight 1.000 (esc)
+ \titem device1 weight 1.000 (esc)
+ }
+ cluster cluster0 {
+ \tid -1\t\t# do not change unnecessarily (esc)
+ \t# weight 2.000 (esc)
+ \talg straw (esc)
+ \thash 0\t# rjenkins1 (esc)
+ \titem host0 weight 2.000 (esc)
+ }
+
+ # rules
+ rule data {
+ \truleset 0 (esc)
+ \ttype replicated (esc)
+ \tmin_size 1 (esc)
+ \tmax_size 10 (esc)
+ \tstep take cluster0 (esc)
+ \tstep chooseleaf firstn 0 type host (esc)
+ \tstep emit (esc)
+ }
+ rule metadata {
+ \truleset 1 (esc)
+ \ttype replicated (esc)
+ \tmin_size 1 (esc)
+ \tmax_size 10 (esc)
+ \tstep take cluster0 (esc)
+ \tstep chooseleaf firstn 0 type host (esc)
+ \tstep emit (esc)
+ }
+ rule rbd {
+ \truleset 2 (esc)
+ \ttype replicated (esc)
+ \tmin_size 1 (esc)
+ \tmax_size 10 (esc)
+ \tstep take cluster0 (esc)
+ \tstep chooseleaf firstn 0 type host (esc)
+ \tstep emit (esc)
+ }
+ rule simple-rule {
+ \truleset 3 (esc)
+ \ttype replicated (esc)
+ \tmin_size 1 (esc)
+ \tmax_size 10 (esc)
+ \tstep take cluster0 (esc)
+ \tstep chooseleaf firstn 0 type host (esc)
+ \tstep emit (esc)
+ }
+
+ # end crush map
+ $ crushtool -i two --remove-rule simple-rule -o two > /dev/null
+ $ crushtool -d two
+ # begin crush map
+
+ # devices
+ device 0 device0
+ device 1 device1
+
+ # types
+ type 0 device
+ type 1 host
+ type 2 cluster
+
+ # buckets
+ host host0 {
+ \tid -2\t\t# do not change unnecessarily (esc)
+ \t# weight 2.000 (esc)
+ \talg straw (esc)
+ \thash 0\t# rjenkins1 (esc)
+ \titem device0 weight 1.000 (esc)
+ \titem device1 weight 1.000 (esc)
+ }
+ cluster cluster0 {
+ \tid -1\t\t# do not change unnecessarily (esc)
+ \t# weight 2.000 (esc)
+ \talg straw (esc)
+ \thash 0\t# rjenkins1 (esc)
+ \titem host0 weight 2.000 (esc)
+ }
+
+ # rules
+ rule data {
+ \truleset 0 (esc)
+ \ttype replicated (esc)
+ \tmin_size 1 (esc)
+ \tmax_size 10 (esc)
+ \tstep take cluster0 (esc)
+ \tstep chooseleaf firstn 0 type host (esc)
+ \tstep emit (esc)
+ }
+ rule metadata {
+ \truleset 1 (esc)
+ \ttype replicated (esc)
+ \tmin_size 1 (esc)
+ \tmax_size 10 (esc)
+ \tstep take cluster0 (esc)
+ \tstep chooseleaf firstn 0 type host (esc)
+ \tstep emit (esc)
+ }
+ rule rbd {
+ \truleset 2 (esc)
+ \ttype replicated (esc)
+ \tmin_size 1 (esc)
+ \tmax_size 10 (esc)
+ \tstep take cluster0 (esc)
+ \tstep chooseleaf firstn 0 type host (esc)
+ \tstep emit (esc)
+ }
+
+ # end crush map
$ crushtool -d two -o final
$ cmp final "$TESTDIR/simple.template.two"
$ crushtool -i two --add-item 1 1.0 device1 --loc host host0 --loc cluster cluster0 -o three 2>/dev/null >/dev/null || echo FAIL
reweight a given item (and adjust ancestor
weights as needed)
-i mapfn --reweight recalculate all bucket weights
+ -i mapfn --create-simple-rule name root type mode
+ create crush rule <name> to start from <root>,
+ replicate across buckets of type <type>, using
+ a choose mode of <firstn|indep>
+ -i mapfn --remove-rule name
+ remove the specified crush rule
Options for the display/test stage
[--outfn|-o outfile]
specify output for modified crush map
+
$ crushtool --help-output
data output from testing routine ...
absolute_weights
cout << " reweight a given item (and adjust ancestor\n"
<< " weights as needed)\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"
+ << " replicate across buckets of type <type>, using\n"
+ << " a choose mode of <firstn|indep>\n";
+ cout << " -i mapfn --remove-rule name\n"
+ << " remove the specified crush rule\n";
cout << "\n";
cout << "Options for the display/test stage\n";
cout << "\n";
bool reweight = false;
int add_item = -1;
bool update_item = false;
+ bool add_rule = false;
+ std::string rule_name, rule_root, rule_type, rule_mode;
+ bool del_rule = false;
float add_weight = 0;
map<string,string> add_loc;
float reweight_weight = 0;
}
add_name.assign(*i);
i = args.erase(i);
+ } else if (ceph_argparse_witharg(args, i, &val, err, "--create-simple-rule", (char*)NULL)) {
+ rule_name.assign(val);
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ return EXIT_FAILURE;
+ }
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --create-simple-rule" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ rule_root.assign(*i);
+ i = args.erase(i);
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --create-simple-rule" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ rule_type.assign(*i);
+ i = args.erase(i);
+ if (i == args.end()) {
+ cerr << "expecting additional argument to --create-simple-rule" << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ rule_mode.assign(*i);
+ i = args.erase(i);
+
+ cout << "--create-simple-rule:"
+ << " name=" << rule_name
+ << " root=" << rule_root
+ << " type=" << rule_type
+ << " mode=" << rule_mode
+ << std::endl;
+ add_rule = true;
+ } else if (ceph_argparse_witharg(args, i, &val, "--remove-rule", (char*)NULL)) {
+ rule_name.assign(val);
+ if (!err.str().empty()) {
+ cerr << err.str() << std::endl;
+ return EXIT_FAILURE;
+ }
+ del_rule = true;
} else if (ceph_argparse_witharg(args, i, &val, "--loc", (char*)NULL)) {
std::string type(val);
if (i == args.end()) {
return EXIT_FAILURE;
}
if (!check && !compile && !decompile && !build && !test && !reweight && !adjust && !tree && !dump &&
- add_item < 0 && full_location < 0 &&
+ add_item < 0 && !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;
}
}
+ if (add_rule) {
+ if (crush.rule_exists(rule_name)) {
+ cerr << "rule " << rule_name << " already exists" << std::endl;
+ return EXIT_FAILURE;
+ }
+ int r = crush.add_simple_ruleset(rule_name, rule_root, rule_type, rule_mode,
+ pg_pool_t::TYPE_REPLICATED, &err);
+ if (r < 0) {
+ cerr << err.str() << std::endl;
+ return EXIT_FAILURE;
+ }
+ modified = true;
+ }
+
+ if (del_rule) {
+ if (!crush.rule_exists(rule_name)) {
+ cerr << "rule " << rule_name << " does not exist" << std::endl;
+ return 0;
+ }
+ int ruleno = crush.get_rule_id(rule_name);
+ assert(ruleno >= 0);
+ int r = crush.remove_rule(ruleno);
+ if (r < 0) {
+ cerr << "fail to remove rule " << rule_name << std::endl;
+ return EXIT_FAILURE;
+ }
+ modified = true;
+ }
+
if (reweight) {
crush.reweight(g_ceph_context);
modified = true;