diff options
Diffstat (limited to 'src/tools/ceph_conf.cc')
-rw-r--r-- | src/tools/ceph_conf.cc | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/src/tools/ceph_conf.cc b/src/tools/ceph_conf.cc new file mode 100644 index 000000000..1d1fc1f77 --- /dev/null +++ b/src/tools/ceph_conf.cc @@ -0,0 +1,278 @@ +// -*- 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 <iomanip> +#include <string> + +#include "common/ceph_argparse.h" +#include "global/global_init.h" +#include "mon/AuthMonitor.h" +#include "common/Formatter.h" + +using std::deque; +using std::string; +using std::unique_ptr; +using std::cerr; +using std::cout; +using std::vector; + +static void usage(std::ostream& out) +{ + // TODO: add generic_usage once cerr/derr issues are resolved + out << R"(Ceph configuration query tool + +USAGE +ceph-conf <flags> <action> + +ACTIONS + -L|--list-all-sections List all sections + -l|--list-sections <prefix> List sections with the given prefix + --filter-key <key> Filter section list to only include sections + with given key defined. + --filter-key-value <key>=<val> Filter section list to only include sections + with given key/value pair. + --lookup <key> Print a configuration setting to stdout. + Returns 0 (success) if the configuration setting is + found; 1 otherwise. + -r|--resolve-search search for the first file that exists and + can be opened in the resulted comma + delimited search list. + -D|--dump-all dump all variables. + --show-config-value <key> Print the corresponding ceph.conf value + that matches the specified key. Also searches + global defaults. + +FLAGS + --name name Set type.id + [-s <section>] Add to list of sections to search + [--format plain|json|json-pretty] + dump variables in plain text, json or pretty + json + [--pid <pid>] Override the $pid when expanding options + +If there is no action given, the action will default to --lookup. + +EXAMPLES +$ ceph-conf --name mon.0 -c /etc/ceph/ceph.conf 'mon addr' +Find out what the value of 'mon addr' is for monitor 0. + +$ ceph-conf -l mon +List sections beginning with 'mon'. + +RETURN CODE +Return code will be 0 on success; error code otherwise. +)"; +} + +static int list_sections(const std::string &prefix, + const std::list<string>& filter_key, + const std::map<string,string>& filter_key_value) +{ + std::vector <std::string> sections; + int ret = g_conf().get_all_sections(sections); + if (ret) + return 2; + for (std::vector<std::string>::const_iterator p = sections.begin(); + p != sections.end(); ++p) { + if (strncmp(prefix.c_str(), p->c_str(), prefix.size())) + continue; + + std::vector<std::string> sec; + sec.push_back(*p); + + int r = 0; + for (std::list<string>::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<string,string>::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<std::string> §ions, + const std::string &key, bool resolve_search) +{ + std::vector<std::string> my_sections{sections.begin(), sections.end()}; + for (auto& section : g_conf().get_my_sections()) { + my_sections.push_back(section); + } + 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; + ret = ceph_resolve_file_search(val, result); + if (!ret) + puts(result.c_str()); + } + else { + puts(val.c_str()); + } + return 0; + } + else { + cerr << "error looking up '" << key << "': error " << ret << std::endl; + return 2; + } +} + +static int dump_all(const string& format) +{ + if (format == "" || format == "plain") { + g_conf().show_config(std::cout); + return 0; + } else { + unique_ptr<Formatter> f(Formatter::create(format)); + if (f) { + f->open_object_section("ceph-conf"); + g_conf().show_config(f.get()); + f->close_section(); + f->flush(std::cout); + return 0; + } + cerr << "format '" << format << "' not recognized." << std::endl; + usage(cerr); + return 1; + } +} + +static void maybe_override_pid(vector<const char*>& args) +{ + for (auto i = args.begin(); i != args.end(); ++i) { + string val; + if (ceph_argparse_witharg(args, i, &val, "--pid", (char*)NULL)) { + setenv("PID", val.c_str(), 1); + break; + } + } +} + +int main(int argc, const char **argv) +{ + deque<std::string> sections; + bool resolve_search = false; + std::string action; + std::string lookup_key; + std::string section_list_prefix; + std::list<string> filter_key; + std::map<string,string> filter_key_value; + std::string dump_format; + + auto args = argv_to_vec(argc, argv); + + auto orig_args = args; + auto cct = [&args] { + // override the PID before options are expanded + maybe_override_pid(args); + std::map<std::string,std::string> defaults = {{"log_to_file", "false"}}; + return global_init(&defaults, args, CEPH_ENTITY_TYPE_CLIENT, + CODE_ENVIRONMENT_DAEMON, + CINIT_FLAG_NO_DAEMON_ACTIONS | + CINIT_FLAG_NO_MON_CONFIG); + }(); + + // 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<const char*>::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(cerr); + return EXIT_FAILURE; + } + string key(val, 0, pos); + string value(val, pos+1); + filter_key_value[key] = value; + } else if (ceph_argparse_flag(args, i, "-D", "--dump_all", (char*)NULL)) { + action = "dumpall"; + } else if (ceph_argparse_witharg(args, i, &val, "--format", (char*)NULL)) { + dump_format = val; + } else { + if (((action == "lookup") || (action == "")) && (lookup_key.empty())) { + action = "lookup"; + lookup_key = *i++; + } else { + cerr << "unable to parse option: '" << *i << "'" << std::endl; + cerr << "args:"; + for (auto arg : orig_args) { + cerr << " " << std::quoted(arg); + } + cerr << std::endl; + usage(cerr); + return EXIT_FAILURE; + } + } + } + + cct->_log->flush(); + if (action == "help") { + usage(cout); + return EXIT_SUCCESS; + } 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 if (action == "dumpall") { + return dump_all(dump_format); + } else { + cerr << "You must give an action, such as --lookup or --list-all-sections." << std::endl; + cerr << "Pass --help for more help." << std::endl; + return EXIT_FAILURE; + } +} |