// -*- 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 "common/ceph_argparse.h" #include "global/global_init.h" #include "mon/AuthMonitor.h" #include "common/Formatter.h" using std::deque; using std::string; 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 ACTIONS -L|--list-all-sections List all sections -l|--list-sections List sections with the given prefix --filter-key Filter section list to only include sections with given key defined. --filter-key-value = Filter section list to only include sections with given key/value pair. --lookup 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 Print the corresponding ceph.conf value that matches the specified key. Also searches global defaults. FLAGS --name name Set type.id [-s
] Add to list of sections to search [--format plain|json|json-pretty] dump variables in plain text, json or pretty json [--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& 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{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 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& 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) { 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; std::string dump_format; argv_to_vec(argc, argv, args); auto orig_args = args; auto cct = [&args] { // override the PID before options are expanded maybe_override_pid(args); std::map 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::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 << " " << 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; } }