X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftools%2Fcrushtool.cc;fp=src%2Fceph%2Fsrc%2Ftools%2Fcrushtool.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=7ecae9529ce9a3cf08ac265b948b58c4c1255538;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/tools/crushtool.cc b/src/ceph/src/tools/crushtool.cc deleted file mode 100644 index 7ecae95..0000000 --- a/src/ceph/src/tools/crushtool.cc +++ /dev/null @@ -1,1054 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2004-2006 Sage Weil - * Copyright (C) 2014 Cloudwatt - * - * Author: Loic Dachary - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ - -#include -#include -#include -#include - -#include - -#include "common/debug.h" -#include "common/errno.h" -#include "common/config.h" -#include "common/Formatter.h" - -#include "common/ceph_argparse.h" -#include "include/stringify.h" -#include "global/global_context.h" -#include "global/global_init.h" -#include "osd/OSDMap.h" -#include "crush/CrushWrapper.h" -#include "crush/CrushCompiler.h" -#include "crush/CrushTester.h" -#include "include/assert.h" - -#define dout_context g_ceph_context -#define dout_subsys ceph_subsys_crush - -using namespace std; - -const char *infn = "stdin"; - -static int get_fd_data(int fd, bufferlist &bl) -{ - - uint64_t total = 0; - do { - ssize_t bytes = bl.read_fd(fd, 1024*1024); - if (bytes < 0) { - cerr << "read_fd error " << cpp_strerror(-bytes) << "\n"; - return -1; - } - - if (bytes == 0) - break; - - total += bytes; - } while(true); - - assert(bl.length() == total); - return 0; -} - -//////////////////////////////////////////////////////////////////////////// - -void data_analysis_usage() -{ -cout << "data output from testing routine ...\n"; -cout << " absolute_weights\n"; -cout << " the decimal weight of each OSD\n"; -cout << " data layout: ROW MAJOR\n"; -cout << " OSD id (int), weight (int)\n"; -cout << " batch_device_expected_utilization_all\n"; -cout << " the expected number of objects each OSD should receive per placement batch\n"; -cout << " which may be a decimal value\n"; -cout << " data layout: COLUMN MAJOR\n"; -cout << " round (int), objects expected on OSD 0...OSD n (float)\n"; -cout << " batch_device_utilization_all\n"; -cout << " the number of objects stored on each OSD during each placement round\n"; -cout << " data layout: COLUMN MAJOR\n"; -cout << " round (int), objects stored on OSD 0...OSD n (int)\n"; -cout << " device_utilization_all\n"; -cout << " the number of objects stored on each OSD at the end of placements\n"; -cout << " data_layout: ROW MAJOR\n"; -cout << " OSD id (int), objects stored (int), objects expected (float)\n"; -cout << " device_utilization\n"; -cout << " the number of objects stored on each OSD marked 'up' at the end of placements\n"; -cout << " data_layout: ROW MAJOR\n"; -cout << " OSD id (int), objects stored (int), objects expected (float)\n"; -cout << " placement_information\n"; -cout << " the map of input -> OSD\n"; -cout << " data_layout: ROW MAJOR\n"; -cout << " input (int), OSD's mapped (int)\n"; -cout << " proportional_weights_all\n"; -cout << " the proportional weight of each OSD specified in the CRUSH map\n"; -cout << " data_layout: ROW MAJOR\n"; -cout << " OSD id (int), proportional weight (float)\n"; -cout << " proportional_weights\n"; -cout << " the proportional weight of each 'up' OSD specified in the CRUSH map\n"; -cout << " data_layout: ROW MAJOR\n"; -cout << " OSD id (int), proportional weight (float)\n"; -} - -void usage() -{ - cout << "usage: crushtool ...\n"; - cout << "\n"; - cout << "Display, modify and test a crush map\n"; - cout << "\n"; - cout << "There are five stages, running one after the other:\n"; - cout << "\n"; - cout << " - input/build\n"; - cout << " - tunables adjustments\n"; - cout << " - modifications\n"; - cout << " - display/test\n"; - cout << " - output\n"; - cout << "\n"; - cout << "Options that are not specific to a stage.\n"; - cout << "\n"; - cout << " [--infn|-i infile]\n"; - cout << " read the crush map from infile\n"; - cout << "\n"; - cout << "Options for the input/build stage\n"; - cout << "\n"; - cout << " --decompile|-d map decompile a crush map to source\n"; - cout << " [--outfn|-o outfile]\n"; - cout << " specify output for for (de)compilation\n"; - cout << " --compile|-c map.txt compile a map from source\n"; - cout << " --enable-unsafe-tunables\n"; - cout << " compile with unsafe tunables\n"; - cout << " --build --num_osds N layer1 ...\n"; - cout << " build a new map, where each 'layer' is\n"; - cout << " 'name (uniform|straw2|straw|list|tree) size'\n"; - cout << "\n"; - cout << "Options for the tunables adjustments stage\n"; - cout << "\n"; - cout << " --set-choose-local-tries N\n"; - cout << " set choose local retries before re-descent\n"; - cout << " --set-choose-local-fallback-tries N\n"; - cout << " set choose local retries using fallback\n"; - cout << " permutation before re-descent\n"; - cout << " --set-choose-total-tries N\n"; - cout << " set choose total descent attempts\n"; - cout << " --set-chooseleaf-descend-once <0|1>\n"; - cout << " set chooseleaf to (not) retry the recursive descent\n"; - cout << " --set-chooseleaf-vary-r <0|1>\n"; - cout << " set chooseleaf to (not) vary r based on parent\n"; - cout << " --set-chooseleaf-stable <0|1>\n"; - cout << " set chooseleaf firstn to (not) return stable results\n"; - cout << "\n"; - cout << "Options for the modifications stage\n"; - cout << "\n"; - cout << " -i mapfn --add-item id weight name [--loc type name ...]\n"; - cout << " insert an item into the hierarchy at the\n"; - cout << " given location\n"; - cout << " -i mapfn --update-item id weight name [--loc type name ...]\n"; - cout << " insert or move an item into the hierarchy at the\n"; - cout << " given location\n"; - cout << " -i mapfn --remove-item name\n" - << " remove the given item\n"; - cout << " -i mapfn --reweight-item name weight\n"; - 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 to start from ,\n" - << " replicate across buckets of type , using\n" - << " a choose mode of \n"; - cout << " -i mapfn --create-replicated-rule name root type\n" - << " create crush rule to start from ,\n" - << " replicate across buckets of type \n"; - cout << " --device-class \n"; - cout << " use device class for new rule\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"; - cout << " -f --format the format of --dump, defaults to json-pretty\n"; - cout << " can be one of json, json-pretty, xml, xml-pretty,\n"; - cout << " table, table-kv, html, html-pretty\n"; - cout << " --dump dump the crush map\n"; - cout << " --tree print map summary as a tree\n"; - cout << " --check [max_id] check if any item is referencing an unknown name/type\n"; - cout << " -i mapfn --show-location id\n"; - cout << " show location for given device id\n"; - cout << " -i mapfn --test test a range of inputs on the map\n"; - cout << " [--min-x x] [--max-x x] [--x x]\n"; - cout << " [--min-rule r] [--max-rule r] [--rule r] [--ruleset rs]\n"; - cout << " [--num-rep n]\n"; - cout << " [--pool-id n] specifies pool id\n"; - cout << " [--batches b] split the CRUSH mapping into b > 1 rounds\n"; - cout << " [--weight|-w devno weight]\n"; - cout << " where weight is 0 to 1.0\n"; - cout << " [--simulate] simulate placements using a random\n"; - cout << " number generator in place of the CRUSH\n"; - cout << " algorithm\n"; - cout << " --show-utilization show OSD usage\n"; - cout << " --show-utilization-all\n"; - cout << " include zero weight items\n"; - cout << " --show-statistics show chi squared statistics\n"; - cout << " --show-mappings show mappings\n"; - cout << " --show-bad-mappings show bad mappings\n"; - cout << " --show-choose-tries show choose tries histogram\n"; - cout << " --output-name name\n"; - cout << " prepend the data file(s) generated during the\n"; - cout << " testing routine with name\n"; - cout << " --output-csv\n"; - cout << " export select data generated during testing routine\n"; - cout << " to CSV files for off-line post-processing\n"; - cout << " use --help-output for more information\n"; - cout << "\n"; - cout << "Options for the output stage\n"; - cout << "\n"; - cout << " [--outfn|-o outfile]\n"; - cout << " specify output for modified crush map\n"; - cout << "\n"; -} - -struct bucket_types_t { - const char *name; - int type; -} bucket_types[] = { - { "uniform", CRUSH_BUCKET_UNIFORM }, - { "list", CRUSH_BUCKET_LIST }, - { "straw", CRUSH_BUCKET_STRAW }, - { "straw2", CRUSH_BUCKET_STRAW2 }, - { "tree", CRUSH_BUCKET_TREE }, - { 0, 0 }, -}; - -struct layer_t { - const char *name; - const char *buckettype; - int size; -}; - -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; - bool compile = false; - bool decompile = false; - bool check = false; - int max_id = -1; - bool test = false; - bool display = false; - bool tree = false; - string dump_format = "json-pretty"; - bool dump = false; - int full_location = -1; - bool write_to_file = false; - int verbose = 0; - bool unsafe_tunables = false; - - 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, rule_device_class; - bool del_rule = false; - float add_weight = 0; - map add_loc; - float reweight_weight = 0; - - bool adjust = false; - - int build = 0; - int num_osds =0; - vector layers; - - int choose_local_tries = -1; - int choose_local_fallback_tries = -1; - int choose_total_tries = -1; - int chooseleaf_descend_once = -1; - int chooseleaf_vary_r = -1; - int chooseleaf_stable = -1; - int straw_calc_version = -1; - int allowed_bucket_algs = -1; - - CrushWrapper crush; - - CrushTester tester(crush, cout); - - // we use -c, don't confuse the generic arg parsing - // only parse arguments from CEPH_ARGS, if in the environment - vector env_args; - env_to_vec(env_args); - auto cct = global_init(NULL, env_args, CEPH_ENTITY_TYPE_CLIENT, - CODE_ENVIRONMENT_UTILITY, - CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); - // crushtool times out occasionally when quits. so do not - // release the g_ceph_context. - cct->get(); - common_init_finish(g_ceph_context); - - int x; - float y; - long long z; - - std::string val; - std::ostringstream err; - int tmp; - for (std::vector::iterator i = args.begin(); i != args.end(); ) { - if (ceph_argparse_double_dash(args, i)) { - break; - } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) { - usage(); - return EXIT_SUCCESS; - } else if (ceph_argparse_witharg(args, i, &val, "-d", "--decompile", (char*)NULL)) { - infn = val; - decompile = true; - } else if (ceph_argparse_witharg(args, i, &val, "-i", "--infn", (char*)NULL)) { - infn = val; - } else if (ceph_argparse_witharg(args, i, &val, "-o", "--outfn", (char*)NULL)) { - outfn = val; - } else if (ceph_argparse_flag(args, i, "-v", "--verbose", (char*)NULL)) { - verbose += 1; - } else if (ceph_argparse_flag(args, i, "--tree", (char*)NULL)) { - tree = true; - } else if (ceph_argparse_witharg(args, i, &val, "-f", "--format", (char*)NULL)) { - dump_format = val; - } else if (ceph_argparse_flag(args, i, "--dump", (char*)NULL)) { - dump = true; - } else if (ceph_argparse_flag(args, i, "--show_utilization", (char*)NULL)) { - display = true; - tester.set_output_utilization(true); - } else if (ceph_argparse_flag(args, i, "--show_utilization_all", (char*)NULL)) { - display = true; - tester.set_output_utilization_all(true); - } else if (ceph_argparse_flag(args, i, "--show_statistics", (char*)NULL)) { - display = true; - tester.set_output_statistics(true); - } else if (ceph_argparse_flag(args, i, "--show_mappings", (char*)NULL)) { - display = true; - tester.set_output_mappings(true); - } else if (ceph_argparse_flag(args, i, "--show_bad_mappings", (char*)NULL)) { - display = true; - tester.set_output_bad_mappings(true); - } else if (ceph_argparse_flag(args, i, "--show_choose_tries", (char*)NULL)) { - display = true; - tester.set_output_choose_tries(true); - } else if (ceph_argparse_witharg(args, i, &val, "-c", "--compile", (char*)NULL)) { - srcfn = val; - compile = true; - } else if (ceph_argparse_witharg(args, i, &max_id, err, "--check", (char*)NULL)) { - check = true; - } else if (ceph_argparse_flag(args, i, "-t", "--test", (char*)NULL)) { - test = true; - } else if (ceph_argparse_witharg(args, i, &full_location, err, "--show-location", (char*)NULL)) { - } else if (ceph_argparse_flag(args, i, "-s", "--simulate", (char*)NULL)) { - tester.set_random_placement(); - } else if (ceph_argparse_flag(args, i, "--enable-unsafe-tunables", (char*)NULL)) { - unsafe_tunables = true; - } else if (ceph_argparse_witharg(args, i, &choose_local_tries, err, - "--set_choose_local_tries", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_witharg(args, i, &choose_local_fallback_tries, err, - "--set_choose_local_fallback_tries", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_witharg(args, i, &choose_total_tries, err, - "--set_choose_total_tries", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_witharg(args, i, &chooseleaf_descend_once, err, - "--set_chooseleaf_descend_once", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_witharg(args, i, &chooseleaf_vary_r, err, - "--set_chooseleaf_vary_r", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_witharg(args, i, &chooseleaf_stable, err, - "--set_chooseleaf_stable", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_witharg(args, i, &straw_calc_version, err, - "--set_straw_calc_version", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_witharg(args, i, &allowed_bucket_algs, err, - "--set_allowed_bucket_algs", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_flag(args, i, "--reweight", (char*)NULL)) { - reweight = true; - } else if (ceph_argparse_witharg(args, i, &add_item, err, "--add_item", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - if (i == args.end()) { - cerr << "expecting additional argument to --add-item" << std::endl; - return EXIT_FAILURE; - } - add_weight = atof(*i); - i = args.erase(i); - if (i == args.end()) { - cerr << "expecting additional argument to --add-item" << std::endl; - return EXIT_FAILURE; - } - add_name.assign(*i); - i = args.erase(i); - } else if (ceph_argparse_witharg(args, i, &add_item, err, "--update_item", (char*)NULL)) { - update_item = true; - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - if (i == args.end()) { - cerr << "expecting additional argument to --update-item" << std::endl; - return EXIT_FAILURE; - } - add_weight = atof(*i); - i = args.erase(i); - if (i == args.end()) { - cerr << "expecting additional argument to --update-item" << std::endl; - return EXIT_FAILURE; - } - 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, err, "--create-replicated-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-replicated-rule" << std::endl; - return EXIT_FAILURE; - } - - rule_root.assign(*i); - i = args.erase(i); - if (i == args.end()) { - cerr << "expecting additional argument to --create-replicated-rule" << std::endl; - return EXIT_FAILURE; - } - - rule_type.assign(*i); - i = args.erase(i); - rule_mode = "firstn"; - - cout << "--create-replicated-rule:" - << " name=" << rule_name - << " root=" << rule_root - << " type=" << rule_type - << std::endl; - add_rule = true; - - } else if (ceph_argparse_witharg(args, i, &val, "--device-class", (char*)NULL)) { - rule_device_class.assign(val); - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - } 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()) { - cerr << "expecting additional argument to --loc" << std::endl; - return EXIT_FAILURE; - } - std::string name(*i); - i = args.erase(i); - add_loc[type] = name; - } else if (ceph_argparse_flag(args, i, "--output-csv", (char*)NULL)) { - write_to_file = true; - tester.set_output_data_file(true); - tester.set_output_csv(true); - } else if (ceph_argparse_flag(args, i, "--help-output", (char*)NULL)) { - data_analysis_usage(); - return EXIT_SUCCESS; - } else if (ceph_argparse_witharg(args, i, &val, "--output-name", (char*)NULL)) { - std::string name(val); - if (i == args.end()) { - cerr << "expecting additional argument to --output-name" << std::endl; - return EXIT_FAILURE; - } - else { - tester.set_output_data_file_name(name + "-"); - } - } else if (ceph_argparse_witharg(args, i, &val, "--remove_item", (char*)NULL)) { - remove_name = val; - } else if (ceph_argparse_witharg(args, i, &val, "--reweight_item", (char*)NULL)) { - reweight_name = val; - if (i == args.end()) { - cerr << "expecting additional argument to --reweight-item" << std::endl; - return EXIT_FAILURE; - } - reweight_weight = atof(*i); - i = args.erase(i); - } else if (ceph_argparse_flag(args, i, "--build", (char*)NULL)) { - build = true; - } else if (ceph_argparse_witharg(args, i, &num_osds, err, "--num_osds", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - } else if (ceph_argparse_witharg(args, i, &x, err, "--num_rep", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_num_rep(x); - } else if (ceph_argparse_witharg(args, i, &x, err, "--max_x", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_max_x(x); - } else if (ceph_argparse_witharg(args, i, &x, err, "--min_x", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_min_x(x); - } else if (ceph_argparse_witharg(args, i, &z, err, "--pool_id", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_pool_id(z); - } else if (ceph_argparse_witharg(args, i, &x, err, "--x", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_x(x); - } else if (ceph_argparse_witharg(args, i, &x, err, "--max_rule", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_max_rule(x); - } else if (ceph_argparse_witharg(args, i, &x, err, "--min_rule", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_min_rule(x); - } else if (ceph_argparse_witharg(args, i, &x, err, "--rule", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_rule(x); - } else if (ceph_argparse_witharg(args, i, &x, err, "--ruleset", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_ruleset(x); - } else if (ceph_argparse_witharg(args, i, &x, err, "--batches", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_batches(x); - } else if (ceph_argparse_witharg(args, i, &y, err, "--mark-down-ratio", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_device_down_ratio(y); - } else if (ceph_argparse_witharg(args, i, &y, err, "--mark-down-bucket-ratio", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - tester.set_bucket_down_ratio(y); - } else if (ceph_argparse_witharg(args, i, &tmp, err, "--weight", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - return EXIT_FAILURE; - } - int dev = tmp; - if (i == args.end()) { - cerr << "expecting additional argument to --weight" << std::endl; - return EXIT_FAILURE; - } - float f = atof(*i); - i = args.erase(i); - tester.set_device_weight(dev, f); - } - else { - ++i; - } - } - - if (test && !check && !display && !write_to_file) { - cerr << "WARNING: no output selected; use --output-csv or --show-X" << std::endl; - } - - if (decompile + compile + build > 1) { - cerr << "cannot specify more than one of compile, decompile, and build" << std::endl; - return EXIT_FAILURE; - } - if (!check && !compile && !decompile && !build && !test && !reweight && !adjust && !tree && !dump && - 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 ((!build) && (!args.empty())) { - cerr << "unrecognized arguments: " << args << std::endl; - return EXIT_FAILURE; - } - else { - if ((args.size() % 3) != 0U) { - cerr << "remaining args: " << args << std::endl; - cerr << "layers must be specified with 3-tuples of (name, buckettype, size)" - << std::endl; - return EXIT_FAILURE; - } - for (size_t j = 0; j < args.size(); j += 3) { - layer_t l; - l.name = args[j]; - l.buckettype = args[j+1]; - l.size = atoi(args[j+2]); - layers.push_back(l); - } - } - - /* - if (outfn) cout << "outfn " << outfn << std::endl; - if (cinfn) cout << "cinfn " << cinfn << std::endl; - if (dinfn) cout << "dinfn " << dinfn << std::endl; - */ - - bool modified = false; - - // input ---- - - if (!infn.empty()) { - bufferlist bl; - std::string error; - - int r = 0; - if (infn == "-") { - if (isatty(STDIN_FILENO)) { - cerr << "stdin must not be from a tty" << std::endl; - return EXIT_FAILURE; - } - r = get_fd_data(STDIN_FILENO, bl); - if (r < 0) { - cerr << "error reading data from STDIN" << std::endl; - return EXIT_FAILURE; - } - } else { - r = bl.read_file(infn.c_str(), &error); - if (r < 0) { - cerr << me << ": error reading '" << infn << "': " - << error << std::endl; - return EXIT_FAILURE; - } - } - bufferlist::iterator p = bl.begin(); - try { - crush.decode(p); - } catch(...) { - cerr << me << ": unable to decode " << infn << std::endl; - return EXIT_FAILURE; - } - } - - if (compile) { - crush.create(); - - // read the file - ifstream in(srcfn.c_str()); - if (!in.is_open()) { - cerr << "input file " << srcfn << " not found" << std::endl; - return -ENOENT; - } - - CrushCompiler cc(crush, cerr, verbose); - if (unsafe_tunables) - cc.enable_unsafe_tunables(); - int r = cc.compile(in, srcfn.c_str()); - if (r < 0) - return EXIT_FAILURE; - - modified = true; - } - - if (build) { - if (layers.empty()) { - cerr << me << ": must specify at least one layer" << std::endl; - return EXIT_FAILURE; - } - - crush.create(); - - vector lower_items; - vector lower_weights; - - crush.set_max_devices(num_osds); - for (int i=0; i::iterator p = layers.begin(); p != layers.end(); ++p, type++) { - layer_t &l = *p; - - dout(2) << "layer " << type - << " " << l.name - << " bucket type " << l.buckettype - << " " << l.size - << dendl; - - crush.set_type_name(type, l.name); - - int buckettype = -1; - for (int i = 0; bucket_types[i].name; i++) - if (l.buckettype && strcmp(l.buckettype, bucket_types[i].name) == 0) { - buckettype = bucket_types[i].type; - break; - } - if (buckettype < 0) { - cerr << "unknown bucket type '" << l.buckettype << "'" << std::endl; - return EXIT_FAILURE; - } - - // build items - vector cur_items; - vector cur_weights; - unsigned lower_pos = 0; // lower pos - - dout(2) << "lower_items " << lower_items << dendl; - dout(2) << "lower_weights " << lower_weights << dendl; - - int i = 0; - while (1) { - if (lower_pos == lower_items.size()) - break; - - int items[num_osds]; - int weights[num_osds]; - - int weight = 0; - int j; - for (j=0; j roots; - crush.find_roots(&roots); - if (roots.size() > 1) { - cerr << "The crush rulesets will use the root " << root << "\n" - << "and ignore the others.\n" - << "There are " << roots.size() << " roots, they can be\n" - << "grouped into a single root by appending something like:\n" - << " root straw 0\n" - << std::endl; - } - } - - if (OSDMap::build_simple_crush_rules(g_ceph_context, crush, root, &cerr)) - return EXIT_FAILURE; - - modified = true; - } - - // mutate ---- - - if (choose_local_tries >= 0) { - crush.set_choose_local_tries(choose_local_tries); - modified = true; - } - if (choose_local_fallback_tries >= 0) { - crush.set_choose_local_fallback_tries(choose_local_fallback_tries); - modified = true; - } - if (choose_total_tries >= 0) { - crush.set_choose_total_tries(choose_total_tries); - modified = true; - } - if (chooseleaf_descend_once >= 0) { - crush.set_chooseleaf_descend_once(chooseleaf_descend_once); - modified = true; - } - if (chooseleaf_vary_r >= 0) { - crush.set_chooseleaf_vary_r(chooseleaf_vary_r); - modified = true; - } - if (chooseleaf_stable >= 0) { - crush.set_chooseleaf_stable(chooseleaf_stable); - modified = true; - } - if (straw_calc_version >= 0) { - crush.set_straw_calc_version(straw_calc_version); - modified = true; - } - if (allowed_bucket_algs >= 0) { - crush.set_allowed_bucket_algs(allowed_bucket_algs); - modified = true; - } - - if (!reweight_name.empty()) { - cout << me << " reweighting item " << reweight_name << " to " << reweight_weight << std::endl; - int r; - if (!crush.name_exists(reweight_name)) { - cerr << " name " << reweight_name << " dne" << std::endl; - r = -ENOENT; - } else { - int item = crush.get_item_id(reweight_name); - r = crush.adjust_item_weightf(g_ceph_context, item, reweight_weight); - } - if (r >= 0) - modified = true; - else { - cerr << me << " " << cpp_strerror(r) << std::endl; - return r; - } - } - - if (!remove_name.empty()) { - cout << me << " removing item " << remove_name << std::endl; - int r; - if (!crush.name_exists(remove_name)) { - cerr << " name " << remove_name << " dne" << std::endl; - r = -ENOENT; - } else { - int remove_item = crush.get_item_id(remove_name); - r = crush.remove_item(g_ceph_context, remove_item, false); - } - if (r == 0) - modified = true; - else { - cerr << me << " " << cpp_strerror(r) << std::endl; - return r; - } - } - - if (add_item >= 0) { - int r; - if (update_item) { - r = crush.update_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc); - } else { - r = crush.insert_item(g_ceph_context, add_item, add_weight, add_name.c_str(), add_loc); - } - if (r >= 0) { - modified = true; - } else { - cerr << me << " " << cpp_strerror(r) << std::endl; - return r; - } - } - - 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_rule(rule_name, rule_root, rule_type, - rule_device_class, - 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; - } - - - // display --- - if (full_location >= 0) { - map loc = crush.get_full_location(full_location); - for (map::iterator p = loc.begin(); - p != loc.end(); - ++p) { - cout << p->first << "\t" << p->second << std::endl; - } - } - - if (tree) { - crush.dump_tree(&cout, NULL); - } - - if (dump) { - boost::scoped_ptr f(Formatter::create(dump_format, "json-pretty", "json-pretty")); - f->open_object_section("crush_map"); - crush.dump(f.get()); - f->close_section(); - f->flush(cout); - cout << "\n"; - } - - if (decompile) { - CrushCompiler cc(crush, cerr, verbose); - if (!outfn.empty()) { - ofstream o; - o.open(outfn.c_str(), ios::out | ios::binary | ios::trunc); - if (!o.is_open()) { - cerr << me << ": error writing '" << outfn << "'" << std::endl; - return EXIT_FAILURE; - } - cc.decompile(o); - o.close(); - } else { - cc.decompile(cout); - } - } - - if (check) { - tester.check_overlapped_rules(); - if (max_id >= 0) { - if (!tester.check_name_maps(max_id)) { - return EXIT_FAILURE; - } - } - } - - if (test) { - if (tester.get_output_utilization_all() || - tester.get_output_utilization()) - tester.set_output_statistics(true); - - int r = tester.test(); - if (r < 0) - return EXIT_FAILURE; - } - - // output --- - if (modified) { - crush.finalize(); - - if (outfn.empty()) { - cout << me << " successfully built or modified map. Use '-o ' to write it out." << std::endl; - } else { - bufferlist bl; - crush.encode(bl, CEPH_FEATURES_SUPPORTED_DEFAULT); - int r = bl.write_file(outfn.c_str()); - if (r < 0) { - cerr << me << ": error writing '" << outfn << "': " << cpp_strerror(r) << std::endl; - return EXIT_FAILURE; - } - if (verbose) - cout << "wrote crush map to " << outfn << std::endl; - } - } - - return 0; -} -/* - * Local Variables: - * compile-command: "cd .. ; make crushtool && test/run-cli-tests" - * End: - */