From: Roald J. van Loon Date: Sat, 7 Sep 2013 13:33:10 +0000 (+0200) Subject: automake cleanup: moving misc tools to tools subdir X-Git-Tag: v0.71~163^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3daf6ea96dd730de645d77cf69d2a5115a6a5d43;p=ceph.git automake cleanup: moving misc tools to tools subdir Signed-off-by: Roald J. van Loon --- diff --git a/src/Makefile.am b/src/Makefile.am index 9a2317537cbc..634d5245ac6d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -86,7 +86,7 @@ ceph_mon_LDADD = libmon.a $(LIBOS_LDA) $(LIBGLOBAL_LDA) ceph_mon_CXXFLAGS = ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS} bin_PROGRAMS += ceph-mon -ceph_mon_store_converter_SOURCES = mon_store_converter.cc \ +ceph_mon_store_converter_SOURCES = tools/mon_store_converter.cc \ mon/MonitorStore.cc ceph_mon_store_converter_LDFLAGS = ${AM_LDFLAGS} ceph_mon_store_converter_LDADD = $(LIBOS_LDA) $(LIBGLOBAL_LDA) @@ -112,10 +112,10 @@ ceph_mds_CXXFLAGS = ${AM_CXXFLAGS} # admin tools -ceph_conf_SOURCES = ceph_conf.cc +ceph_conf_SOURCES = tools/ceph_conf.cc ceph_conf_LDADD = $(LIBGLOBAL_LDA) ceph_conf_CXXFLAGS = ${AM_CXXFLAGS} -ceph_authtool_SOURCES = ceph_authtool.cc +ceph_authtool_SOURCES = tools/ceph_authtool.cc ceph_authtool_LDADD = $(LIBGLOBAL_LDA) ceph_filestore_dump_SOURCES = tools/ceph-filestore-dump.cc ceph_filestore_dump_SOURCES += perfglue/disabled_heap_profiler.cc @@ -139,11 +139,11 @@ ceph_monstore_tool_LDADD = $(LIBOS_LDA) $(LIBGLOBAL_LDA) -lboost_program_option ceph_monstore_tool_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS} bin_DEBUGPROGRAMS += ceph-monstore-tool -monmaptool_SOURCES = monmaptool.cc +monmaptool_SOURCES = tools/monmaptool.cc monmaptool_LDADD = $(LIBGLOBAL_LDA) -crushtool_SOURCES = crushtool.cc +crushtool_SOURCES = tools/crushtool.cc crushtool_LDADD = $(LIBGLOBAL_LDA) -osdmaptool_SOURCES = osdmaptool.cc +osdmaptool_SOURCES = tools/osdmaptool.cc osdmaptool_LDADD = $(LIBGLOBAL_LDA) bin_PROGRAMS += monmaptool crushtool osdmaptool @@ -227,7 +227,7 @@ ceph_mon_SOURCES += perfglue/disabled_heap_profiler.cc endif # WITH_TCMALLOC # debug targets -ceph_psim_SOURCES = psim.cc +ceph_psim_SOURCES = tools/psim.cc ceph_psim_LDADD = $(LIBGLOBAL_LDA) bin_DEBUGPROGRAMS += ceph_psim @@ -246,7 +246,7 @@ bin_DEBUGPROGRAMS += ceph_test_msgr ceph_test_ioctls_SOURCES = client/test_ioctls.c bin_DEBUGPROGRAMS += ceph_test_ioctls -ceph_dupstore_SOURCES = dupstore.cc +ceph_dupstore_SOURCES = tools/dupstore.cc ceph_dupstore_CXXFLAGS= ${CRYPTO_CXXFLAGS} ${AM_CXXFLAGS} ceph_dupstore_LDADD = $(LIBOS_LDA) $(LIBGLOBAL_LDA) ceph_streamtest_SOURCES = test/streamtest.cc @@ -500,11 +500,11 @@ endif endif -ceph_scratchtool_SOURCES = scratchtool.c +ceph_scratchtool_SOURCES = tools/scratchtool.c ceph_scratchtool_LDADD = librados.la $(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXTRALIBS) -ceph_scratchtoolpp_SOURCES = scratchtoolpp.cc +ceph_scratchtoolpp_SOURCES = tools/scratchtoolpp.cc ceph_scratchtoolpp_LDADD = librados.la $(PTHREAD_LIBS) -lm -ceph_radosacl_SOURCES = radosacl.cc +ceph_radosacl_SOURCES = tools/radosacl.cc ceph_radosacl_LDADD = librados.la $(PTHREAD_LIBS) -lm $(CRYPTO_LIBS) $(EXTRALIBS) bin_DEBUGPROGRAMS += ceph_scratchtool ceph_scratchtoolpp ceph_radosacl diff --git a/src/ceph_authtool.cc b/src/ceph_authtool.cc deleted file mode 100644 index f66a3c66eee9..000000000000 --- a/src/ceph_authtool.cc +++ /dev/null @@ -1,277 +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-2009 Sage Weil - * - * 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 "common/config.h" -#include "common/strtol.h" - -#include "common/ConfUtils.h" -#include "common/ceph_argparse.h" -#include "global/global_context.h" -#include "global/global_init.h" -#include "auth/Crypto.h" -#include "auth/Auth.h" -#include "auth/KeyRing.h" - -#include - -void usage() -{ - cout << "usage: ceph-authtool keyringfile [OPTIONS]...\n" - << "where the options are:\n" - << " -l, --list will list all keys and capabilities present in\n" - << " the keyring\n" - << " -p, --print-key will print an encoded key for the specified\n" - << " entityname. This is suitable for the\n" - << " 'mount -o secret=..' argument\n" - << " -C, --create-keyring will create a new keyring, overwriting any\n" - << " existing keyringfile\n" - << " -g, --gen-key will generate a new secret key for the\n" - << " specified entityname\n" - << " --gen-print-key will generate a new secret key without set it\n" - << " to the keyringfile, prints the secret to stdout\n" - << " --import-keyring will import the content of a given keyring\n" - << " into the keyringfile\n" - << " -u, --set-uid sets the auid (authenticated user id) for the\n" - << " specified entityname\n" - << " -a, --add-key will add an encoded key to the keyring\n" - << " --cap subsystem capability will set the capability for given subsystem\n" - << " --caps capsfile will set all of capabilities associated with a\n" - << " given key, for all subsystems" - << std::endl; - exit(1); -} - -int main(int argc, const char **argv) -{ - vector args; - argv_to_vec(argc, argv, args); - env_to_vec(args); - - bool gen_key = false; - bool gen_print_key = false; - std::string add_key; - bool list = false; - bool print_key = false; - bool create_keyring = false; - std::string caps_fn; - std::string import_keyring; - bool set_auid = false; - uint64_t auid = CEPH_AUTH_UID_DEFAULT; - map caps; - std::string fn; - - global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, - CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); - std::vector::iterator i; - for (i = args.begin(); i != args.end(); ) { - std::string val; - if (ceph_argparse_double_dash(args, i)) { - break; - } else if (ceph_argparse_flag(args, i, "-g", "--gen-key", (char*)NULL)) { - gen_key = true; - } else if (ceph_argparse_flag(args, i, "--gen-print-key", (char*)NULL)) { - gen_print_key = true; - } else if (ceph_argparse_witharg(args, i, &val, "-a", "--add-key", (char*)NULL)) { - add_key = val; - } else if (ceph_argparse_flag(args, i, &val, "-l", "--list", (char*)NULL)) { - list = true; - } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) { - caps_fn = val; - } else if (ceph_argparse_witharg(args, i, &val, "--cap", (char*)NULL)) { - std::string my_key = val; - if (i == args.end()) { - cerr << "must give two arguments to --cap: key and val." << std::endl; - exit(1); - } - std::string my_val = *i; - ++i; - ::encode(my_val, caps[my_key]); - } else if (ceph_argparse_flag(args, i, "-p", "--print-key", (char*)NULL)) { - print_key = true; - } else if (ceph_argparse_flag(args, i, "-C", "--create-keyring", (char*)NULL)) { - create_keyring = true; - } else if (ceph_argparse_witharg(args, i, &val, "--import-keyring", (char*)NULL)) { - import_keyring = val; - } else if (ceph_argparse_witharg(args, i, &val, "-u", "--set-uid", (char*)NULL)) { - std::string err; - auid = strict_strtoll(val.c_str(), 10, &err); - if (!err.empty()) { - cerr << "error parsing UID: " << err << std::endl; - exit(1); - } - set_auid = true; - } else if (fn.empty()) { - fn = *i++; - } else { - cerr << argv[0] << ": unexpected '" << *i << "'" << std::endl; - usage(); - } - } - if (fn.empty() && !gen_print_key) { - cerr << argv[0] << ": must specify filename" << std::endl; - usage(); - } - if (!(gen_key || - gen_print_key || - !add_key.empty() || - list || - !caps_fn.empty() || - !caps.empty() || - set_auid || - print_key || - create_keyring || - !import_keyring.empty())) { - cerr << "no command specified" << std::endl; - usage(); - } - if (gen_key && (!add_key.empty())) { - cerr << "can't both gen_key and add_key" << std::endl; - usage(); - } - - common_init_finish(g_ceph_context); - EntityName ename(g_conf->name); - - if (gen_print_key) { - CryptoKey key; - key.create(g_ceph_context, CEPH_CRYPTO_AES); - cout << key << std::endl; - return 0; - } - - // keyring -------- - bool modified = false; - KeyRing keyring; - - bufferlist bl; - int r = 0; - if (create_keyring) { - cout << "creating " << fn << std::endl; - modified = true; - } else { - std::string err; - r = bl.read_file(fn.c_str(), &err); - if (r >= 0) { - try { - bufferlist::iterator iter = bl.begin(); - ::decode(keyring, iter); - } catch (const buffer::error &err) { - cerr << "error reading file " << fn << std::endl; - exit(1); - } - } else { - cerr << "can't open " << fn << ": " << err << std::endl; - exit(1); - } - } - - // write commands - if (!import_keyring.empty()) { - KeyRing other; - bufferlist obl; - std::string err; - int r = obl.read_file(import_keyring.c_str(), &err); - if (r >= 0) { - try { - bufferlist::iterator iter = obl.begin(); - ::decode(other, iter); - } catch (const buffer::error &err) { - cerr << "error reading file " << import_keyring << std::endl; - exit(1); - } - - cout << "importing contents of " << import_keyring << " into " << fn << std::endl; - //other.print(cout); - keyring.import(g_ceph_context, other); - modified = true; - } else { - cerr << "can't open " << import_keyring << ": " << err << std::endl; - exit(1); - } - } - if (gen_key) { - EntityAuth eauth; - eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES); - keyring.add(ename, eauth); - modified = true; - } - if (!add_key.empty()) { - EntityAuth eauth; - try { - eauth.key.decode_base64(add_key); - } catch (const buffer::error &err) { - cerr << "can't decode key '" << add_key << "'" << std::endl; - exit(1); - } - keyring.add(ename, eauth); - modified = true; - cout << "added entity " << ename << " auth " << eauth << std::endl; - } - if (!caps_fn.empty()) { - ConfFile cf; - std::deque parse_errors; - if (cf.parse_file(caps_fn, &parse_errors, &cerr) != 0) { - cerr << "could not parse caps file " << caps_fn << std::endl; - exit(1); - } - complain_about_parse_errors(g_ceph_context, &parse_errors); - map caps; - const char *key_names[] = { "mon", "osd", "mds", NULL }; - for (int i=0; key_names[i]; i++) { - std::string val; - if (cf.read("global", key_names[i], val) == 0) { - bufferlist bl; - ::encode(val, bl); - string s(key_names[i]); - caps[s] = bl; - } - } - keyring.set_caps(ename, caps); - modified = true; - } - if (!caps.empty()) { - keyring.set_caps(ename, caps); - modified = true; - } - if (set_auid) { - keyring.set_uid(ename, auid); - modified = true; - } - - // read commands - if (list) { - keyring.print(cout); - } - if (print_key) { - CryptoKey key; - if (keyring.get_secret(ename, key)) { - cout << key << std::endl; - } else { - cerr << "entity " << ename << " not found" << std::endl; - } - } - - // write result? - if (modified) { - bufferlist bl; - keyring.encode_plaintext(bl); - r = bl.write_file(fn.c_str(), 0600); - if (r < 0) { - cerr << "could not write " << fn << std::endl; - } - //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl; - } - - return 0; -} diff --git a/src/ceph_conf.cc b/src/ceph_conf.cc deleted file mode 100644 index b2286f4e0944..000000000000 --- a/src/ceph_conf.cc +++ /dev/null @@ -1,223 +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-2010 Dreamhost - * - * 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 "mon/AuthMonitor.h" -#include "common/ConfUtils.h" -#include "global/global_init.h" -#include "common/entity_name.h" -#include "common/ceph_argparse.h" -#include "common/config.h" -#include "include/str_list.h" - -using std::deque; -using std::string; - -static void usage() -{ - // TODO: add generic_usage once cerr/derr issues are resolved - cerr << "Ceph configuration query tool\n\ -\n\ -USAGE\n\ -ceph-conf \n\ -\n\ -ACTIONS\n\ - -L|--list-all-sections List all sections\n\ - -l|--list-sections List sections with the given prefix\n\ - --filter-key Filter section list to only include sections\n\ - with given key defined.\n\ - --filter-key-value = Filter section list to only include sections\n\ - with given key/value pair.\n\ - --lookup Print a configuration setting to stdout.\n\ - Returns 0 (success) if the configuration setting is\n\ - found; 1 otherwise.\n\ - -r|--resolve-search search for the first file that exists and\n\ - can be opened in the resulted comma\n\ - delimited search list.\n\ -\n\ -FLAGS\n\ - --name name Set type.id\n\ - [-s
] Add to list of sections to search\n\ -\n\ -If there is no action given, the action will default to --lookup.\n\ -\n\ -EXAMPLES\n\ -$ ceph-conf --name mon.0 -c /etc/ceph/ceph.conf 'mon addr'\n\ -Find out what the value of 'mon add' is for monitor 0.\n\ -\n\ -$ ceph-conf -l mon\n\ -List sections beginning with 'mon'.\n\ -\n\ -RETURN CODE\n\ -Return code will be 0 on success; error code otherwise.\n\ -"; - exit(1); -} - -static int list_sections(const std::string &prefix, - const std::list& filter_key, - const std::map& filter_key_value) -{ - std::vector sections; - int ret = g_conf->get_all_sections(sections); - if (ret) - return 2; - for (std::vector::const_iterator p = sections.begin(); - p != sections.end(); ++p) { - if (strncmp(prefix.c_str(), p->c_str(), prefix.size())) - continue; - - std::vector sec; - sec.push_back(*p); - - int r = 0; - for (std::list::const_iterator q = filter_key.begin(); q != filter_key.end(); ++q) { - string v; - r = g_conf->get_val_from_conf_file(sec, q->c_str(), v, false); - if (r < 0) - break; - } - if (r < 0) - continue; - - for (std::map::const_iterator q = filter_key_value.begin(); - q != filter_key_value.end(); - ++q) { - string v; - r = g_conf->get_val_from_conf_file(sec, q->first.c_str(), v, false); - if (r < 0 || v != q->second) { - r = -1; - break; - } - } - if (r < 0) - continue; - - cout << *p << std::endl; - } - return 0; -} - -static int lookup(const std::deque §ions, - const std::string &key, bool resolve_search) -{ - std::vector my_sections; - for (deque::const_iterator s = sections.begin(); s != sections.end(); ++s) { - my_sections.push_back(*s); - } - g_conf->get_my_sections(my_sections); - std::string val; - int ret = g_conf->get_val_from_conf_file(my_sections, key.c_str(), val, true); - if (ret == -ENOENT) - return 1; - else if (ret == 0) { - if (resolve_search) { - string result; - if (ceph_resolve_file_search(val, result)) - puts(result.c_str()); - } - else { - puts(val.c_str()); - } - return 0; - } - else { - cerr << "error looking up '" << key << "': error " << ret << std::endl; - return 2; - } -} - -int main(int argc, const char **argv) -{ - vector args; - deque sections; - bool resolve_search = false; - std::string action; - std::string lookup_key; - std::string section_list_prefix; - std::list filter_key; - std::map filter_key_value; - - argv_to_vec(argc, argv, args); - env_to_vec(args); - - global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON, - CINIT_FLAG_NO_DAEMON_ACTIONS); - - // do not common_init_finish(); do not start threads; do not do any of thing - // wonky things the daemon whose conf we are examining would do (like initialize - // the admin socket). - //common_init_finish(g_ceph_context); - - std::string val; - for (std::vector::iterator i = args.begin(); i != args.end(); ) { - if (ceph_argparse_double_dash(args, i)) { - break; - } else if (ceph_argparse_witharg(args, i, &val, "-s", "--section", (char*)NULL)) { - sections.push_back(val); - } else if (ceph_argparse_flag(args, i, "-r", "--resolve_search", (char*)NULL)) { - resolve_search = true; - } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) { - action = "help"; - } else if (ceph_argparse_witharg(args, i, &val, "--lookup", (char*)NULL)) { - action = "lookup"; - lookup_key = val; - } else if (ceph_argparse_flag(args, i, "-L", "--list_all_sections", (char*)NULL)) { - action = "list-sections"; - section_list_prefix = ""; - } else if (ceph_argparse_witharg(args, i, &val, "-l", "--list_sections", (char*)NULL)) { - action = "list-sections"; - section_list_prefix = val; - } else if (ceph_argparse_witharg(args, i, &val, "--filter_key", (char*)NULL)) { - filter_key.push_back(val); - } else if (ceph_argparse_witharg(args, i, &val, "--filter_key_value", (char*)NULL)) { - size_t pos = val.find_first_of('='); - if (pos == string::npos) { - cerr << "expecting argument like 'key=value' for --filter-key-value (not '" << val << "')" << std::endl; - usage(); - exit(1); - } - string key(val, 0, pos); - string value(val, pos+1); - filter_key_value[key] = value; - } else { - if (((action == "lookup") || (action == "")) && (lookup_key.empty())) { - action = "lookup"; - lookup_key = *i++; - } else { - cerr << "unable to parse option: '" << *i << "'" << std::endl; - usage(); - exit(1); - } - } - } - - if (action == "help") { - usage(); - exit(0); - } else if (action == "list-sections") { - return list_sections(section_list_prefix, filter_key, filter_key_value); - } else if (action == "lookup") { - return lookup(sections, lookup_key, resolve_search); - } else { - cerr << "You must give an action, such as --lookup or --list-all-sections." << std::endl; - cerr << "Pass --help for more help." << std::endl; - exit(1); - } -} diff --git a/src/crushtool.cc b/src/crushtool.cc deleted file mode 100644 index 75c26c098b66..000000000000 --- a/src/crushtool.cc +++ /dev/null @@ -1,724 +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 - * - * 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/ceph_argparse.h" -#include "global/global_context.h" -#include "global/global_init.h" -#include "crush/CrushWrapper.h" -#include "crush/CrushCompiler.h" -#include "crush/CrushTester.h" -#include "include/assert.h" - -#define dout_subsys ceph_subsys_crush - -using namespace std; - -const char *infn = "stdin"; - - -//////////////////////////////////////////////////////////////////////////// - -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 << " --decompile|-d map decompile a crush map to source\n"; - cout << " --compile|-c map.txt compile a map from source\n"; - cout << " [-o outfile [--clobber]]\n"; - cout << " specify output for for (de)compilation\n"; - cout << " --build --num_osds N layer1 ...\n"; - cout << " build a new map, where each 'layer' is\n"; - cout << " 'name (uniform|straw|list|tree) size'\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]\n"; - cout << " [--num-rep n]\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 << " -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 << " --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-bad-mappings show bad mappings\n"; - cout << " --show-choose-tries show choose tries histogram\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 << " --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"; -} - -struct bucket_types_t { - const char *name; - int type; -} bucket_types[] = { - { "uniform", CRUSH_BUCKET_UNIFORM }, - { "list", CRUSH_BUCKET_LIST }, - { "straw", CRUSH_BUCKET_STRAW }, - { "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 test = false; - bool display = false; - bool write_to_file = false; - int verbose = 0; - bool unsafe_tunables = false; - - bool reweight = false; - int add_item = -1; - bool update_item = 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; - - CrushWrapper crush; - - CrushTester tester(crush, cerr, 1); - - vector empty_args; // we use -c, don't confuse the generic arg parsing - global_init(NULL, empty_args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, - CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); - common_init_finish(g_ceph_context); - - int x; - float y; - - 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(); - exit(0); - } 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, "--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_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_flag(args, i, "-t", "--test", (char*)NULL)) { - test = true; - } 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_withint(args, i, &choose_local_tries, &err, - "--set_choose_local_tries", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_withint(args, i, &choose_local_fallback_tries, &err, - "--set_choose_local_fallback_tries", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_withint(args, i, &choose_total_tries, &err, - "--set_choose_total_tries", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_withint(args, i, &chooseleaf_descend_once, &err, - "--set_chooseleaf_descend_once", (char*)NULL)) { - adjust = true; - } else if (ceph_argparse_flag(args, i, "--reweight", (char*)NULL)) { - reweight = true; - } else if (ceph_argparse_withint(args, i, &add_item, &err, "--add_item", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - if (i == args.end()) { - cerr << "expecting additional argument to --add-item" << std::endl; - exit(EXIT_FAILURE); - } - add_weight = atof(*i); - i = args.erase(i); - if (i == args.end()) { - cerr << "expecting additional argument to --add-item" << std::endl; - exit(EXIT_FAILURE); - } - add_name.assign(*i); - i = args.erase(i); - } else if (ceph_argparse_withint(args, i, &add_item, &err, "--update_item", (char*)NULL)) { - update_item = true; - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - if (i == args.end()) { - cerr << "expecting additional argument to --update-item" << std::endl; - exit(EXIT_FAILURE); - } - add_weight = atof(*i); - i = args.erase(i); - if (i == args.end()) { - cerr << "expecting additional argument to --update-item" << std::endl; - exit(EXIT_FAILURE); - } - add_name.assign(*i); - i = args.erase(i); - } 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; - exit(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(); - exit(0); - } 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; - exit(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; - exit(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_withint(args, i, &num_osds, &err, "--num_osds", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - } else if (ceph_argparse_withint(args, i, &x, &err, "--num_rep", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_num_rep(x); - } else if (ceph_argparse_withint(args, i, &x, &err, "--max_x", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_max_x(x); - } else if (ceph_argparse_withint(args, i, &x, &err, "--min_x", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_min_x(x); - } else if (ceph_argparse_withint(args, i, &x, &err, "--x", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_x(x); - } else if (ceph_argparse_withint(args, i, &x, &err, "--max_rule", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_max_rule(x); - } else if (ceph_argparse_withint(args, i, &x, &err, "--min_rule", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_min_rule(x); - } else if (ceph_argparse_withint(args, i, &x, &err, "--rule", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_rule(x); - } else if (ceph_argparse_withint(args, i, &x, &err, "--batches", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_batches(x); - } else if (ceph_argparse_withfloat(args, i, &y, &err, "--mark-down-ratio", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_device_down_ratio(y); - } else if (ceph_argparse_withfloat(args, i, &y, &err, "--mark-down-bucket-ratio", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - tester.set_bucket_down_ratio(y); - } else if (ceph_argparse_withint(args, i, &tmp, &err, "--weight", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - int dev = tmp; - if (i == args.end()) { - cerr << "expecting additional argument to --weight" << std::endl; - exit(EXIT_FAILURE); - } - float f = atof(*i); - i = args.erase(i); - tester.set_device_weight(dev, f); - } - else { - ++i; - } - } - - if (test && !display && !write_to_file) { - cerr << "WARNING: no output selected; use --output-csv or --show-X" << std::endl; - exit(EXIT_FAILURE); - } - - if (decompile + compile + build > 1) { - cout << "cannot specify more than one of compile, decompile, and build" << std::endl; - exit(EXIT_FAILURE); - } - if (!compile && !decompile && !build && !test && !reweight && !adjust && - add_item < 0 && - remove_name.empty() && reweight_name.empty()) { - cout << "no action specified; -h for help" << std::endl; - exit(EXIT_FAILURE); - } - if ((!build) && (!args.empty())) { - cerr << "unrecognized arguments: " << args << std::endl; - exit(EXIT_FAILURE); - } - else { - if ((args.size() % 3) != 0U) { - cerr << "layers must be specified with 3-tuples of (name, buckettype, size)" - << std::endl; - exit(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; - - if (!infn.empty()) { - bufferlist bl; - std::string error; - int r = bl.read_file(infn.c_str(), &error); - if (r < 0) { - cerr << me << ": error reading '" << infn << "': " - << error << std::endl; - exit(1); - } - bufferlist::iterator p = bl.begin(); - crush.decode(p); - } - - 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; - exit(1); - } - cc.decompile(o); - o.close(); - } else { - cc.decompile(cout); - } - } - - 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) - exit(1); - - modified = true; - } - - if (build) { - if (layers.empty()) { - cerr << me << ": must specify at least one layer" << std::endl; - exit(1); - } - - crush.create(); - - vector lower_items; - vector lower_weights; - - for (int i=0; i::iterator p = layers.begin(); p != layers.end(); ++p, type++) { - layer_t &l = *p; - - dout(0) << "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 << std::endl; - exit(EXIT_FAILURE); - } - - // build items - vector cur_items; - vector cur_weights; - unsigned lower_pos = 0; // lower pos - - dout(0) << "lower_items " << lower_items << dendl; - dout(0) << "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= 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 (reweight) { - crush.reweight(g_ceph_context); - modified = true; - } - - const char *scary_tunables_message = - "** tunables are DANGEROUS and NOT YET RECOMMENDED. DO NOT USE without\n" - "** confirming with developers that your use-case is safe and correct."; - if (choose_local_tries >= 0) { - if (!unsafe_tunables) { - cerr << scary_tunables_message << std::endl; - return -1; - } - crush.set_choose_local_tries(choose_local_tries); - modified = true; - } - if (choose_local_fallback_tries >= 0) { - if (!unsafe_tunables) { - cerr << scary_tunables_message << std::endl; - return -1; - } - crush.set_choose_local_fallback_tries(choose_local_fallback_tries); - modified = true; - } - if (choose_total_tries >= 0) { - if (!unsafe_tunables) { - cerr << scary_tunables_message << std::endl; - return -1; - } - crush.set_choose_total_tries(choose_total_tries); - modified = true; - } - if (chooseleaf_descend_once >= 0) { - if (!unsafe_tunables) { - cerr << scary_tunables_message << std::endl; - return -1; - } - crush.set_chooseleaf_descend_once(chooseleaf_descend_once); - modified = true; - } - 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); - int r = bl.write_file(outfn.c_str()); - if (r < 0) { - char buf[80]; - cerr << me << ": error writing '" << outfn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl; - exit(1); - } - if (verbose) - cout << "wrote crush map to " << outfn << std::endl; - } - } - - if (test) { - int r = tester.test(); - if (r < 0) - exit(1); - } - - return 0; -} diff --git a/src/dupstore.cc b/src/dupstore.cc deleted file mode 100644 index e17eb2201a7a..000000000000 --- a/src/dupstore.cc +++ /dev/null @@ -1,114 +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 - * - * 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 "os/FileStore.h" -#include "common/ceph_argparse.h" -#include "global/global_init.h" - -#include -using __gnu_cxx::hash_map; - -int dupstore(ObjectStore* src, ObjectStore* dst) -{ - if (src->mount() < 0) return 1; - if (dst->mkfs() < 0) return 1; - if (dst->mount() < 0) return 1; - - // objects - hash_map did_object; - - // collections - vector collections; - - int ret = src->list_collections(collections); - if (ret < 0) { - cerr << "Error " << ret << " while listing collections" << std::endl; - return 1; - } - - int num = collections.size(); - cout << num << " collections" << std::endl; - int i = 1; - for (vector::iterator p = collections.begin(); - p != collections.end(); - ++p) { - cout << "collection " << i++ << "/" << num << " " << hex << *p << dec << std::endl; - { - ObjectStore::Transaction t; - t.create_collection(*p); - map attrs; - src->collection_getattrs(*p, attrs); - t.collection_setattrs(*p, attrs); - dst->apply_transaction(t); - } - - vector o; - src->collection_list(*p, o); - int numo = o.size(); - int j = 1; - for (vector::iterator q = o.begin(); q != o.end(); ++q) { - ObjectStore::Transaction t; - if (did_object.count(*q)) - t.collection_add(*p, did_object[*q], *q); - else { - bufferlist bl; - src->read(*p, *q, 0, 0, bl); - cout << "object " << j++ << "/" << numo << " " << *q << " = " << bl.length() << " bytes" << std::endl; - t.write(*p, *q, 0, bl.length(), bl); - map attrs; - src->getattrs(*p, *q, attrs); - t.setattrs(*p, *q, attrs); - did_object[*q] = *p; - } - dst->apply_transaction(t); - } - } - - src->umount(); - dst->umount(); - return 0; -} - -void usage() -{ - cerr << "usage: ceph_dupstore filestore SRC filestore DST" << std::endl; - exit(0); -} - -int main(int argc, const char **argv) -{ - vector args; - argv_to_vec(argc, argv, args); - env_to_vec(args); - - global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); - common_init_finish(g_ceph_context); - - // args - if (args.size() != 4) - usage(); - - ObjectStore *src = 0, *dst = 0; - - if (strcmp(args[0], "filestore") == 0) - src = new FileStore(args[1], NULL); - else usage(); - - if (strcmp(args[2], "filestore") == 0) - dst = new FileStore(args[3], NULL); - else usage(); - - return dupstore(src, dst); -} diff --git a/src/mon_store_converter.cc b/src/mon_store_converter.cc deleted file mode 100644 index 1c0d3af98e2b..000000000000 --- a/src/mon_store_converter.cc +++ /dev/null @@ -1,336 +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) 2012 Inktank, Inc. -* -* 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 -#include - -#include "include/types.h" -#include "include/buffer.h" -#include "common/ceph_argparse.h" -#include "global/global_init.h" -#include "common/debug.h" -#include "common/config.h" - -#include "mon/MonitorDBStore.h" -#include "mon/MonitorStore.h" - -using namespace std; - -class MonitorStoreConverter { - - boost::scoped_ptr db; - boost::scoped_ptr store; - - set gvs; - version_t highest_last_pn; - version_t highest_accepted_pn; - - static const int PAXOS_MAX_VERSIONS = 50; - string MONITOR_NAME; - - public: - MonitorStoreConverter(string &store_path, string &db_store_path) - : db(0), store(0), - highest_last_pn(0), highest_accepted_pn(0), - MONITOR_NAME("monitor") - { - MonitorStore *store_ptr = new MonitorStore(store_path); - assert(!store_ptr->mount()); - store.reset(store_ptr); - - MonitorDBStore *db_ptr = new MonitorDBStore(db_store_path); - db.reset(db_ptr); - } - - int convert() { - if (db->open(std::cerr) >= 0) { - std::cerr << "store already exists" << std::endl; - return EEXIST; - } - assert(!db->create_and_open(std::cerr)); - if (db->exists("mon_convert", "on_going")) { - std::cout << __func__ << " found a mon store in mid-convertion; abort!" - << std::endl; - return EEXIST; - } - _mark_convert_start(); - _convert_monitor(); - _convert_machines(); - _mark_convert_finish(); - - std::cout << __func__ << " finished conversion" << std::endl; - - return 0; - } - - bool match() { - return true; - } - - private: - - set _get_machines_names() { - set names; - names.insert("auth"); - names.insert("logm"); - names.insert("mdsmap"); - names.insert("monmap"); - names.insert("osdmap"); - names.insert("pgmap"); - - return names; - } - - void _mark_convert_start() { - MonitorDBStore::Transaction tx; - tx.put("mon_convert", "on_going", 1); - db->apply_transaction(tx); - } - - void _mark_convert_finish() { - MonitorDBStore::Transaction tx; - tx.erase("mon_convert", "on_going"); - db->apply_transaction(tx); - } - - void _convert_monitor() { - - assert(store->exists_bl_ss("magic")); - assert(store->exists_bl_ss("keyring")); - assert(store->exists_bl_ss("feature_set")); - assert(store->exists_bl_ss("election_epoch")); - - MonitorDBStore::Transaction tx; - - if (store->exists_bl_ss("joined")) { - version_t joined = store->get_int("joined"); - tx.put(MONITOR_NAME, "joined", joined); - } - - vector keys; - keys.push_back("magic"); - keys.push_back("feature_set"); - keys.push_back("election_epoch"); - keys.push_back("cluster_uuid"); - - vector::iterator it; - for (it = keys.begin(); it != keys.end(); ++it) { - if (!store->exists_bl_ss((*it).c_str())) - continue; - - bufferlist bl; - int r = store->get_bl_ss(bl, (*it).c_str(), 0); - assert(r > 0); - tx.put(MONITOR_NAME, *it, bl); - } - - assert(!tx.empty()); - db->apply_transaction(tx); - } - - void _convert_machines(string machine) { - std::cout << __func__ << " " << machine << std::endl; - - version_t first_committed = - store->get_int(machine.c_str(), "first_committed"); - version_t last_committed = - store->get_int(machine.c_str(), "last_committed"); - - version_t accepted_pn = store->get_int(machine.c_str(), "accepted_pn"); - version_t last_pn = store->get_int(machine.c_str(), "last_pn"); - - if (accepted_pn > highest_accepted_pn) - highest_accepted_pn = accepted_pn; - if (last_pn > highest_last_pn) - highest_last_pn = last_pn; - - string machine_gv(machine); - machine_gv.append("_gv"); - bool has_gv = true; - - if (!store->exists_bl_ss(machine_gv.c_str())) { - std::cerr << __func__ << " " << machine - << " no gv dir '" << machine_gv << "'" << std::endl; - has_gv = false; - } - - for (version_t ver = first_committed; ver <= last_committed; ver++) { - if (!store->exists_bl_sn(machine.c_str(), ver)) { - std::cerr << __func__ << " " << machine - << " ver " << ver << " dne" << std::endl; - continue; - } - - bufferlist bl; - int r = store->get_bl_sn(bl, machine.c_str(), ver); - assert(r >= 0); - std::cout << __func__ << " " << machine - << " ver " << ver << " bl " << bl.length() << std::endl; - - MonitorDBStore::Transaction tx; - tx.put(machine, ver, bl); - tx.put(machine, "last_committed", ver); - - if (has_gv && store->exists_bl_sn(machine_gv.c_str(), ver)) { - stringstream s; - s << ver; - string ver_str = s.str(); - - version_t gv = store->get_int(machine_gv.c_str(), ver_str.c_str()); - std::cerr << __func__ << " " << machine - << " ver " << ver << " -> " << gv << std::endl; - - if (gvs.count(gv) == 0) { - gvs.insert(gv); - } else { - std::cerr << __func__ << " " << machine - << " gv " << gv << " already exists" - << std::endl; - } - - bufferlist tx_bl; - tx.encode(tx_bl); - tx.put("paxos", gv, tx_bl); - } - db->apply_transaction(tx); - } - - version_t lc = db->get(machine, "last_committed"); - assert(lc == last_committed); - - MonitorDBStore::Transaction tx; - tx.put(machine, "first_committed", first_committed); - tx.put(machine, "last_committed", last_committed); - - if (store->exists_bl_ss(machine.c_str(), "latest")) { - bufferlist latest_bl_raw; - int r = store->get_bl_ss(latest_bl_raw, machine.c_str(), "latest"); - assert(r >= 0); - if (!latest_bl_raw.length()) { - std::cerr << __func__ << " machine " << machine - << " skip latest with size 0" << std::endl; - goto out; - } - - tx.put(machine, "latest", latest_bl_raw); - - bufferlist::iterator lbl_it = latest_bl_raw.begin(); - bufferlist latest_bl; - version_t latest_ver; - ::decode(latest_ver, lbl_it); - ::decode(latest_bl, lbl_it); - - std::cout << __func__ << " machine " << machine - << " latest ver " << latest_ver << std::endl; - - tx.put(machine, "full_latest", latest_ver); - stringstream os; - os << "full_" << latest_ver; - tx.put(machine, os.str(), latest_bl); - } - out: - db->apply_transaction(tx); - } - - void _convert_paxos() { - assert(!gvs.empty()); - - set::reverse_iterator rit = gvs.rbegin(); - version_t highest_gv = *rit; - version_t last_gv = highest_gv; - - int n = 0; - for (; (rit != gvs.rend()) && (n < PAXOS_MAX_VERSIONS); ++rit, ++n) { - - version_t gv = *rit; - - if (last_gv == gv) - continue; - - if ((last_gv - gv) > 1) { - // we are done; we found a gap and we are only interested in keeping - // contiguous paxos versions. - break; - } - last_gv = gv; - } - - // erase all paxos versions between [first, last_gv[, with first being the - // first gv in the map. - MonitorDBStore::Transaction tx; - set::iterator it = gvs.begin(); - std::cout << __func__ << " first gv " << (*it) - << " last gv " << last_gv << std::endl; - for (; it != gvs.end() && (*it < last_gv); ++it) { - tx.erase("paxos", *it); - } - tx.put("paxos", "first_committed", last_gv); - tx.put("paxos", "last_committed", highest_gv); - tx.put("paxos", "accepted_pn", highest_accepted_pn); - tx.put("paxos", "last_pn", highest_last_pn); - db->apply_transaction(tx); - } - - void _convert_machines() { - - set machine_names = _get_machines_names(); - set::iterator it = machine_names.begin(); - - std::cout << __func__ << std::endl; - - for (; it != machine_names.end(); ++it) { - _convert_machines(*it); - } - - _convert_paxos(); - } -}; - - -void usage(const char *pname) -{ - std::cerr << "Usage: " << pname << " \n" - << std::endl; -} - -int main(int argc, const char *argv[]) -{ - vector def_args; - vector args; - const char *our_name = argv[0]; - argv_to_vec(argc, argv, args); - - global_init(&def_args, args, - CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, - CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); - common_init_finish(g_ceph_context); - g_ceph_context->_conf->apply_changes(NULL); - - if (args.empty()) { - usage(our_name); - return 1; - } - string store(args[0]); - string new_store(store); - MonitorStoreConverter converter(store, new_store); - assert(!converter.convert()); - assert(converter.match()); - - std::cout << "store successfully converted to new format" << std::endl; - - return 0; -} diff --git a/src/monmaptool.cc b/src/monmaptool.cc deleted file mode 100644 index 57843aa350d0..000000000000 --- a/src/monmaptool.cc +++ /dev/null @@ -1,208 +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 - * - * 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 -using namespace std; - -#include "common/config.h" -#include "common/ceph_argparse.h" -#include "global/global_init.h" -#include "mon/MonMap.h" -#include "include/str_list.h" - -void usage() -{ - cout << " usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] " << std::endl; - exit(1); -} - -int main(int argc, const char **argv) -{ - vector args; - argv_to_vec(argc, argv, args); - - const char *me = argv[0]; - - std::string fn; - bool print = false; - bool create = false; - bool clobber = false; - bool modified = false; - bool generate = false; - bool filter = false; - map add; - list rm; - - global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, - CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); - common_init_finish(g_ceph_context); - std::string val; - 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(); - } else if (ceph_argparse_flag(args, i, "-p", "--print", (char*)NULL)) { - print = true; - } else if (ceph_argparse_flag(args, i, "--create", (char*)NULL)) { - create = true; - } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) { - clobber = true; - } else if (ceph_argparse_flag(args, i, "--generate", (char*)NULL)) { - generate = true; - } else if (ceph_argparse_flag(args, i, "--set-initial-members", (char*)NULL)) { - filter = true; - } else if (ceph_argparse_flag(args, i, "--add", (char*)NULL)) { - string name = *i; - i = args.erase(i); - if (i == args.end()) - usage(); - entity_addr_t addr; - if (!addr.parse(*i)) { - cerr << me << ": invalid ip:port '" << *i << "'" << std::endl; - return -1; - } - if (addr.get_port() == 0) - addr.set_port(CEPH_MON_PORT); - add[name] = addr; - modified = true; - i = args.erase(i); - } else if (ceph_argparse_witharg(args, i, &val, "--rm", (char*)NULL)) { - rm.push_back(val); - modified = true; - } else { - ++i; - } - } - if (args.empty()) { - cerr << me << ": must specify monmap filename" << std::endl; - usage(); - } - else if (args.size() > 1) { - cerr << me << ": too many arguments" << std::endl; - usage(); - } - fn = args[0]; - - MonMap monmap; - - cout << me << ": monmap file " << fn << std::endl; - - int r = 0; - if (!(create && clobber)) { - try { - r = monmap.read(fn.c_str()); - } catch (...) { - cerr << me << ": unable to read monmap file" << std::endl; - return -1; - } - } - - char buf[80]; - if (!create && r < 0) { - cerr << me << ": couldn't open " << fn << ": " << strerror_r(-r, buf, sizeof(buf)) << std::endl; - return -1; - } - else if (create && !clobber && r == 0) { - cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl; - return -1; - } - - if (create) { - monmap.epoch = 0; - monmap.created = ceph_clock_now(g_ceph_context); - monmap.last_changed = monmap.created; - srand(getpid() + time(0)); - if (g_conf->fsid.is_zero()) { - monmap.generate_fsid(); - cout << me << ": generated fsid " << monmap.fsid << std::endl; - } - modified = true; - } - - if (generate) { - int r = monmap.build_initial(g_ceph_context, cerr); - if (r < 0) - return r; - } - - if (filter) { - // apply initial members - list initial_members; - get_str_list(g_conf->mon_initial_members, initial_members); - if (!initial_members.empty()) { - cout << "initial_members " << initial_members << ", filtering seed monmap" << std::endl; - set removed; - monmap.set_initial_members(g_ceph_context, initial_members, - string(), entity_addr_t(), - &removed); - cout << "removed " << removed << std::endl; - } - modified = true; - } - - if (!g_conf->fsid.is_zero()) { - monmap.fsid = g_conf->fsid; - cout << me << ": set fsid to " << monmap.fsid << std::endl; - modified = true; - } - - for (map::iterator p = add.begin(); p != add.end(); ++p) { - if (monmap.contains(p->first)) { - cerr << me << ": map already contains mon." << p->first << std::endl; - usage(); - } - if (monmap.contains(p->second)) { - cerr << me << ": map already contains " << p->second << std::endl; - usage(); - } - monmap.add(p->first, p->second); - } - for (list::iterator p = rm.begin(); p != rm.end(); ++p) { - cout << me << ": removing " << *p << std::endl; - if (!monmap.contains(*p)) { - cerr << me << ": map does not contain " << *p << std::endl; - usage(); - } - monmap.remove(*p); - } - - if (!print && !modified) - usage(); - - if (print) - monmap.print(cout); - - if (modified) { - // write it out - cout << me << ": writing epoch " << monmap.epoch - << " to " << fn - << " (" << monmap.size() << " monitors)" - << std::endl; - int r = monmap.write(fn.c_str()); - if (r < 0) { - cerr << "monmaptool: error writing to '" << fn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl; - return 1; - } - } - - - return 0; -} diff --git a/src/osdmaptool.cc b/src/osdmaptool.cc deleted file mode 100644 index 2e55026076c3..000000000000 --- a/src/osdmaptool.cc +++ /dev/null @@ -1,343 +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 - * - * 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 -using namespace std; - -#include "common/config.h" - -#include "common/errno.h" -#include "osd/OSDMap.h" -#include "mon/MonMap.h" -#include "common/ceph_argparse.h" -#include "global/global_init.h" - -void usage() -{ - cout << " usage: [--print] [--createsimple [--clobber] [--pg_bits ]] " << std::endl; - cout << " --export-crush write osdmap's crush map to " << std::endl; - cout << " --import-crush replace osdmap's crush map with " << std::endl; - cout << " --test-map-pg map a pgid to osds" << std::endl; - cout << " --test-map-object [--pool ] map an object to osds" - << std::endl; - exit(1); -} - -int main(int argc, const char **argv) -{ - vector args; - argv_to_vec(argc, argv, args); - env_to_vec(args); - - global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, - CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); - common_init_finish(g_ceph_context); - - const char *me = argv[0]; - - std::string fn; - bool print = false; - bool print_json = false; - bool tree = false; - bool createsimple = false; - bool create_from_conf = false; - int num_osd = 0; - int pg_bits = g_conf->osd_pg_bits; - int pgp_bits = g_conf->osd_pgp_bits; - bool clobber = false; - bool modified = false; - std::string export_crush, import_crush, test_map_pg, test_map_object; - bool test_crush = false; - int range_first = -1; - int range_last = -1; - int pool = 0; - - std::string val; - std::ostringstream err; - 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(); - } else if (ceph_argparse_flag(args, i, "-p", "--print", (char*)NULL)) { - print = true; - } else if (ceph_argparse_flag(args, i, "--dump-json", (char*)NULL)) { - print_json = true; - } else if (ceph_argparse_flag(args, i, "--tree", (char*)NULL)) { - tree = true; - } else if (ceph_argparse_withint(args, i, &num_osd, &err, "--createsimple", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - createsimple = true; - } else if (ceph_argparse_flag(args, i, "--create-from-conf", (char*)NULL)) { - create_from_conf = true; - } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) { - clobber = true; - } else if (ceph_argparse_withint(args, i, &pg_bits, &err, "--pg_bits", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - } else if (ceph_argparse_withint(args, i, &pgp_bits, &err, "--pgp_bits", (char*)NULL)) { - if (!err.str().empty()) { - cerr << err.str() << std::endl; - exit(EXIT_FAILURE); - } - } else if (ceph_argparse_witharg(args, i, &val, "--export_crush", (char*)NULL)) { - export_crush = val; - } else if (ceph_argparse_witharg(args, i, &val, "--import_crush", (char*)NULL)) { - import_crush = val; - } else if (ceph_argparse_witharg(args, i, &val, "--test_map_pg", (char*)NULL)) { - test_map_pg = val; - } else if (ceph_argparse_witharg(args, i, &val, "--test_map_object", (char*)NULL)) { - test_map_object = val; - } else if (ceph_argparse_flag(args, i, "--test_crush", (char*)NULL)) { - test_crush = true; - } else if (ceph_argparse_withint(args, i, &range_first, &err, "--range_first", (char*)NULL)) { - } else if (ceph_argparse_withint(args, i, &range_last, &err, "--range_last", (char*)NULL)) { - } else if (ceph_argparse_withint(args, i, &pool, &err, "--pool", (char*)NULL)) { - } else { - ++i; - } - } - if (args.empty()) { - cerr << me << ": must specify osdmap filename" << std::endl; - usage(); - } - else if (args.size() > 1) { - cerr << me << ": too many arguments" << std::endl; - usage(); - } - fn = args[0]; - - if (range_first >= 0 && range_last >= 0) { - set maps; - OSDMap *prev = NULL; - for (int i=range_first; i <= range_last; i++) { - ostringstream f; - f << fn << "/" << i; - bufferlist bl; - string error, s = f.str(); - int r = bl.read_file(s.c_str(), &error); - if (r < 0) { - cerr << "unable to read " << s << ": " << cpp_strerror(r) << std::endl; - exit(1); - } - cout << s << " got " << bl.length() << " bytes" << std::endl; - OSDMap *o = new OSDMap; - o->decode(bl); - maps.insert(o); - if (prev) - OSDMap::dedup(prev, o); - prev = o; - } - exit(0); - } - - OSDMap osdmap; - bufferlist bl; - - cout << me << ": osdmap file '" << fn << "'" << std::endl; - - int r = 0; - struct stat st; - if (!createsimple && !create_from_conf && !clobber) { - std::string error; - r = bl.read_file(fn.c_str(), &error); - if (r == 0) { - try { - osdmap.decode(bl); - } - catch (const buffer::error &e) { - cerr << me << ": error decoding osdmap '" << fn << "'" << std::endl; - return -1; - } - } - else { - cerr << me << ": couldn't open " << fn << ": " << error << std::endl; - return -1; - } - } - else if ((createsimple || create_from_conf) && !clobber && ::stat(fn.c_str(), &st) == 0) { - cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl; - return -1; - } - - if (createsimple) { - if (num_osd < 1) { - cerr << me << ": osd count must be > 0" << std::endl; - exit(1); - } - uuid_d fsid; - memset(&fsid, 0, sizeof(uuid_d)); - osdmap.build_simple(g_ceph_context, 0, fsid, num_osd, pg_bits, pgp_bits); - modified = true; - } - if (create_from_conf) { - uuid_d fsid; - memset(&fsid, 0, sizeof(uuid_d)); - int r = osdmap.build_simple_from_conf(g_ceph_context, 0, fsid, pg_bits, pgp_bits); - if (r < 0) - return -1; - modified = true; - } - - if (!import_crush.empty()) { - bufferlist cbl; - std::string error; - r = cbl.read_file(import_crush.c_str(), &error); - if (r) { - cerr << me << ": error reading crush map from " << import_crush - << ": " << error << std::endl; - exit(1); - } - - // validate - CrushWrapper cw; - bufferlist::iterator p = cbl.begin(); - cw.decode(p); - - if (cw.get_max_devices() > osdmap.get_max_osd()) { - cerr << me << ": crushmap max_devices " << cw.get_max_devices() - << " > osdmap max_osd " << osdmap.get_max_osd() << std::endl; - exit(1); - } - - // apply - OSDMap::Incremental inc; - inc.fsid = osdmap.get_fsid(); - inc.epoch = osdmap.get_epoch()+1; - inc.crush = cbl; - osdmap.apply_incremental(inc); - cout << me << ": imported " << cbl.length() << " byte crush map from " << import_crush << std::endl; - modified = true; - } - - if (!export_crush.empty()) { - bufferlist cbl; - osdmap.crush->encode(cbl); - r = cbl.write_file(export_crush.c_str()); - if (r < 0) { - cerr << me << ": error writing crush map to " << import_crush << std::endl; - exit(1); - } - cout << me << ": exported crush map to " << export_crush << std::endl; - } - - if (!test_map_object.empty()) { - object_t oid(test_map_object); - if (!osdmap.have_pg_pool(pool)) { - cerr << "There is no pool " << pool << std::endl; - exit(1); - } - object_locator_t loc(pool); - pg_t raw_pgid = osdmap.object_locator_to_pg(oid, loc); - pg_t pgid = osdmap.raw_pg_to_pg(raw_pgid); - - vector acting; - osdmap.pg_to_acting_osds(pgid, acting); - cout << " object '" << oid - << "' -> " << pgid - << " -> " << acting - << std::endl; - } - if (!test_map_pg.empty()) { - pg_t pgid; - if (!pgid.parse(test_map_pg.c_str())) { - cerr << me << ": failed to parse pg '" << test_map_pg - << "', r = " << r << std::endl; - usage(); - } - cout << " parsed '" << test_map_pg << "' -> " << pgid << std::endl; - - vector raw, up, acting; - osdmap.pg_to_osds(pgid, raw); - osdmap.pg_to_up_acting_osds(pgid, up, acting); - cout << pgid << " raw " << raw << " up " << up << " acting " << acting << std::endl; - } - if (test_crush) { - int pass = 0; - while (1) { - cout << "pass " << ++pass << std::endl; - - hash_map > m; - for (map::const_iterator p = osdmap.get_pools().begin(); - p != osdmap.get_pools().end(); - ++p) { - const pg_pool_t *pool = osdmap.get_pg_pool(p->first); - for (ps_t ps = 0; ps < pool->get_pg_num(); ps++) { - pg_t pgid(ps, p->first, -1); - for (int i=0; i<100; i++) { - cout << pgid << " attempt " << i << std::endl; - - vector r; - osdmap.pg_to_acting_osds(pgid, r); - //cout << pgid << " " << r << std::endl; - if (m.count(pgid)) { - if (m[pgid] != r) { - cout << pgid << " had " << m[pgid] << " now " << r << std::endl; - assert(0); - } - } else - m[pgid] = r; - } - } - } - } - } - - if (!print && !print_json && !tree && !modified && - export_crush.empty() && import_crush.empty() && - test_map_pg.empty() && test_map_object.empty()) { - cerr << me << ": no action specified?" << std::endl; - usage(); - } - - if (modified) - osdmap.inc_epoch(); - - if (print) - osdmap.print(cout); - if (print_json) - osdmap.dump_json(cout); - if (tree) - osdmap.print_tree(&cout, NULL); - - if (modified) { - bl.clear(); - osdmap.encode(bl); - - // write it out - cout << me << ": writing epoch " << osdmap.get_epoch() - << " to " << fn - << std::endl; - int r = bl.write_file(fn.c_str()); - if (r) { - cerr << "osdmaptool: error writing to '" << fn << "': " - << cpp_strerror(r) << std::endl; - return 1; - } - } - - - return 0; -} diff --git a/src/psim.cc b/src/psim.cc deleted file mode 100644 index c1adc7580fb6..000000000000 --- a/src/psim.cc +++ /dev/null @@ -1,96 +0,0 @@ - -#include - -#include "crush/CrushWrapper.h" -#include "osd/OSDMap.h" -#include "common/config.h" -#include "include/buffer.h" - -int main(int argc, char **argv) -{ - /* - * you need to create a suitable osdmap first. e.g., for 40 osds, - * $ ./osdmaptool --createsimple 40 --clobber .ceph_osdmap - */ - bufferlist bl; - std::string error; - if (bl.read_file(".ceph_osdmap", &error)) { - cout << argv[0] << ": error reading .ceph_osdmap: " << error << std::endl; - return 1; - } - OSDMap osdmap; - osdmap.decode(bl); - - int n = osdmap.get_max_osd(); - int count[n]; - for (int i=0; i osds; - pg_t pgid = pg_t(l.ol_pgid); - //pgid.u.ps = f * 4 + b; - osdmap.pg_to_osds(pgid, osds); - size[osds.size()]++; -#if 0 - if (0) { - hash H; - int x = H(oid); - x = ceph_stable_mod(x, 1023, 1023); - int s = crush_hash32(x) % 15; - //cout << "ceph_psim: x = " << x << " s = " << s << std::endl; - //osds[0] = s; - } -#endif - //osds[0] = crush_hash32(f) % n; - //cout << "oid " << oid << " pgid " << pgid << " on " << osds << std::endl; - for (unsigned i=0; iget_pg_num() / (double)n; - double edev = sqrt(pgavg) * (double)avg / pgavg; - cout << " avg " << avg - << " stddev " << dev - << " (expected " << edev << ")" - << " (indep object placement would be " << sqrt(avg) << ")" << std::endl; - - for (int i=0; i<4; i++) { - cout << "size" << i << "\t" << size[i] << std::endl; - } - - return 0; -} diff --git a/src/radosacl.cc b/src/radosacl.cc deleted file mode 100644 index d2f7ca5c488f..000000000000 --- a/src/radosacl.cc +++ /dev/null @@ -1,202 +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 - * - * 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/types.h" -#include "include/rados/librados.hpp" -using namespace librados; - -#include - -#include -#include -#include - -void buf_to_hex(const unsigned char *buf, int len, char *str) -{ - str[0] = '\0'; - for (int i = 0; i < len; i++) { - sprintf(&str[i*2], "%02x", (int)buf[i]); - } -} - - -#define ID_SIZE 8 - -#define ACL_RD 0x1 -#define ACL_WR 0x2 - -struct ACLID { - char id[ID_SIZE + 1]; - - void encode(bufferlist& bl) const { - bl.append((const char *)id, ID_SIZE); - } - void decode(bufferlist::iterator& iter) { - iter.copy(ID_SIZE, (char *)id); - } -}; -WRITE_CLASS_ENCODER(ACLID) - -typedef __u32 ACLFlags; - - -inline bool operator<(const ACLID& l, const ACLID& r) -{ - return (memcmp(&l, &r, ID_SIZE) > 0); -} - -struct ACLPair { - ACLID id; - ACLFlags flags; -}; - -class ObjectACLs { - map acls_map; - -public: - - void encode(bufferlist& bl) const { - ::encode(acls_map, bl); - } - void decode(bufferlist::iterator& bl) { - ::decode(acls_map, bl); - } - - int read_acl(ACLID& id, ACLFlags *flags); - void set_acl(ACLID& id, ACLFlags flags); -}; -WRITE_CLASS_ENCODER(ObjectACLs) - -int ObjectACLs::read_acl(ACLID& id, ACLFlags *flags) -{ - if (!flags) - return -EINVAL; - - map::iterator iter = acls_map.find(id); - - if (iter == acls_map.end()) - return -ENOENT; - - *flags = iter->second; - - return 0; -} - -void ObjectACLs::set_acl(ACLID& id, ACLFlags flags) -{ - acls_map[id] = flags; -} - - - -class ACLEntity -{ - string name; - map groups; -}; - -typedef map tACLIDEntityMap; - -static map users; -static map groups; - -void get_user(ACLID& aclid, ACLEntity *entity) -{ - //users.find(aclid); -} - - - - - -int main(int argc, const char **argv) -{ - Rados rados; - if (rados.init(NULL) < 0) { - cerr << "couldn't initialize rados!" << std::endl; - exit(1); - } - if (rados.conf_read_file(NULL)) { - cerr << "couldn't read Ceph configuration file!" << std::endl; - exit(1); - } - if (rados.connect() < 0) { - cerr << "couldn't connect to cluster!" << std::endl; - exit(1); - } - - time_t tm; - bufferlist bl, bl2; - char buf[128]; - - time(&tm); - snprintf(buf, 128, "%s", ctime(&tm)); - bl.append(buf, strlen(buf)); - - const char *oid = "bar"; - - IoCtx io_ctx; - int r = rados.ioctx_create("data", io_ctx); - cout << "open io_ctx result = " << r << " pool = " << io_ctx.get_pool_name() << std::endl; - - ACLID id; - - snprintf(id.id, ID_SIZE + 1, "%.16x", 0x1234); - cout << "id=" << id.id << std::endl; - - r = io_ctx.exec(oid, "acl", "get", bl, bl2); - cout << "exec returned " << r << " len=" << bl2.length() << std::endl; - ObjectACLs oa; - if (r >= 0) { - bufferlist::iterator iter = bl2.begin(); - oa.decode(iter); - } - - oa.set_acl(id, ACL_RD); - bl.clear(); - oa.encode(bl); - r = io_ctx.exec(oid, "acl", "set", bl, bl2); - - const unsigned char *md5 = (const unsigned char *)bl2.c_str(); - char md5_str[bl2.length()*2 + 1]; - buf_to_hex(md5, bl2.length(), md5_str); - cout << "md5 result=" << md5_str << std::endl; - - int size = io_ctx.read(oid, bl2, 128, 0); - cout << "read result=" << bl2.c_str() << std::endl; - cout << "size=" << size << std::endl; - -#if 0 - Rados::ListCtx ctx; - int entries; - do { - list vec; - r = rados.list(io_ctx, 2, vec, ctx); - entries = vec.size(); - cout << "list result=" << r << " entries=" << entries << std::endl; - list::iterator iter; - for (iter = vec.begin(); iter != vec.end(); ++iter) { - cout << *iter << std::endl; - } - } while (entries); -#endif -#if 0 - r = rados.remove(io_ctx, oid); - cout << "remove result=" << r << std::endl; - rados.close_io_ctx(io_ctx); -#endif - - return 0; -} - diff --git a/src/scratchtool.c b/src/scratchtool.c deleted file mode 100644 index 22cf2bdf531d..000000000000 --- a/src/scratchtool.c +++ /dev/null @@ -1,312 +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 - * - * 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/rados/librados.h" - -#include -#include -#include -#include -#include -#include - -static int do_rados_setxattr(rados_ioctx_t io_ctx, const char *oid, - const char *key, const char *val) -{ - int ret = rados_setxattr(io_ctx, oid, key, val, strlen(val) + 1); - if (ret < 0) { - printf("rados_setxattr failed with error %d\n", ret); - return 1; - } - printf("rados_setxattr %s=%s\n", key, val); - return 0; -} - -static int do_rados_getxattr(rados_ioctx_t io_ctx, const char *oid, - const char *key, const char *expected) -{ - size_t blen = strlen(expected) + 1; - char buf[blen]; - memset(buf, 0, sizeof(buf)); - int r = rados_getxattr(io_ctx, oid, key, buf, blen); - if (r < 0) { - printf("rados_getxattr(%s) failed with error %d\n", key, r); - return 1; - } - if (strcmp(buf, expected) != 0) { - printf("rados_getxattr(%s) got wrong result! " - "expected: '%s'. got '%s'\n", key, expected, buf); - return 1; - } - printf("rados_getxattr %s=%s\n", key, buf); - return 0; -} - -static int do_rados_getxattrs(rados_ioctx_t io_ctx, const char *oid, - const char **exkeys, const char **exvals) -{ - rados_xattrs_iter_t iter; - int nval = 0, i, nfound = 0, ret = 0; - - for (i = 0; exvals[i]; ++i) { - ++nval; - } - ret = rados_getxattrs(io_ctx, oid, &iter); - if (ret) { - printf("rados_getxattrs(%s) failed with error %d\n", oid, ret); - return 1; - } - while (1) { - size_t len; - const char *key, *val; - ret = rados_getxattrs_next(iter, &key, &val, &len); - if (ret) { - printf("rados_getxattrs(%s): rados_getxattrs_next " - "returned error %d\n", oid, ret); - return 1; - } - if (!key) - break; - for (i = 0; i < nval; ++i) { - if (strcmp(exkeys[i], key)) - continue; - if ((len == strlen(exvals[i]) + 1) && (!strcmp(exvals[i], val))) { - nfound++; - break; - } - printf("rados_getxattrs(%s): got key %s, but the " - "value was %s rather than %s.\n", - oid, key, val, exvals[i]); - return 1; - } - } - if (nfound != nval) { - printf("rados_getxattrs(%s): only found %d extended attributes. " - "Expected %d\n", oid, nfound, nval); - return 1; - } - rados_getxattrs_end(iter); - printf("rados_getxattrs(%s)\n", oid); - return 0; -} - -static int testrados(void) -{ - char tmp[32]; - int i, r; - int ret = 1; //set 1 as error case - rados_t cl; - - if (rados_create(&cl, NULL) < 0) { - printf("error initializing\n"); - return 1; - } - - if (rados_conf_read_file(cl, NULL)) { - printf("error reading configuration file\n"); - goto out_err; - } - - // Try to set a configuration option that doesn't exist. - // This should fail. - if (!rados_conf_set(cl, "config option that doesn't exist", - "some random value")) { - printf("error: succeeded in setting nonexistent config option\n"); - goto out_err; - } - - if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) { - printf("error: failed to read log_to_stderr from config\n"); - goto out_err; - } - - // Can we change it? - if (rados_conf_set(cl, "log to stderr", "true")) { - printf("error: error setting log_to_stderr\n"); - goto out_err; - } - if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) { - printf("error: failed to read log_to_stderr from config\n"); - goto out_err; - } - if (strcmp(tmp, "true")) { - printf("error: new setting for log_to_stderr failed to take effect.\n"); - goto out_err; - } - - if (rados_connect(cl)) { - printf("error connecting\n"); - goto out_err; - } - if (rados_connect(cl) == 0) { - printf("second connect attempt didn't return an error\n"); - goto out_err; - } - - /* create an io_ctx */ - r = rados_pool_create(cl, "foo"); - printf("rados_pool_create = %d\n", r); - - rados_ioctx_t io_ctx; - r = rados_ioctx_create(cl, "foo", &io_ctx); - printf("rados_ioctx_create = %d, io_ctx = %p\n", r, io_ctx); - - /* list all pools */ - { - int buf_sz = rados_pool_list(cl, NULL, 0); - printf("need buffer size of %d\n", buf_sz); - char buf[buf_sz]; - int r = rados_pool_list(cl, buf, buf_sz); - if (r != buf_sz) { - printf("buffer size mismatch: got %d the first time, but %d " - "the second.\n", buf_sz, r); - goto out_err; - } - const char *b = buf; - printf("begin pools.\n"); - while (1) { - if (b[0] == '\0') - break; - printf(" pool: '%s'\n", b); - b += strlen(b) + 1; - }; - printf("end pools.\n"); - } - - - /* stat */ - struct rados_pool_stat_t st; - r = rados_ioctx_pool_stat(io_ctx, &st); - printf("rados_ioctx_pool_stat = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects); - - /* snapshots */ - r = rados_ioctx_snap_create(io_ctx, "snap1"); - printf("rados_ioctx_snap_create snap1 = %d\n", r); - rados_snap_t snaps[10]; - r = rados_ioctx_snap_list(io_ctx, snaps, 10); - for (i=0; i - * - * 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/types.h" -#include "include/rados/librados.hpp" - -using namespace librados; - -#include - -#include -#include -#include - -void buf_to_hex(const unsigned char *buf, int len, char *str) -{ - str[0] = '\0'; - for (int i = 0; i < len; i++) { - sprintf(&str[i*2], "%02x", (int)buf[i]); - } -} - -class C_Watch : public WatchCtx { -public: - C_Watch() {} - void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) { - cout << "C_Watch::notify() opcode=" << (int)opcode << " ver=" << ver << std::endl; - } -}; - -void testradospp_milestone(void) -{ - cout << "*** press enter to continue ***" << std::endl; - getchar(); -} - -int main(int argc, const char **argv) -{ - Rados rados; - if (rados.init(NULL) < 0) { - cerr << "couldn't initialize rados!" << std::endl; - exit(1); - } - - if (rados.conf_read_file(NULL)) { - cerr << "couldn't read configuration file." << std::endl; - exit(1); - } - rados.conf_parse_argv(argc, argv); - - if (!rados.conf_set("config option that doesn't exist", - "some random value")) { - printf("error: succeeded in setting nonexistent config option\n"); - exit(1); - } - if (rados.conf_set("log to stderr", "true")) { - printf("error: error setting log_to_stderr\n"); - exit(1); - } - std::string tmp; - if (rados.conf_get("log to stderr", tmp)) { - printf("error: failed to read log_to_stderr from config\n"); - exit(1); - } - if (tmp != "true") { - printf("error: new setting for log_to_stderr failed to take effect.\n"); - exit(1); - } - - if (rados.connect()) { - printf("error connecting\n"); - exit(1); - } - - cout << "rados_initialize completed" << std::endl; - testradospp_milestone(); - - time_t tm; - bufferlist bl, bl2, blf; - char buf[128]; - - time(&tm); - snprintf(buf, 128, "%s", ctime(&tm)); - bl.append(buf, strlen(buf)); - blf.append(buf, 16); - - const char *oid = "bar"; - - IoCtx io_ctx; - int r = rados.ioctx_create("data", io_ctx); - cout << "ioctx_create result = " << r << std::endl; - - r = io_ctx.write(oid, bl, bl.length(), 0); - uint64_t objver = io_ctx.get_last_version(); - assert(objver > 0); - cout << "io_ctx.write returned " << r << " last_ver=" << objver << std::endl; - - uint64_t stat_size; - time_t stat_mtime; - r = io_ctx.stat(oid, &stat_size, &stat_mtime); - cout << "io_ctx.stat returned " << r << " size = " << stat_size << " mtime = " << stat_mtime << std::endl; - - r = io_ctx.stat(oid, NULL, NULL); - cout << "io_ctx.stat(does_not_exist) = " << r; - - uint64_t handle; - C_Watch wc; - r = io_ctx.watch(oid, objver, &handle, &wc); - cout << "io_ctx.watch returned " << r << std::endl; - - testradospp_milestone(); - io_ctx.set_notify_timeout(7); - bufferlist notify_bl; - r = io_ctx.notify(oid, objver, notify_bl); - cout << "io_ctx.notify returned " << r << std::endl; - testradospp_milestone(); - - r = io_ctx.notify(oid, objver, notify_bl); - cout << "io_ctx.notify returned " << r << std::endl; - testradospp_milestone(); - - r = io_ctx.unwatch(oid, handle); - cout << "io_ctx.unwatch returned " << r << std::endl; - cout << "*** press enter to continue ***" << std::endl; - testradospp_milestone(); - - r = io_ctx.notify(oid, objver, notify_bl); - cout << "io_ctx.notify returned " << r << std::endl; - cout << "*** press enter to continue ***" << std::endl; - testradospp_milestone(); - io_ctx.set_assert_version(objver); - - r = io_ctx.write(oid, bl, bl.length() - 1, 0); - cout << "io_ctx.write returned " << r << std::endl; - - r = io_ctx.write(oid, bl, bl.length() - 2, 0); - cout << "io_ctx.write returned " << r << std::endl; - r = io_ctx.write(oid, bl, bl.length() - 3, 0); - cout << "rados.write returned " << r << std::endl; - r = io_ctx.append(oid, bl, bl.length()); - cout << "rados.write returned " << r << std::endl; - r = io_ctx.write_full(oid, blf); - cout << "rados.write_full returned " << r << std::endl; - r = io_ctx.read(oid, bl, bl.length(), 0); - cout << "rados.read returned " << r << std::endl; - r = io_ctx.trunc(oid, 8); - cout << "rados.trunc returned " << r << std::endl; - r = io_ctx.read(oid, bl, bl.length(), 0); - cout << "rados.read returned " << r << std::endl; - r = io_ctx.exec(oid, "crypto", "md5", bl, bl2); - cout << "exec returned " << r << " buf size=" << bl2.length() << std::endl; - const unsigned char *md5 = (const unsigned char *)bl2.c_str(); - char md5_str[bl2.length()*2 + 1]; - buf_to_hex(md5, bl2.length(), md5_str); - cout << "md5 result=" << md5_str << std::endl; - - // test assert_version - r = io_ctx.read(oid, bl, 0, 1); - assert(r >= 0); - uint64_t v = io_ctx.get_last_version(); - cout << oid << " version is " << v << std::endl; - assert(v > 0); - io_ctx.set_assert_version(v); - r = io_ctx.read(oid, bl, 0, 1); - assert(r >= 0); - io_ctx.set_assert_version(v - 1); - r = io_ctx.read(oid, bl, 0, 1); - assert(r == -ERANGE); - io_ctx.set_assert_version(v + 1); - r = io_ctx.read(oid, bl, 0, 1); - assert(r == -EOVERFLOW); - - // test assert_src_version - const char *dest = "baz"; - r = io_ctx.read(oid, bl, 0, 1); - assert(r >= 0); - v = io_ctx.get_last_version(); - cout << oid << " version is " << v << std::endl; - io_ctx.set_assert_src_version(oid, v); - r = io_ctx.clone_range(dest, 0, oid, 0, 1); - assert(r >= 0); - io_ctx.set_assert_src_version(oid, v-1); - r = io_ctx.clone_range(dest, 0, oid, 0, 1); - assert(r == -ERANGE); - io_ctx.set_assert_src_version(oid, v+1); - r = io_ctx.clone_range(dest, 0, oid, 0, 1); - assert(r == -EOVERFLOW); - - r = io_ctx.exec(oid, "crypto", "sha1", bl, bl2); - cout << "exec returned " << r << std::endl; - const unsigned char *sha1 = (const unsigned char *)bl2.c_str(); - char sha1_str[bl2.length()*2 + 1]; - buf_to_hex(sha1, bl2.length(), sha1_str); - cout << "sha1 result=" << sha1_str << std::endl; - - r = io_ctx.exec(oid, "acl", "set", bl, bl2); - cout << "exec (set) returned " << r << std::endl; - r = io_ctx.exec(oid, "acl", "get", bl, bl2); - cout << "exec (get) returned " << r << std::endl; - if (bl2.length() > 0) { - cout << "attr=" << bl2.c_str() << std::endl; - } - - int size = io_ctx.read(oid, bl2, 128, 0); - if (size <= 0) { - cout << "failed to read oid " << oid << "." << std::endl; - exit(1); - } - if (size > 4096) { - cout << "read too many bytes from oid " << oid << "." << std::endl; - exit(1); - } - char rbuf[size + 1]; - memcpy(rbuf, bl2.c_str(), size); - rbuf[size] = '\0'; - cout << "read result='" << rbuf << "'" << std::endl; - cout << "size=" << size << std::endl; - - const char *oid2 = "jjj10.rbd"; - r = io_ctx.exec(oid2, "rbd", "snap_list", bl, bl2); - cout << "snap_list result=" << r << std::endl; - r = io_ctx.exec(oid2, "rbd", "snap_add", bl, bl2); - cout << "snap_add result=" << r << std::endl; - - if (r > 0) { - char *s = bl2.c_str(); - for (int i=0; i= 0); - { - ObjectReadOperation o; - o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val); - r = io_ctx.operate(oid, &o, &bl2); - cout << " got " << r << " wanted >= 0" << std::endl; - assert(r >= 0); - } - val.append("..."); - { - ObjectReadOperation o; - o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val); - r = io_ctx.operate(oid, &o, &bl2); - cout << " got " << r << " wanted ECANCELED" << std::endl; - assert(r == -ECANCELED); - } - - cout << "src_cmpxattr" << std::endl; - const char *oidb = "bar-clone"; - { - ObjectWriteOperation o; - o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_EQ, val); - io_ctx.locator_set_key(oid); - o.write_full(val); - r = io_ctx.operate(oidb, &o); - cout << " got " << r << " wanted ECANCELED" << std::endl; - assert(r == -ECANCELED); - } - { - ObjectWriteOperation o; - o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_NE, val); - io_ctx.locator_set_key(oid); - o.write_full(val); - r = io_ctx.operate(oidb, &o); - cout << " got " << r << " wanted >= 0" << std::endl; - assert(r >= 0); - } - io_ctx.locator_set_key(string()); - - - cout << "iterating over objects..." << std::endl; - int num_objs = 0; - for (ObjectIterator iter = io_ctx.objects_begin(); - iter != io_ctx.objects_end(); ++iter) { - num_objs++; - cout << "'" << *iter << "'" << std::endl; - } - cout << "iterated over " << num_objs << " objects." << std::endl; - map attrset; - io_ctx.getxattrs(oid, attrset); - - map::iterator it; - for (it = attrset.begin(); it != attrset.end(); ++it) { - cout << "xattr: " << it->first << std::endl; - } - - r = io_ctx.remove(oid); - cout << "remove result=" << r << std::endl; - rados.shutdown(); - - return 0; -} - diff --git a/src/tools/ceph_authtool.cc b/src/tools/ceph_authtool.cc new file mode 100644 index 000000000000..f66a3c66eee9 --- /dev/null +++ b/src/tools/ceph_authtool.cc @@ -0,0 +1,277 @@ +// -*- 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-2009 Sage Weil + * + * 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 "common/config.h" +#include "common/strtol.h" + +#include "common/ConfUtils.h" +#include "common/ceph_argparse.h" +#include "global/global_context.h" +#include "global/global_init.h" +#include "auth/Crypto.h" +#include "auth/Auth.h" +#include "auth/KeyRing.h" + +#include + +void usage() +{ + cout << "usage: ceph-authtool keyringfile [OPTIONS]...\n" + << "where the options are:\n" + << " -l, --list will list all keys and capabilities present in\n" + << " the keyring\n" + << " -p, --print-key will print an encoded key for the specified\n" + << " entityname. This is suitable for the\n" + << " 'mount -o secret=..' argument\n" + << " -C, --create-keyring will create a new keyring, overwriting any\n" + << " existing keyringfile\n" + << " -g, --gen-key will generate a new secret key for the\n" + << " specified entityname\n" + << " --gen-print-key will generate a new secret key without set it\n" + << " to the keyringfile, prints the secret to stdout\n" + << " --import-keyring will import the content of a given keyring\n" + << " into the keyringfile\n" + << " -u, --set-uid sets the auid (authenticated user id) for the\n" + << " specified entityname\n" + << " -a, --add-key will add an encoded key to the keyring\n" + << " --cap subsystem capability will set the capability for given subsystem\n" + << " --caps capsfile will set all of capabilities associated with a\n" + << " given key, for all subsystems" + << std::endl; + exit(1); +} + +int main(int argc, const char **argv) +{ + vector args; + argv_to_vec(argc, argv, args); + env_to_vec(args); + + bool gen_key = false; + bool gen_print_key = false; + std::string add_key; + bool list = false; + bool print_key = false; + bool create_keyring = false; + std::string caps_fn; + std::string import_keyring; + bool set_auid = false; + uint64_t auid = CEPH_AUTH_UID_DEFAULT; + map caps; + std::string fn; + + global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); + std::vector::iterator i; + for (i = args.begin(); i != args.end(); ) { + std::string val; + if (ceph_argparse_double_dash(args, i)) { + break; + } else if (ceph_argparse_flag(args, i, "-g", "--gen-key", (char*)NULL)) { + gen_key = true; + } else if (ceph_argparse_flag(args, i, "--gen-print-key", (char*)NULL)) { + gen_print_key = true; + } else if (ceph_argparse_witharg(args, i, &val, "-a", "--add-key", (char*)NULL)) { + add_key = val; + } else if (ceph_argparse_flag(args, i, &val, "-l", "--list", (char*)NULL)) { + list = true; + } else if (ceph_argparse_witharg(args, i, &val, "--caps", (char*)NULL)) { + caps_fn = val; + } else if (ceph_argparse_witharg(args, i, &val, "--cap", (char*)NULL)) { + std::string my_key = val; + if (i == args.end()) { + cerr << "must give two arguments to --cap: key and val." << std::endl; + exit(1); + } + std::string my_val = *i; + ++i; + ::encode(my_val, caps[my_key]); + } else if (ceph_argparse_flag(args, i, "-p", "--print-key", (char*)NULL)) { + print_key = true; + } else if (ceph_argparse_flag(args, i, "-C", "--create-keyring", (char*)NULL)) { + create_keyring = true; + } else if (ceph_argparse_witharg(args, i, &val, "--import-keyring", (char*)NULL)) { + import_keyring = val; + } else if (ceph_argparse_witharg(args, i, &val, "-u", "--set-uid", (char*)NULL)) { + std::string err; + auid = strict_strtoll(val.c_str(), 10, &err); + if (!err.empty()) { + cerr << "error parsing UID: " << err << std::endl; + exit(1); + } + set_auid = true; + } else if (fn.empty()) { + fn = *i++; + } else { + cerr << argv[0] << ": unexpected '" << *i << "'" << std::endl; + usage(); + } + } + if (fn.empty() && !gen_print_key) { + cerr << argv[0] << ": must specify filename" << std::endl; + usage(); + } + if (!(gen_key || + gen_print_key || + !add_key.empty() || + list || + !caps_fn.empty() || + !caps.empty() || + set_auid || + print_key || + create_keyring || + !import_keyring.empty())) { + cerr << "no command specified" << std::endl; + usage(); + } + if (gen_key && (!add_key.empty())) { + cerr << "can't both gen_key and add_key" << std::endl; + usage(); + } + + common_init_finish(g_ceph_context); + EntityName ename(g_conf->name); + + if (gen_print_key) { + CryptoKey key; + key.create(g_ceph_context, CEPH_CRYPTO_AES); + cout << key << std::endl; + return 0; + } + + // keyring -------- + bool modified = false; + KeyRing keyring; + + bufferlist bl; + int r = 0; + if (create_keyring) { + cout << "creating " << fn << std::endl; + modified = true; + } else { + std::string err; + r = bl.read_file(fn.c_str(), &err); + if (r >= 0) { + try { + bufferlist::iterator iter = bl.begin(); + ::decode(keyring, iter); + } catch (const buffer::error &err) { + cerr << "error reading file " << fn << std::endl; + exit(1); + } + } else { + cerr << "can't open " << fn << ": " << err << std::endl; + exit(1); + } + } + + // write commands + if (!import_keyring.empty()) { + KeyRing other; + bufferlist obl; + std::string err; + int r = obl.read_file(import_keyring.c_str(), &err); + if (r >= 0) { + try { + bufferlist::iterator iter = obl.begin(); + ::decode(other, iter); + } catch (const buffer::error &err) { + cerr << "error reading file " << import_keyring << std::endl; + exit(1); + } + + cout << "importing contents of " << import_keyring << " into " << fn << std::endl; + //other.print(cout); + keyring.import(g_ceph_context, other); + modified = true; + } else { + cerr << "can't open " << import_keyring << ": " << err << std::endl; + exit(1); + } + } + if (gen_key) { + EntityAuth eauth; + eauth.key.create(g_ceph_context, CEPH_CRYPTO_AES); + keyring.add(ename, eauth); + modified = true; + } + if (!add_key.empty()) { + EntityAuth eauth; + try { + eauth.key.decode_base64(add_key); + } catch (const buffer::error &err) { + cerr << "can't decode key '" << add_key << "'" << std::endl; + exit(1); + } + keyring.add(ename, eauth); + modified = true; + cout << "added entity " << ename << " auth " << eauth << std::endl; + } + if (!caps_fn.empty()) { + ConfFile cf; + std::deque parse_errors; + if (cf.parse_file(caps_fn, &parse_errors, &cerr) != 0) { + cerr << "could not parse caps file " << caps_fn << std::endl; + exit(1); + } + complain_about_parse_errors(g_ceph_context, &parse_errors); + map caps; + const char *key_names[] = { "mon", "osd", "mds", NULL }; + for (int i=0; key_names[i]; i++) { + std::string val; + if (cf.read("global", key_names[i], val) == 0) { + bufferlist bl; + ::encode(val, bl); + string s(key_names[i]); + caps[s] = bl; + } + } + keyring.set_caps(ename, caps); + modified = true; + } + if (!caps.empty()) { + keyring.set_caps(ename, caps); + modified = true; + } + if (set_auid) { + keyring.set_uid(ename, auid); + modified = true; + } + + // read commands + if (list) { + keyring.print(cout); + } + if (print_key) { + CryptoKey key; + if (keyring.get_secret(ename, key)) { + cout << key << std::endl; + } else { + cerr << "entity " << ename << " not found" << std::endl; + } + } + + // write result? + if (modified) { + bufferlist bl; + keyring.encode_plaintext(bl); + r = bl.write_file(fn.c_str(), 0600); + if (r < 0) { + cerr << "could not write " << fn << std::endl; + } + //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl; + } + + return 0; +} diff --git a/src/tools/ceph_conf.cc b/src/tools/ceph_conf.cc new file mode 100644 index 000000000000..b2286f4e0944 --- /dev/null +++ b/src/tools/ceph_conf.cc @@ -0,0 +1,223 @@ +// -*- 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-2010 Dreamhost + * + * 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 "mon/AuthMonitor.h" +#include "common/ConfUtils.h" +#include "global/global_init.h" +#include "common/entity_name.h" +#include "common/ceph_argparse.h" +#include "common/config.h" +#include "include/str_list.h" + +using std::deque; +using std::string; + +static void usage() +{ + // TODO: add generic_usage once cerr/derr issues are resolved + cerr << "Ceph configuration query tool\n\ +\n\ +USAGE\n\ +ceph-conf \n\ +\n\ +ACTIONS\n\ + -L|--list-all-sections List all sections\n\ + -l|--list-sections List sections with the given prefix\n\ + --filter-key Filter section list to only include sections\n\ + with given key defined.\n\ + --filter-key-value = Filter section list to only include sections\n\ + with given key/value pair.\n\ + --lookup Print a configuration setting to stdout.\n\ + Returns 0 (success) if the configuration setting is\n\ + found; 1 otherwise.\n\ + -r|--resolve-search search for the first file that exists and\n\ + can be opened in the resulted comma\n\ + delimited search list.\n\ +\n\ +FLAGS\n\ + --name name Set type.id\n\ + [-s
] Add to list of sections to search\n\ +\n\ +If there is no action given, the action will default to --lookup.\n\ +\n\ +EXAMPLES\n\ +$ ceph-conf --name mon.0 -c /etc/ceph/ceph.conf 'mon addr'\n\ +Find out what the value of 'mon add' is for monitor 0.\n\ +\n\ +$ ceph-conf -l mon\n\ +List sections beginning with 'mon'.\n\ +\n\ +RETURN CODE\n\ +Return code will be 0 on success; error code otherwise.\n\ +"; + exit(1); +} + +static int list_sections(const std::string &prefix, + const std::list& filter_key, + const std::map& filter_key_value) +{ + std::vector sections; + int ret = g_conf->get_all_sections(sections); + if (ret) + return 2; + for (std::vector::const_iterator p = sections.begin(); + p != sections.end(); ++p) { + if (strncmp(prefix.c_str(), p->c_str(), prefix.size())) + continue; + + std::vector sec; + sec.push_back(*p); + + int r = 0; + for (std::list::const_iterator q = filter_key.begin(); q != filter_key.end(); ++q) { + string v; + r = g_conf->get_val_from_conf_file(sec, q->c_str(), v, false); + if (r < 0) + break; + } + if (r < 0) + continue; + + for (std::map::const_iterator q = filter_key_value.begin(); + q != filter_key_value.end(); + ++q) { + string v; + r = g_conf->get_val_from_conf_file(sec, q->first.c_str(), v, false); + if (r < 0 || v != q->second) { + r = -1; + break; + } + } + if (r < 0) + continue; + + cout << *p << std::endl; + } + return 0; +} + +static int lookup(const std::deque §ions, + const std::string &key, bool resolve_search) +{ + std::vector my_sections; + for (deque::const_iterator s = sections.begin(); s != sections.end(); ++s) { + my_sections.push_back(*s); + } + g_conf->get_my_sections(my_sections); + std::string val; + int ret = g_conf->get_val_from_conf_file(my_sections, key.c_str(), val, true); + if (ret == -ENOENT) + return 1; + else if (ret == 0) { + if (resolve_search) { + string result; + if (ceph_resolve_file_search(val, result)) + puts(result.c_str()); + } + else { + puts(val.c_str()); + } + return 0; + } + else { + cerr << "error looking up '" << key << "': error " << ret << std::endl; + return 2; + } +} + +int main(int argc, const char **argv) +{ + vector args; + deque sections; + bool resolve_search = false; + std::string action; + std::string lookup_key; + std::string section_list_prefix; + std::list filter_key; + std::map filter_key_value; + + argv_to_vec(argc, argv, args); + env_to_vec(args); + + global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON, + CINIT_FLAG_NO_DAEMON_ACTIONS); + + // do not common_init_finish(); do not start threads; do not do any of thing + // wonky things the daemon whose conf we are examining would do (like initialize + // the admin socket). + //common_init_finish(g_ceph_context); + + std::string val; + for (std::vector::iterator i = args.begin(); i != args.end(); ) { + if (ceph_argparse_double_dash(args, i)) { + break; + } else if (ceph_argparse_witharg(args, i, &val, "-s", "--section", (char*)NULL)) { + sections.push_back(val); + } else if (ceph_argparse_flag(args, i, "-r", "--resolve_search", (char*)NULL)) { + resolve_search = true; + } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) { + action = "help"; + } else if (ceph_argparse_witharg(args, i, &val, "--lookup", (char*)NULL)) { + action = "lookup"; + lookup_key = val; + } else if (ceph_argparse_flag(args, i, "-L", "--list_all_sections", (char*)NULL)) { + action = "list-sections"; + section_list_prefix = ""; + } else if (ceph_argparse_witharg(args, i, &val, "-l", "--list_sections", (char*)NULL)) { + action = "list-sections"; + section_list_prefix = val; + } else if (ceph_argparse_witharg(args, i, &val, "--filter_key", (char*)NULL)) { + filter_key.push_back(val); + } else if (ceph_argparse_witharg(args, i, &val, "--filter_key_value", (char*)NULL)) { + size_t pos = val.find_first_of('='); + if (pos == string::npos) { + cerr << "expecting argument like 'key=value' for --filter-key-value (not '" << val << "')" << std::endl; + usage(); + exit(1); + } + string key(val, 0, pos); + string value(val, pos+1); + filter_key_value[key] = value; + } else { + if (((action == "lookup") || (action == "")) && (lookup_key.empty())) { + action = "lookup"; + lookup_key = *i++; + } else { + cerr << "unable to parse option: '" << *i << "'" << std::endl; + usage(); + exit(1); + } + } + } + + if (action == "help") { + usage(); + exit(0); + } else if (action == "list-sections") { + return list_sections(section_list_prefix, filter_key, filter_key_value); + } else if (action == "lookup") { + return lookup(sections, lookup_key, resolve_search); + } else { + cerr << "You must give an action, such as --lookup or --list-all-sections." << std::endl; + cerr << "Pass --help for more help." << std::endl; + exit(1); + } +} diff --git a/src/tools/crushtool.cc b/src/tools/crushtool.cc new file mode 100644 index 000000000000..75c26c098b66 --- /dev/null +++ b/src/tools/crushtool.cc @@ -0,0 +1,724 @@ +// -*- 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 + * + * 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/ceph_argparse.h" +#include "global/global_context.h" +#include "global/global_init.h" +#include "crush/CrushWrapper.h" +#include "crush/CrushCompiler.h" +#include "crush/CrushTester.h" +#include "include/assert.h" + +#define dout_subsys ceph_subsys_crush + +using namespace std; + +const char *infn = "stdin"; + + +//////////////////////////////////////////////////////////////////////////// + +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 << " --decompile|-d map decompile a crush map to source\n"; + cout << " --compile|-c map.txt compile a map from source\n"; + cout << " [-o outfile [--clobber]]\n"; + cout << " specify output for for (de)compilation\n"; + cout << " --build --num_osds N layer1 ...\n"; + cout << " build a new map, where each 'layer' is\n"; + cout << " 'name (uniform|straw|list|tree) size'\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]\n"; + cout << " [--num-rep n]\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 << " -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 << " --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-bad-mappings show bad mappings\n"; + cout << " --show-choose-tries show choose tries histogram\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 << " --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"; +} + +struct bucket_types_t { + const char *name; + int type; +} bucket_types[] = { + { "uniform", CRUSH_BUCKET_UNIFORM }, + { "list", CRUSH_BUCKET_LIST }, + { "straw", CRUSH_BUCKET_STRAW }, + { "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 test = false; + bool display = false; + bool write_to_file = false; + int verbose = 0; + bool unsafe_tunables = false; + + bool reweight = false; + int add_item = -1; + bool update_item = 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; + + CrushWrapper crush; + + CrushTester tester(crush, cerr, 1); + + vector empty_args; // we use -c, don't confuse the generic arg parsing + global_init(NULL, empty_args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); + common_init_finish(g_ceph_context); + + int x; + float y; + + 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(); + exit(0); + } 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, "--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_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_flag(args, i, "-t", "--test", (char*)NULL)) { + test = true; + } 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_withint(args, i, &choose_local_tries, &err, + "--set_choose_local_tries", (char*)NULL)) { + adjust = true; + } else if (ceph_argparse_withint(args, i, &choose_local_fallback_tries, &err, + "--set_choose_local_fallback_tries", (char*)NULL)) { + adjust = true; + } else if (ceph_argparse_withint(args, i, &choose_total_tries, &err, + "--set_choose_total_tries", (char*)NULL)) { + adjust = true; + } else if (ceph_argparse_withint(args, i, &chooseleaf_descend_once, &err, + "--set_chooseleaf_descend_once", (char*)NULL)) { + adjust = true; + } else if (ceph_argparse_flag(args, i, "--reweight", (char*)NULL)) { + reweight = true; + } else if (ceph_argparse_withint(args, i, &add_item, &err, "--add_item", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + if (i == args.end()) { + cerr << "expecting additional argument to --add-item" << std::endl; + exit(EXIT_FAILURE); + } + add_weight = atof(*i); + i = args.erase(i); + if (i == args.end()) { + cerr << "expecting additional argument to --add-item" << std::endl; + exit(EXIT_FAILURE); + } + add_name.assign(*i); + i = args.erase(i); + } else if (ceph_argparse_withint(args, i, &add_item, &err, "--update_item", (char*)NULL)) { + update_item = true; + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + if (i == args.end()) { + cerr << "expecting additional argument to --update-item" << std::endl; + exit(EXIT_FAILURE); + } + add_weight = atof(*i); + i = args.erase(i); + if (i == args.end()) { + cerr << "expecting additional argument to --update-item" << std::endl; + exit(EXIT_FAILURE); + } + add_name.assign(*i); + i = args.erase(i); + } 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; + exit(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(); + exit(0); + } 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; + exit(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; + exit(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_withint(args, i, &num_osds, &err, "--num_osds", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + } else if (ceph_argparse_withint(args, i, &x, &err, "--num_rep", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_num_rep(x); + } else if (ceph_argparse_withint(args, i, &x, &err, "--max_x", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_max_x(x); + } else if (ceph_argparse_withint(args, i, &x, &err, "--min_x", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_min_x(x); + } else if (ceph_argparse_withint(args, i, &x, &err, "--x", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_x(x); + } else if (ceph_argparse_withint(args, i, &x, &err, "--max_rule", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_max_rule(x); + } else if (ceph_argparse_withint(args, i, &x, &err, "--min_rule", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_min_rule(x); + } else if (ceph_argparse_withint(args, i, &x, &err, "--rule", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_rule(x); + } else if (ceph_argparse_withint(args, i, &x, &err, "--batches", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_batches(x); + } else if (ceph_argparse_withfloat(args, i, &y, &err, "--mark-down-ratio", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_device_down_ratio(y); + } else if (ceph_argparse_withfloat(args, i, &y, &err, "--mark-down-bucket-ratio", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + tester.set_bucket_down_ratio(y); + } else if (ceph_argparse_withint(args, i, &tmp, &err, "--weight", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + int dev = tmp; + if (i == args.end()) { + cerr << "expecting additional argument to --weight" << std::endl; + exit(EXIT_FAILURE); + } + float f = atof(*i); + i = args.erase(i); + tester.set_device_weight(dev, f); + } + else { + ++i; + } + } + + if (test && !display && !write_to_file) { + cerr << "WARNING: no output selected; use --output-csv or --show-X" << std::endl; + exit(EXIT_FAILURE); + } + + if (decompile + compile + build > 1) { + cout << "cannot specify more than one of compile, decompile, and build" << std::endl; + exit(EXIT_FAILURE); + } + if (!compile && !decompile && !build && !test && !reweight && !adjust && + add_item < 0 && + remove_name.empty() && reweight_name.empty()) { + cout << "no action specified; -h for help" << std::endl; + exit(EXIT_FAILURE); + } + if ((!build) && (!args.empty())) { + cerr << "unrecognized arguments: " << args << std::endl; + exit(EXIT_FAILURE); + } + else { + if ((args.size() % 3) != 0U) { + cerr << "layers must be specified with 3-tuples of (name, buckettype, size)" + << std::endl; + exit(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; + + if (!infn.empty()) { + bufferlist bl; + std::string error; + int r = bl.read_file(infn.c_str(), &error); + if (r < 0) { + cerr << me << ": error reading '" << infn << "': " + << error << std::endl; + exit(1); + } + bufferlist::iterator p = bl.begin(); + crush.decode(p); + } + + 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; + exit(1); + } + cc.decompile(o); + o.close(); + } else { + cc.decompile(cout); + } + } + + 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) + exit(1); + + modified = true; + } + + if (build) { + if (layers.empty()) { + cerr << me << ": must specify at least one layer" << std::endl; + exit(1); + } + + crush.create(); + + vector lower_items; + vector lower_weights; + + for (int i=0; i::iterator p = layers.begin(); p != layers.end(); ++p, type++) { + layer_t &l = *p; + + dout(0) << "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 << std::endl; + exit(EXIT_FAILURE); + } + + // build items + vector cur_items; + vector cur_weights; + unsigned lower_pos = 0; // lower pos + + dout(0) << "lower_items " << lower_items << dendl; + dout(0) << "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= 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 (reweight) { + crush.reweight(g_ceph_context); + modified = true; + } + + const char *scary_tunables_message = + "** tunables are DANGEROUS and NOT YET RECOMMENDED. DO NOT USE without\n" + "** confirming with developers that your use-case is safe and correct."; + if (choose_local_tries >= 0) { + if (!unsafe_tunables) { + cerr << scary_tunables_message << std::endl; + return -1; + } + crush.set_choose_local_tries(choose_local_tries); + modified = true; + } + if (choose_local_fallback_tries >= 0) { + if (!unsafe_tunables) { + cerr << scary_tunables_message << std::endl; + return -1; + } + crush.set_choose_local_fallback_tries(choose_local_fallback_tries); + modified = true; + } + if (choose_total_tries >= 0) { + if (!unsafe_tunables) { + cerr << scary_tunables_message << std::endl; + return -1; + } + crush.set_choose_total_tries(choose_total_tries); + modified = true; + } + if (chooseleaf_descend_once >= 0) { + if (!unsafe_tunables) { + cerr << scary_tunables_message << std::endl; + return -1; + } + crush.set_chooseleaf_descend_once(chooseleaf_descend_once); + modified = true; + } + 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); + int r = bl.write_file(outfn.c_str()); + if (r < 0) { + char buf[80]; + cerr << me << ": error writing '" << outfn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl; + exit(1); + } + if (verbose) + cout << "wrote crush map to " << outfn << std::endl; + } + } + + if (test) { + int r = tester.test(); + if (r < 0) + exit(1); + } + + return 0; +} diff --git a/src/tools/dupstore.cc b/src/tools/dupstore.cc new file mode 100644 index 000000000000..e17eb2201a7a --- /dev/null +++ b/src/tools/dupstore.cc @@ -0,0 +1,114 @@ +// -*- 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 + * + * 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 "os/FileStore.h" +#include "common/ceph_argparse.h" +#include "global/global_init.h" + +#include +using __gnu_cxx::hash_map; + +int dupstore(ObjectStore* src, ObjectStore* dst) +{ + if (src->mount() < 0) return 1; + if (dst->mkfs() < 0) return 1; + if (dst->mount() < 0) return 1; + + // objects + hash_map did_object; + + // collections + vector collections; + + int ret = src->list_collections(collections); + if (ret < 0) { + cerr << "Error " << ret << " while listing collections" << std::endl; + return 1; + } + + int num = collections.size(); + cout << num << " collections" << std::endl; + int i = 1; + for (vector::iterator p = collections.begin(); + p != collections.end(); + ++p) { + cout << "collection " << i++ << "/" << num << " " << hex << *p << dec << std::endl; + { + ObjectStore::Transaction t; + t.create_collection(*p); + map attrs; + src->collection_getattrs(*p, attrs); + t.collection_setattrs(*p, attrs); + dst->apply_transaction(t); + } + + vector o; + src->collection_list(*p, o); + int numo = o.size(); + int j = 1; + for (vector::iterator q = o.begin(); q != o.end(); ++q) { + ObjectStore::Transaction t; + if (did_object.count(*q)) + t.collection_add(*p, did_object[*q], *q); + else { + bufferlist bl; + src->read(*p, *q, 0, 0, bl); + cout << "object " << j++ << "/" << numo << " " << *q << " = " << bl.length() << " bytes" << std::endl; + t.write(*p, *q, 0, bl.length(), bl); + map attrs; + src->getattrs(*p, *q, attrs); + t.setattrs(*p, *q, attrs); + did_object[*q] = *p; + } + dst->apply_transaction(t); + } + } + + src->umount(); + dst->umount(); + return 0; +} + +void usage() +{ + cerr << "usage: ceph_dupstore filestore SRC filestore DST" << std::endl; + exit(0); +} + +int main(int argc, const char **argv) +{ + vector args; + argv_to_vec(argc, argv, args); + env_to_vec(args); + + global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, 0); + common_init_finish(g_ceph_context); + + // args + if (args.size() != 4) + usage(); + + ObjectStore *src = 0, *dst = 0; + + if (strcmp(args[0], "filestore") == 0) + src = new FileStore(args[1], NULL); + else usage(); + + if (strcmp(args[2], "filestore") == 0) + dst = new FileStore(args[3], NULL); + else usage(); + + return dupstore(src, dst); +} diff --git a/src/tools/mon_store_converter.cc b/src/tools/mon_store_converter.cc new file mode 100644 index 000000000000..1c0d3af98e2b --- /dev/null +++ b/src/tools/mon_store_converter.cc @@ -0,0 +1,336 @@ +// -*- 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) 2012 Inktank, Inc. +* +* 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 +#include + +#include "include/types.h" +#include "include/buffer.h" +#include "common/ceph_argparse.h" +#include "global/global_init.h" +#include "common/debug.h" +#include "common/config.h" + +#include "mon/MonitorDBStore.h" +#include "mon/MonitorStore.h" + +using namespace std; + +class MonitorStoreConverter { + + boost::scoped_ptr db; + boost::scoped_ptr store; + + set gvs; + version_t highest_last_pn; + version_t highest_accepted_pn; + + static const int PAXOS_MAX_VERSIONS = 50; + string MONITOR_NAME; + + public: + MonitorStoreConverter(string &store_path, string &db_store_path) + : db(0), store(0), + highest_last_pn(0), highest_accepted_pn(0), + MONITOR_NAME("monitor") + { + MonitorStore *store_ptr = new MonitorStore(store_path); + assert(!store_ptr->mount()); + store.reset(store_ptr); + + MonitorDBStore *db_ptr = new MonitorDBStore(db_store_path); + db.reset(db_ptr); + } + + int convert() { + if (db->open(std::cerr) >= 0) { + std::cerr << "store already exists" << std::endl; + return EEXIST; + } + assert(!db->create_and_open(std::cerr)); + if (db->exists("mon_convert", "on_going")) { + std::cout << __func__ << " found a mon store in mid-convertion; abort!" + << std::endl; + return EEXIST; + } + _mark_convert_start(); + _convert_monitor(); + _convert_machines(); + _mark_convert_finish(); + + std::cout << __func__ << " finished conversion" << std::endl; + + return 0; + } + + bool match() { + return true; + } + + private: + + set _get_machines_names() { + set names; + names.insert("auth"); + names.insert("logm"); + names.insert("mdsmap"); + names.insert("monmap"); + names.insert("osdmap"); + names.insert("pgmap"); + + return names; + } + + void _mark_convert_start() { + MonitorDBStore::Transaction tx; + tx.put("mon_convert", "on_going", 1); + db->apply_transaction(tx); + } + + void _mark_convert_finish() { + MonitorDBStore::Transaction tx; + tx.erase("mon_convert", "on_going"); + db->apply_transaction(tx); + } + + void _convert_monitor() { + + assert(store->exists_bl_ss("magic")); + assert(store->exists_bl_ss("keyring")); + assert(store->exists_bl_ss("feature_set")); + assert(store->exists_bl_ss("election_epoch")); + + MonitorDBStore::Transaction tx; + + if (store->exists_bl_ss("joined")) { + version_t joined = store->get_int("joined"); + tx.put(MONITOR_NAME, "joined", joined); + } + + vector keys; + keys.push_back("magic"); + keys.push_back("feature_set"); + keys.push_back("election_epoch"); + keys.push_back("cluster_uuid"); + + vector::iterator it; + for (it = keys.begin(); it != keys.end(); ++it) { + if (!store->exists_bl_ss((*it).c_str())) + continue; + + bufferlist bl; + int r = store->get_bl_ss(bl, (*it).c_str(), 0); + assert(r > 0); + tx.put(MONITOR_NAME, *it, bl); + } + + assert(!tx.empty()); + db->apply_transaction(tx); + } + + void _convert_machines(string machine) { + std::cout << __func__ << " " << machine << std::endl; + + version_t first_committed = + store->get_int(machine.c_str(), "first_committed"); + version_t last_committed = + store->get_int(machine.c_str(), "last_committed"); + + version_t accepted_pn = store->get_int(machine.c_str(), "accepted_pn"); + version_t last_pn = store->get_int(machine.c_str(), "last_pn"); + + if (accepted_pn > highest_accepted_pn) + highest_accepted_pn = accepted_pn; + if (last_pn > highest_last_pn) + highest_last_pn = last_pn; + + string machine_gv(machine); + machine_gv.append("_gv"); + bool has_gv = true; + + if (!store->exists_bl_ss(machine_gv.c_str())) { + std::cerr << __func__ << " " << machine + << " no gv dir '" << machine_gv << "'" << std::endl; + has_gv = false; + } + + for (version_t ver = first_committed; ver <= last_committed; ver++) { + if (!store->exists_bl_sn(machine.c_str(), ver)) { + std::cerr << __func__ << " " << machine + << " ver " << ver << " dne" << std::endl; + continue; + } + + bufferlist bl; + int r = store->get_bl_sn(bl, machine.c_str(), ver); + assert(r >= 0); + std::cout << __func__ << " " << machine + << " ver " << ver << " bl " << bl.length() << std::endl; + + MonitorDBStore::Transaction tx; + tx.put(machine, ver, bl); + tx.put(machine, "last_committed", ver); + + if (has_gv && store->exists_bl_sn(machine_gv.c_str(), ver)) { + stringstream s; + s << ver; + string ver_str = s.str(); + + version_t gv = store->get_int(machine_gv.c_str(), ver_str.c_str()); + std::cerr << __func__ << " " << machine + << " ver " << ver << " -> " << gv << std::endl; + + if (gvs.count(gv) == 0) { + gvs.insert(gv); + } else { + std::cerr << __func__ << " " << machine + << " gv " << gv << " already exists" + << std::endl; + } + + bufferlist tx_bl; + tx.encode(tx_bl); + tx.put("paxos", gv, tx_bl); + } + db->apply_transaction(tx); + } + + version_t lc = db->get(machine, "last_committed"); + assert(lc == last_committed); + + MonitorDBStore::Transaction tx; + tx.put(machine, "first_committed", first_committed); + tx.put(machine, "last_committed", last_committed); + + if (store->exists_bl_ss(machine.c_str(), "latest")) { + bufferlist latest_bl_raw; + int r = store->get_bl_ss(latest_bl_raw, machine.c_str(), "latest"); + assert(r >= 0); + if (!latest_bl_raw.length()) { + std::cerr << __func__ << " machine " << machine + << " skip latest with size 0" << std::endl; + goto out; + } + + tx.put(machine, "latest", latest_bl_raw); + + bufferlist::iterator lbl_it = latest_bl_raw.begin(); + bufferlist latest_bl; + version_t latest_ver; + ::decode(latest_ver, lbl_it); + ::decode(latest_bl, lbl_it); + + std::cout << __func__ << " machine " << machine + << " latest ver " << latest_ver << std::endl; + + tx.put(machine, "full_latest", latest_ver); + stringstream os; + os << "full_" << latest_ver; + tx.put(machine, os.str(), latest_bl); + } + out: + db->apply_transaction(tx); + } + + void _convert_paxos() { + assert(!gvs.empty()); + + set::reverse_iterator rit = gvs.rbegin(); + version_t highest_gv = *rit; + version_t last_gv = highest_gv; + + int n = 0; + for (; (rit != gvs.rend()) && (n < PAXOS_MAX_VERSIONS); ++rit, ++n) { + + version_t gv = *rit; + + if (last_gv == gv) + continue; + + if ((last_gv - gv) > 1) { + // we are done; we found a gap and we are only interested in keeping + // contiguous paxos versions. + break; + } + last_gv = gv; + } + + // erase all paxos versions between [first, last_gv[, with first being the + // first gv in the map. + MonitorDBStore::Transaction tx; + set::iterator it = gvs.begin(); + std::cout << __func__ << " first gv " << (*it) + << " last gv " << last_gv << std::endl; + for (; it != gvs.end() && (*it < last_gv); ++it) { + tx.erase("paxos", *it); + } + tx.put("paxos", "first_committed", last_gv); + tx.put("paxos", "last_committed", highest_gv); + tx.put("paxos", "accepted_pn", highest_accepted_pn); + tx.put("paxos", "last_pn", highest_last_pn); + db->apply_transaction(tx); + } + + void _convert_machines() { + + set machine_names = _get_machines_names(); + set::iterator it = machine_names.begin(); + + std::cout << __func__ << std::endl; + + for (; it != machine_names.end(); ++it) { + _convert_machines(*it); + } + + _convert_paxos(); + } +}; + + +void usage(const char *pname) +{ + std::cerr << "Usage: " << pname << " \n" + << std::endl; +} + +int main(int argc, const char *argv[]) +{ + vector def_args; + vector args; + const char *our_name = argv[0]; + argv_to_vec(argc, argv, args); + + global_init(&def_args, args, + CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); + common_init_finish(g_ceph_context); + g_ceph_context->_conf->apply_changes(NULL); + + if (args.empty()) { + usage(our_name); + return 1; + } + string store(args[0]); + string new_store(store); + MonitorStoreConverter converter(store, new_store); + assert(!converter.convert()); + assert(converter.match()); + + std::cout << "store successfully converted to new format" << std::endl; + + return 0; +} diff --git a/src/tools/monmaptool.cc b/src/tools/monmaptool.cc new file mode 100644 index 000000000000..57843aa350d0 --- /dev/null +++ b/src/tools/monmaptool.cc @@ -0,0 +1,208 @@ +// -*- 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 + * + * 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 +using namespace std; + +#include "common/config.h" +#include "common/ceph_argparse.h" +#include "global/global_init.h" +#include "mon/MonMap.h" +#include "include/str_list.h" + +void usage() +{ + cout << " usage: [--print] [--create [--clobber][--fsid uuid]] [--generate] [--set-initial-members] [--add name 1.2.3.4:567] [--rm name] " << std::endl; + exit(1); +} + +int main(int argc, const char **argv) +{ + vector args; + argv_to_vec(argc, argv, args); + + const char *me = argv[0]; + + std::string fn; + bool print = false; + bool create = false; + bool clobber = false; + bool modified = false; + bool generate = false; + bool filter = false; + map add; + list rm; + + global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); + common_init_finish(g_ceph_context); + std::string val; + 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(); + } else if (ceph_argparse_flag(args, i, "-p", "--print", (char*)NULL)) { + print = true; + } else if (ceph_argparse_flag(args, i, "--create", (char*)NULL)) { + create = true; + } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) { + clobber = true; + } else if (ceph_argparse_flag(args, i, "--generate", (char*)NULL)) { + generate = true; + } else if (ceph_argparse_flag(args, i, "--set-initial-members", (char*)NULL)) { + filter = true; + } else if (ceph_argparse_flag(args, i, "--add", (char*)NULL)) { + string name = *i; + i = args.erase(i); + if (i == args.end()) + usage(); + entity_addr_t addr; + if (!addr.parse(*i)) { + cerr << me << ": invalid ip:port '" << *i << "'" << std::endl; + return -1; + } + if (addr.get_port() == 0) + addr.set_port(CEPH_MON_PORT); + add[name] = addr; + modified = true; + i = args.erase(i); + } else if (ceph_argparse_witharg(args, i, &val, "--rm", (char*)NULL)) { + rm.push_back(val); + modified = true; + } else { + ++i; + } + } + if (args.empty()) { + cerr << me << ": must specify monmap filename" << std::endl; + usage(); + } + else if (args.size() > 1) { + cerr << me << ": too many arguments" << std::endl; + usage(); + } + fn = args[0]; + + MonMap monmap; + + cout << me << ": monmap file " << fn << std::endl; + + int r = 0; + if (!(create && clobber)) { + try { + r = monmap.read(fn.c_str()); + } catch (...) { + cerr << me << ": unable to read monmap file" << std::endl; + return -1; + } + } + + char buf[80]; + if (!create && r < 0) { + cerr << me << ": couldn't open " << fn << ": " << strerror_r(-r, buf, sizeof(buf)) << std::endl; + return -1; + } + else if (create && !clobber && r == 0) { + cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl; + return -1; + } + + if (create) { + monmap.epoch = 0; + monmap.created = ceph_clock_now(g_ceph_context); + monmap.last_changed = monmap.created; + srand(getpid() + time(0)); + if (g_conf->fsid.is_zero()) { + monmap.generate_fsid(); + cout << me << ": generated fsid " << monmap.fsid << std::endl; + } + modified = true; + } + + if (generate) { + int r = monmap.build_initial(g_ceph_context, cerr); + if (r < 0) + return r; + } + + if (filter) { + // apply initial members + list initial_members; + get_str_list(g_conf->mon_initial_members, initial_members); + if (!initial_members.empty()) { + cout << "initial_members " << initial_members << ", filtering seed monmap" << std::endl; + set removed; + monmap.set_initial_members(g_ceph_context, initial_members, + string(), entity_addr_t(), + &removed); + cout << "removed " << removed << std::endl; + } + modified = true; + } + + if (!g_conf->fsid.is_zero()) { + monmap.fsid = g_conf->fsid; + cout << me << ": set fsid to " << monmap.fsid << std::endl; + modified = true; + } + + for (map::iterator p = add.begin(); p != add.end(); ++p) { + if (monmap.contains(p->first)) { + cerr << me << ": map already contains mon." << p->first << std::endl; + usage(); + } + if (monmap.contains(p->second)) { + cerr << me << ": map already contains " << p->second << std::endl; + usage(); + } + monmap.add(p->first, p->second); + } + for (list::iterator p = rm.begin(); p != rm.end(); ++p) { + cout << me << ": removing " << *p << std::endl; + if (!monmap.contains(*p)) { + cerr << me << ": map does not contain " << *p << std::endl; + usage(); + } + monmap.remove(*p); + } + + if (!print && !modified) + usage(); + + if (print) + monmap.print(cout); + + if (modified) { + // write it out + cout << me << ": writing epoch " << monmap.epoch + << " to " << fn + << " (" << monmap.size() << " monitors)" + << std::endl; + int r = monmap.write(fn.c_str()); + if (r < 0) { + cerr << "monmaptool: error writing to '" << fn << "': " << strerror_r(-r, buf, sizeof(buf)) << std::endl; + return 1; + } + } + + + return 0; +} diff --git a/src/tools/osdmaptool.cc b/src/tools/osdmaptool.cc new file mode 100644 index 000000000000..2e55026076c3 --- /dev/null +++ b/src/tools/osdmaptool.cc @@ -0,0 +1,343 @@ +// -*- 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 + * + * 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 +using namespace std; + +#include "common/config.h" + +#include "common/errno.h" +#include "osd/OSDMap.h" +#include "mon/MonMap.h" +#include "common/ceph_argparse.h" +#include "global/global_init.h" + +void usage() +{ + cout << " usage: [--print] [--createsimple [--clobber] [--pg_bits ]] " << std::endl; + cout << " --export-crush write osdmap's crush map to " << std::endl; + cout << " --import-crush replace osdmap's crush map with " << std::endl; + cout << " --test-map-pg map a pgid to osds" << std::endl; + cout << " --test-map-object [--pool ] map an object to osds" + << std::endl; + exit(1); +} + +int main(int argc, const char **argv) +{ + vector args; + argv_to_vec(argc, argv, args); + env_to_vec(args); + + global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); + common_init_finish(g_ceph_context); + + const char *me = argv[0]; + + std::string fn; + bool print = false; + bool print_json = false; + bool tree = false; + bool createsimple = false; + bool create_from_conf = false; + int num_osd = 0; + int pg_bits = g_conf->osd_pg_bits; + int pgp_bits = g_conf->osd_pgp_bits; + bool clobber = false; + bool modified = false; + std::string export_crush, import_crush, test_map_pg, test_map_object; + bool test_crush = false; + int range_first = -1; + int range_last = -1; + int pool = 0; + + std::string val; + std::ostringstream err; + 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(); + } else if (ceph_argparse_flag(args, i, "-p", "--print", (char*)NULL)) { + print = true; + } else if (ceph_argparse_flag(args, i, "--dump-json", (char*)NULL)) { + print_json = true; + } else if (ceph_argparse_flag(args, i, "--tree", (char*)NULL)) { + tree = true; + } else if (ceph_argparse_withint(args, i, &num_osd, &err, "--createsimple", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + createsimple = true; + } else if (ceph_argparse_flag(args, i, "--create-from-conf", (char*)NULL)) { + create_from_conf = true; + } else if (ceph_argparse_flag(args, i, "--clobber", (char*)NULL)) { + clobber = true; + } else if (ceph_argparse_withint(args, i, &pg_bits, &err, "--pg_bits", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + } else if (ceph_argparse_withint(args, i, &pgp_bits, &err, "--pgp_bits", (char*)NULL)) { + if (!err.str().empty()) { + cerr << err.str() << std::endl; + exit(EXIT_FAILURE); + } + } else if (ceph_argparse_witharg(args, i, &val, "--export_crush", (char*)NULL)) { + export_crush = val; + } else if (ceph_argparse_witharg(args, i, &val, "--import_crush", (char*)NULL)) { + import_crush = val; + } else if (ceph_argparse_witharg(args, i, &val, "--test_map_pg", (char*)NULL)) { + test_map_pg = val; + } else if (ceph_argparse_witharg(args, i, &val, "--test_map_object", (char*)NULL)) { + test_map_object = val; + } else if (ceph_argparse_flag(args, i, "--test_crush", (char*)NULL)) { + test_crush = true; + } else if (ceph_argparse_withint(args, i, &range_first, &err, "--range_first", (char*)NULL)) { + } else if (ceph_argparse_withint(args, i, &range_last, &err, "--range_last", (char*)NULL)) { + } else if (ceph_argparse_withint(args, i, &pool, &err, "--pool", (char*)NULL)) { + } else { + ++i; + } + } + if (args.empty()) { + cerr << me << ": must specify osdmap filename" << std::endl; + usage(); + } + else if (args.size() > 1) { + cerr << me << ": too many arguments" << std::endl; + usage(); + } + fn = args[0]; + + if (range_first >= 0 && range_last >= 0) { + set maps; + OSDMap *prev = NULL; + for (int i=range_first; i <= range_last; i++) { + ostringstream f; + f << fn << "/" << i; + bufferlist bl; + string error, s = f.str(); + int r = bl.read_file(s.c_str(), &error); + if (r < 0) { + cerr << "unable to read " << s << ": " << cpp_strerror(r) << std::endl; + exit(1); + } + cout << s << " got " << bl.length() << " bytes" << std::endl; + OSDMap *o = new OSDMap; + o->decode(bl); + maps.insert(o); + if (prev) + OSDMap::dedup(prev, o); + prev = o; + } + exit(0); + } + + OSDMap osdmap; + bufferlist bl; + + cout << me << ": osdmap file '" << fn << "'" << std::endl; + + int r = 0; + struct stat st; + if (!createsimple && !create_from_conf && !clobber) { + std::string error; + r = bl.read_file(fn.c_str(), &error); + if (r == 0) { + try { + osdmap.decode(bl); + } + catch (const buffer::error &e) { + cerr << me << ": error decoding osdmap '" << fn << "'" << std::endl; + return -1; + } + } + else { + cerr << me << ": couldn't open " << fn << ": " << error << std::endl; + return -1; + } + } + else if ((createsimple || create_from_conf) && !clobber && ::stat(fn.c_str(), &st) == 0) { + cerr << me << ": " << fn << " exists, --clobber to overwrite" << std::endl; + return -1; + } + + if (createsimple) { + if (num_osd < 1) { + cerr << me << ": osd count must be > 0" << std::endl; + exit(1); + } + uuid_d fsid; + memset(&fsid, 0, sizeof(uuid_d)); + osdmap.build_simple(g_ceph_context, 0, fsid, num_osd, pg_bits, pgp_bits); + modified = true; + } + if (create_from_conf) { + uuid_d fsid; + memset(&fsid, 0, sizeof(uuid_d)); + int r = osdmap.build_simple_from_conf(g_ceph_context, 0, fsid, pg_bits, pgp_bits); + if (r < 0) + return -1; + modified = true; + } + + if (!import_crush.empty()) { + bufferlist cbl; + std::string error; + r = cbl.read_file(import_crush.c_str(), &error); + if (r) { + cerr << me << ": error reading crush map from " << import_crush + << ": " << error << std::endl; + exit(1); + } + + // validate + CrushWrapper cw; + bufferlist::iterator p = cbl.begin(); + cw.decode(p); + + if (cw.get_max_devices() > osdmap.get_max_osd()) { + cerr << me << ": crushmap max_devices " << cw.get_max_devices() + << " > osdmap max_osd " << osdmap.get_max_osd() << std::endl; + exit(1); + } + + // apply + OSDMap::Incremental inc; + inc.fsid = osdmap.get_fsid(); + inc.epoch = osdmap.get_epoch()+1; + inc.crush = cbl; + osdmap.apply_incremental(inc); + cout << me << ": imported " << cbl.length() << " byte crush map from " << import_crush << std::endl; + modified = true; + } + + if (!export_crush.empty()) { + bufferlist cbl; + osdmap.crush->encode(cbl); + r = cbl.write_file(export_crush.c_str()); + if (r < 0) { + cerr << me << ": error writing crush map to " << import_crush << std::endl; + exit(1); + } + cout << me << ": exported crush map to " << export_crush << std::endl; + } + + if (!test_map_object.empty()) { + object_t oid(test_map_object); + if (!osdmap.have_pg_pool(pool)) { + cerr << "There is no pool " << pool << std::endl; + exit(1); + } + object_locator_t loc(pool); + pg_t raw_pgid = osdmap.object_locator_to_pg(oid, loc); + pg_t pgid = osdmap.raw_pg_to_pg(raw_pgid); + + vector acting; + osdmap.pg_to_acting_osds(pgid, acting); + cout << " object '" << oid + << "' -> " << pgid + << " -> " << acting + << std::endl; + } + if (!test_map_pg.empty()) { + pg_t pgid; + if (!pgid.parse(test_map_pg.c_str())) { + cerr << me << ": failed to parse pg '" << test_map_pg + << "', r = " << r << std::endl; + usage(); + } + cout << " parsed '" << test_map_pg << "' -> " << pgid << std::endl; + + vector raw, up, acting; + osdmap.pg_to_osds(pgid, raw); + osdmap.pg_to_up_acting_osds(pgid, up, acting); + cout << pgid << " raw " << raw << " up " << up << " acting " << acting << std::endl; + } + if (test_crush) { + int pass = 0; + while (1) { + cout << "pass " << ++pass << std::endl; + + hash_map > m; + for (map::const_iterator p = osdmap.get_pools().begin(); + p != osdmap.get_pools().end(); + ++p) { + const pg_pool_t *pool = osdmap.get_pg_pool(p->first); + for (ps_t ps = 0; ps < pool->get_pg_num(); ps++) { + pg_t pgid(ps, p->first, -1); + for (int i=0; i<100; i++) { + cout << pgid << " attempt " << i << std::endl; + + vector r; + osdmap.pg_to_acting_osds(pgid, r); + //cout << pgid << " " << r << std::endl; + if (m.count(pgid)) { + if (m[pgid] != r) { + cout << pgid << " had " << m[pgid] << " now " << r << std::endl; + assert(0); + } + } else + m[pgid] = r; + } + } + } + } + } + + if (!print && !print_json && !tree && !modified && + export_crush.empty() && import_crush.empty() && + test_map_pg.empty() && test_map_object.empty()) { + cerr << me << ": no action specified?" << std::endl; + usage(); + } + + if (modified) + osdmap.inc_epoch(); + + if (print) + osdmap.print(cout); + if (print_json) + osdmap.dump_json(cout); + if (tree) + osdmap.print_tree(&cout, NULL); + + if (modified) { + bl.clear(); + osdmap.encode(bl); + + // write it out + cout << me << ": writing epoch " << osdmap.get_epoch() + << " to " << fn + << std::endl; + int r = bl.write_file(fn.c_str()); + if (r) { + cerr << "osdmaptool: error writing to '" << fn << "': " + << cpp_strerror(r) << std::endl; + return 1; + } + } + + + return 0; +} diff --git a/src/tools/psim.cc b/src/tools/psim.cc new file mode 100644 index 000000000000..c1adc7580fb6 --- /dev/null +++ b/src/tools/psim.cc @@ -0,0 +1,96 @@ + +#include + +#include "crush/CrushWrapper.h" +#include "osd/OSDMap.h" +#include "common/config.h" +#include "include/buffer.h" + +int main(int argc, char **argv) +{ + /* + * you need to create a suitable osdmap first. e.g., for 40 osds, + * $ ./osdmaptool --createsimple 40 --clobber .ceph_osdmap + */ + bufferlist bl; + std::string error; + if (bl.read_file(".ceph_osdmap", &error)) { + cout << argv[0] << ": error reading .ceph_osdmap: " << error << std::endl; + return 1; + } + OSDMap osdmap; + osdmap.decode(bl); + + int n = osdmap.get_max_osd(); + int count[n]; + for (int i=0; i osds; + pg_t pgid = pg_t(l.ol_pgid); + //pgid.u.ps = f * 4 + b; + osdmap.pg_to_osds(pgid, osds); + size[osds.size()]++; +#if 0 + if (0) { + hash H; + int x = H(oid); + x = ceph_stable_mod(x, 1023, 1023); + int s = crush_hash32(x) % 15; + //cout << "ceph_psim: x = " << x << " s = " << s << std::endl; + //osds[0] = s; + } +#endif + //osds[0] = crush_hash32(f) % n; + //cout << "oid " << oid << " pgid " << pgid << " on " << osds << std::endl; + for (unsigned i=0; iget_pg_num() / (double)n; + double edev = sqrt(pgavg) * (double)avg / pgavg; + cout << " avg " << avg + << " stddev " << dev + << " (expected " << edev << ")" + << " (indep object placement would be " << sqrt(avg) << ")" << std::endl; + + for (int i=0; i<4; i++) { + cout << "size" << i << "\t" << size[i] << std::endl; + } + + return 0; +} diff --git a/src/tools/radosacl.cc b/src/tools/radosacl.cc new file mode 100644 index 000000000000..d2f7ca5c488f --- /dev/null +++ b/src/tools/radosacl.cc @@ -0,0 +1,202 @@ +// -*- 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 + * + * 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/types.h" +#include "include/rados/librados.hpp" +using namespace librados; + +#include + +#include +#include +#include + +void buf_to_hex(const unsigned char *buf, int len, char *str) +{ + str[0] = '\0'; + for (int i = 0; i < len; i++) { + sprintf(&str[i*2], "%02x", (int)buf[i]); + } +} + + +#define ID_SIZE 8 + +#define ACL_RD 0x1 +#define ACL_WR 0x2 + +struct ACLID { + char id[ID_SIZE + 1]; + + void encode(bufferlist& bl) const { + bl.append((const char *)id, ID_SIZE); + } + void decode(bufferlist::iterator& iter) { + iter.copy(ID_SIZE, (char *)id); + } +}; +WRITE_CLASS_ENCODER(ACLID) + +typedef __u32 ACLFlags; + + +inline bool operator<(const ACLID& l, const ACLID& r) +{ + return (memcmp(&l, &r, ID_SIZE) > 0); +} + +struct ACLPair { + ACLID id; + ACLFlags flags; +}; + +class ObjectACLs { + map acls_map; + +public: + + void encode(bufferlist& bl) const { + ::encode(acls_map, bl); + } + void decode(bufferlist::iterator& bl) { + ::decode(acls_map, bl); + } + + int read_acl(ACLID& id, ACLFlags *flags); + void set_acl(ACLID& id, ACLFlags flags); +}; +WRITE_CLASS_ENCODER(ObjectACLs) + +int ObjectACLs::read_acl(ACLID& id, ACLFlags *flags) +{ + if (!flags) + return -EINVAL; + + map::iterator iter = acls_map.find(id); + + if (iter == acls_map.end()) + return -ENOENT; + + *flags = iter->second; + + return 0; +} + +void ObjectACLs::set_acl(ACLID& id, ACLFlags flags) +{ + acls_map[id] = flags; +} + + + +class ACLEntity +{ + string name; + map groups; +}; + +typedef map tACLIDEntityMap; + +static map users; +static map groups; + +void get_user(ACLID& aclid, ACLEntity *entity) +{ + //users.find(aclid); +} + + + + + +int main(int argc, const char **argv) +{ + Rados rados; + if (rados.init(NULL) < 0) { + cerr << "couldn't initialize rados!" << std::endl; + exit(1); + } + if (rados.conf_read_file(NULL)) { + cerr << "couldn't read Ceph configuration file!" << std::endl; + exit(1); + } + if (rados.connect() < 0) { + cerr << "couldn't connect to cluster!" << std::endl; + exit(1); + } + + time_t tm; + bufferlist bl, bl2; + char buf[128]; + + time(&tm); + snprintf(buf, 128, "%s", ctime(&tm)); + bl.append(buf, strlen(buf)); + + const char *oid = "bar"; + + IoCtx io_ctx; + int r = rados.ioctx_create("data", io_ctx); + cout << "open io_ctx result = " << r << " pool = " << io_ctx.get_pool_name() << std::endl; + + ACLID id; + + snprintf(id.id, ID_SIZE + 1, "%.16x", 0x1234); + cout << "id=" << id.id << std::endl; + + r = io_ctx.exec(oid, "acl", "get", bl, bl2); + cout << "exec returned " << r << " len=" << bl2.length() << std::endl; + ObjectACLs oa; + if (r >= 0) { + bufferlist::iterator iter = bl2.begin(); + oa.decode(iter); + } + + oa.set_acl(id, ACL_RD); + bl.clear(); + oa.encode(bl); + r = io_ctx.exec(oid, "acl", "set", bl, bl2); + + const unsigned char *md5 = (const unsigned char *)bl2.c_str(); + char md5_str[bl2.length()*2 + 1]; + buf_to_hex(md5, bl2.length(), md5_str); + cout << "md5 result=" << md5_str << std::endl; + + int size = io_ctx.read(oid, bl2, 128, 0); + cout << "read result=" << bl2.c_str() << std::endl; + cout << "size=" << size << std::endl; + +#if 0 + Rados::ListCtx ctx; + int entries; + do { + list vec; + r = rados.list(io_ctx, 2, vec, ctx); + entries = vec.size(); + cout << "list result=" << r << " entries=" << entries << std::endl; + list::iterator iter; + for (iter = vec.begin(); iter != vec.end(); ++iter) { + cout << *iter << std::endl; + } + } while (entries); +#endif +#if 0 + r = rados.remove(io_ctx, oid); + cout << "remove result=" << r << std::endl; + rados.close_io_ctx(io_ctx); +#endif + + return 0; +} + diff --git a/src/tools/scratchtool.c b/src/tools/scratchtool.c new file mode 100644 index 000000000000..22cf2bdf531d --- /dev/null +++ b/src/tools/scratchtool.c @@ -0,0 +1,312 @@ +// -*- 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 + * + * 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/rados/librados.h" + +#include +#include +#include +#include +#include +#include + +static int do_rados_setxattr(rados_ioctx_t io_ctx, const char *oid, + const char *key, const char *val) +{ + int ret = rados_setxattr(io_ctx, oid, key, val, strlen(val) + 1); + if (ret < 0) { + printf("rados_setxattr failed with error %d\n", ret); + return 1; + } + printf("rados_setxattr %s=%s\n", key, val); + return 0; +} + +static int do_rados_getxattr(rados_ioctx_t io_ctx, const char *oid, + const char *key, const char *expected) +{ + size_t blen = strlen(expected) + 1; + char buf[blen]; + memset(buf, 0, sizeof(buf)); + int r = rados_getxattr(io_ctx, oid, key, buf, blen); + if (r < 0) { + printf("rados_getxattr(%s) failed with error %d\n", key, r); + return 1; + } + if (strcmp(buf, expected) != 0) { + printf("rados_getxattr(%s) got wrong result! " + "expected: '%s'. got '%s'\n", key, expected, buf); + return 1; + } + printf("rados_getxattr %s=%s\n", key, buf); + return 0; +} + +static int do_rados_getxattrs(rados_ioctx_t io_ctx, const char *oid, + const char **exkeys, const char **exvals) +{ + rados_xattrs_iter_t iter; + int nval = 0, i, nfound = 0, ret = 0; + + for (i = 0; exvals[i]; ++i) { + ++nval; + } + ret = rados_getxattrs(io_ctx, oid, &iter); + if (ret) { + printf("rados_getxattrs(%s) failed with error %d\n", oid, ret); + return 1; + } + while (1) { + size_t len; + const char *key, *val; + ret = rados_getxattrs_next(iter, &key, &val, &len); + if (ret) { + printf("rados_getxattrs(%s): rados_getxattrs_next " + "returned error %d\n", oid, ret); + return 1; + } + if (!key) + break; + for (i = 0; i < nval; ++i) { + if (strcmp(exkeys[i], key)) + continue; + if ((len == strlen(exvals[i]) + 1) && (!strcmp(exvals[i], val))) { + nfound++; + break; + } + printf("rados_getxattrs(%s): got key %s, but the " + "value was %s rather than %s.\n", + oid, key, val, exvals[i]); + return 1; + } + } + if (nfound != nval) { + printf("rados_getxattrs(%s): only found %d extended attributes. " + "Expected %d\n", oid, nfound, nval); + return 1; + } + rados_getxattrs_end(iter); + printf("rados_getxattrs(%s)\n", oid); + return 0; +} + +static int testrados(void) +{ + char tmp[32]; + int i, r; + int ret = 1; //set 1 as error case + rados_t cl; + + if (rados_create(&cl, NULL) < 0) { + printf("error initializing\n"); + return 1; + } + + if (rados_conf_read_file(cl, NULL)) { + printf("error reading configuration file\n"); + goto out_err; + } + + // Try to set a configuration option that doesn't exist. + // This should fail. + if (!rados_conf_set(cl, "config option that doesn't exist", + "some random value")) { + printf("error: succeeded in setting nonexistent config option\n"); + goto out_err; + } + + if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) { + printf("error: failed to read log_to_stderr from config\n"); + goto out_err; + } + + // Can we change it? + if (rados_conf_set(cl, "log to stderr", "true")) { + printf("error: error setting log_to_stderr\n"); + goto out_err; + } + if (rados_conf_get(cl, "log to stderr", tmp, sizeof(tmp))) { + printf("error: failed to read log_to_stderr from config\n"); + goto out_err; + } + if (strcmp(tmp, "true")) { + printf("error: new setting for log_to_stderr failed to take effect.\n"); + goto out_err; + } + + if (rados_connect(cl)) { + printf("error connecting\n"); + goto out_err; + } + if (rados_connect(cl) == 0) { + printf("second connect attempt didn't return an error\n"); + goto out_err; + } + + /* create an io_ctx */ + r = rados_pool_create(cl, "foo"); + printf("rados_pool_create = %d\n", r); + + rados_ioctx_t io_ctx; + r = rados_ioctx_create(cl, "foo", &io_ctx); + printf("rados_ioctx_create = %d, io_ctx = %p\n", r, io_ctx); + + /* list all pools */ + { + int buf_sz = rados_pool_list(cl, NULL, 0); + printf("need buffer size of %d\n", buf_sz); + char buf[buf_sz]; + int r = rados_pool_list(cl, buf, buf_sz); + if (r != buf_sz) { + printf("buffer size mismatch: got %d the first time, but %d " + "the second.\n", buf_sz, r); + goto out_err; + } + const char *b = buf; + printf("begin pools.\n"); + while (1) { + if (b[0] == '\0') + break; + printf(" pool: '%s'\n", b); + b += strlen(b) + 1; + }; + printf("end pools.\n"); + } + + + /* stat */ + struct rados_pool_stat_t st; + r = rados_ioctx_pool_stat(io_ctx, &st); + printf("rados_ioctx_pool_stat = %d, %lld KB, %lld objects\n", r, (long long)st.num_kb, (long long)st.num_objects); + + /* snapshots */ + r = rados_ioctx_snap_create(io_ctx, "snap1"); + printf("rados_ioctx_snap_create snap1 = %d\n", r); + rados_snap_t snaps[10]; + r = rados_ioctx_snap_list(io_ctx, snaps, 10); + for (i=0; i + * + * 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/types.h" +#include "include/rados/librados.hpp" + +using namespace librados; + +#include + +#include +#include +#include + +void buf_to_hex(const unsigned char *buf, int len, char *str) +{ + str[0] = '\0'; + for (int i = 0; i < len; i++) { + sprintf(&str[i*2], "%02x", (int)buf[i]); + } +} + +class C_Watch : public WatchCtx { +public: + C_Watch() {} + void notify(uint8_t opcode, uint64_t ver, bufferlist& bl) { + cout << "C_Watch::notify() opcode=" << (int)opcode << " ver=" << ver << std::endl; + } +}; + +void testradospp_milestone(void) +{ + cout << "*** press enter to continue ***" << std::endl; + getchar(); +} + +int main(int argc, const char **argv) +{ + Rados rados; + if (rados.init(NULL) < 0) { + cerr << "couldn't initialize rados!" << std::endl; + exit(1); + } + + if (rados.conf_read_file(NULL)) { + cerr << "couldn't read configuration file." << std::endl; + exit(1); + } + rados.conf_parse_argv(argc, argv); + + if (!rados.conf_set("config option that doesn't exist", + "some random value")) { + printf("error: succeeded in setting nonexistent config option\n"); + exit(1); + } + if (rados.conf_set("log to stderr", "true")) { + printf("error: error setting log_to_stderr\n"); + exit(1); + } + std::string tmp; + if (rados.conf_get("log to stderr", tmp)) { + printf("error: failed to read log_to_stderr from config\n"); + exit(1); + } + if (tmp != "true") { + printf("error: new setting for log_to_stderr failed to take effect.\n"); + exit(1); + } + + if (rados.connect()) { + printf("error connecting\n"); + exit(1); + } + + cout << "rados_initialize completed" << std::endl; + testradospp_milestone(); + + time_t tm; + bufferlist bl, bl2, blf; + char buf[128]; + + time(&tm); + snprintf(buf, 128, "%s", ctime(&tm)); + bl.append(buf, strlen(buf)); + blf.append(buf, 16); + + const char *oid = "bar"; + + IoCtx io_ctx; + int r = rados.ioctx_create("data", io_ctx); + cout << "ioctx_create result = " << r << std::endl; + + r = io_ctx.write(oid, bl, bl.length(), 0); + uint64_t objver = io_ctx.get_last_version(); + assert(objver > 0); + cout << "io_ctx.write returned " << r << " last_ver=" << objver << std::endl; + + uint64_t stat_size; + time_t stat_mtime; + r = io_ctx.stat(oid, &stat_size, &stat_mtime); + cout << "io_ctx.stat returned " << r << " size = " << stat_size << " mtime = " << stat_mtime << std::endl; + + r = io_ctx.stat(oid, NULL, NULL); + cout << "io_ctx.stat(does_not_exist) = " << r; + + uint64_t handle; + C_Watch wc; + r = io_ctx.watch(oid, objver, &handle, &wc); + cout << "io_ctx.watch returned " << r << std::endl; + + testradospp_milestone(); + io_ctx.set_notify_timeout(7); + bufferlist notify_bl; + r = io_ctx.notify(oid, objver, notify_bl); + cout << "io_ctx.notify returned " << r << std::endl; + testradospp_milestone(); + + r = io_ctx.notify(oid, objver, notify_bl); + cout << "io_ctx.notify returned " << r << std::endl; + testradospp_milestone(); + + r = io_ctx.unwatch(oid, handle); + cout << "io_ctx.unwatch returned " << r << std::endl; + cout << "*** press enter to continue ***" << std::endl; + testradospp_milestone(); + + r = io_ctx.notify(oid, objver, notify_bl); + cout << "io_ctx.notify returned " << r << std::endl; + cout << "*** press enter to continue ***" << std::endl; + testradospp_milestone(); + io_ctx.set_assert_version(objver); + + r = io_ctx.write(oid, bl, bl.length() - 1, 0); + cout << "io_ctx.write returned " << r << std::endl; + + r = io_ctx.write(oid, bl, bl.length() - 2, 0); + cout << "io_ctx.write returned " << r << std::endl; + r = io_ctx.write(oid, bl, bl.length() - 3, 0); + cout << "rados.write returned " << r << std::endl; + r = io_ctx.append(oid, bl, bl.length()); + cout << "rados.write returned " << r << std::endl; + r = io_ctx.write_full(oid, blf); + cout << "rados.write_full returned " << r << std::endl; + r = io_ctx.read(oid, bl, bl.length(), 0); + cout << "rados.read returned " << r << std::endl; + r = io_ctx.trunc(oid, 8); + cout << "rados.trunc returned " << r << std::endl; + r = io_ctx.read(oid, bl, bl.length(), 0); + cout << "rados.read returned " << r << std::endl; + r = io_ctx.exec(oid, "crypto", "md5", bl, bl2); + cout << "exec returned " << r << " buf size=" << bl2.length() << std::endl; + const unsigned char *md5 = (const unsigned char *)bl2.c_str(); + char md5_str[bl2.length()*2 + 1]; + buf_to_hex(md5, bl2.length(), md5_str); + cout << "md5 result=" << md5_str << std::endl; + + // test assert_version + r = io_ctx.read(oid, bl, 0, 1); + assert(r >= 0); + uint64_t v = io_ctx.get_last_version(); + cout << oid << " version is " << v << std::endl; + assert(v > 0); + io_ctx.set_assert_version(v); + r = io_ctx.read(oid, bl, 0, 1); + assert(r >= 0); + io_ctx.set_assert_version(v - 1); + r = io_ctx.read(oid, bl, 0, 1); + assert(r == -ERANGE); + io_ctx.set_assert_version(v + 1); + r = io_ctx.read(oid, bl, 0, 1); + assert(r == -EOVERFLOW); + + // test assert_src_version + const char *dest = "baz"; + r = io_ctx.read(oid, bl, 0, 1); + assert(r >= 0); + v = io_ctx.get_last_version(); + cout << oid << " version is " << v << std::endl; + io_ctx.set_assert_src_version(oid, v); + r = io_ctx.clone_range(dest, 0, oid, 0, 1); + assert(r >= 0); + io_ctx.set_assert_src_version(oid, v-1); + r = io_ctx.clone_range(dest, 0, oid, 0, 1); + assert(r == -ERANGE); + io_ctx.set_assert_src_version(oid, v+1); + r = io_ctx.clone_range(dest, 0, oid, 0, 1); + assert(r == -EOVERFLOW); + + r = io_ctx.exec(oid, "crypto", "sha1", bl, bl2); + cout << "exec returned " << r << std::endl; + const unsigned char *sha1 = (const unsigned char *)bl2.c_str(); + char sha1_str[bl2.length()*2 + 1]; + buf_to_hex(sha1, bl2.length(), sha1_str); + cout << "sha1 result=" << sha1_str << std::endl; + + r = io_ctx.exec(oid, "acl", "set", bl, bl2); + cout << "exec (set) returned " << r << std::endl; + r = io_ctx.exec(oid, "acl", "get", bl, bl2); + cout << "exec (get) returned " << r << std::endl; + if (bl2.length() > 0) { + cout << "attr=" << bl2.c_str() << std::endl; + } + + int size = io_ctx.read(oid, bl2, 128, 0); + if (size <= 0) { + cout << "failed to read oid " << oid << "." << std::endl; + exit(1); + } + if (size > 4096) { + cout << "read too many bytes from oid " << oid << "." << std::endl; + exit(1); + } + char rbuf[size + 1]; + memcpy(rbuf, bl2.c_str(), size); + rbuf[size] = '\0'; + cout << "read result='" << rbuf << "'" << std::endl; + cout << "size=" << size << std::endl; + + const char *oid2 = "jjj10.rbd"; + r = io_ctx.exec(oid2, "rbd", "snap_list", bl, bl2); + cout << "snap_list result=" << r << std::endl; + r = io_ctx.exec(oid2, "rbd", "snap_add", bl, bl2); + cout << "snap_add result=" << r << std::endl; + + if (r > 0) { + char *s = bl2.c_str(); + for (int i=0; i= 0); + { + ObjectReadOperation o; + o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val); + r = io_ctx.operate(oid, &o, &bl2); + cout << " got " << r << " wanted >= 0" << std::endl; + assert(r >= 0); + } + val.append("..."); + { + ObjectReadOperation o; + o.cmpxattr("foo", CEPH_OSD_CMPXATTR_OP_EQ, val); + r = io_ctx.operate(oid, &o, &bl2); + cout << " got " << r << " wanted ECANCELED" << std::endl; + assert(r == -ECANCELED); + } + + cout << "src_cmpxattr" << std::endl; + const char *oidb = "bar-clone"; + { + ObjectWriteOperation o; + o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_EQ, val); + io_ctx.locator_set_key(oid); + o.write_full(val); + r = io_ctx.operate(oidb, &o); + cout << " got " << r << " wanted ECANCELED" << std::endl; + assert(r == -ECANCELED); + } + { + ObjectWriteOperation o; + o.src_cmpxattr(oid, "foo", CEPH_OSD_CMPXATTR_OP_NE, val); + io_ctx.locator_set_key(oid); + o.write_full(val); + r = io_ctx.operate(oidb, &o); + cout << " got " << r << " wanted >= 0" << std::endl; + assert(r >= 0); + } + io_ctx.locator_set_key(string()); + + + cout << "iterating over objects..." << std::endl; + int num_objs = 0; + for (ObjectIterator iter = io_ctx.objects_begin(); + iter != io_ctx.objects_end(); ++iter) { + num_objs++; + cout << "'" << *iter << "'" << std::endl; + } + cout << "iterated over " << num_objs << " objects." << std::endl; + map attrset; + io_ctx.getxattrs(oid, attrset); + + map::iterator it; + for (it = attrset.begin(); it != attrset.end(); ++it) { + cout << "xattr: " << it->first << std::endl; + } + + r = io_ctx.remove(oid); + cout << "remove result=" << r << std::endl; + rados.shutdown(); + + return 0; +} +