]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2010 Dreamhost | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | #include <string> | |
16 | ||
17 | #include "common/ceph_argparse.h" | |
18 | #include "global/global_init.h" | |
19 | #include "mon/AuthMonitor.h" | |
b32b8144 | 20 | #include "common/Formatter.h" |
7c673cae FG |
21 | |
22 | using std::deque; | |
23 | using std::string; | |
24 | ||
25 | static void usage() | |
26 | { | |
27 | // TODO: add generic_usage once cerr/derr issues are resolved | |
28 | cerr << "Ceph configuration query tool\n\ | |
29 | \n\ | |
30 | USAGE\n\ | |
31 | ceph-conf <flags> <action>\n\ | |
32 | \n\ | |
33 | ACTIONS\n\ | |
34 | -L|--list-all-sections List all sections\n\ | |
35 | -l|--list-sections <prefix> List sections with the given prefix\n\ | |
36 | --filter-key <key> Filter section list to only include sections\n\ | |
37 | with given key defined.\n\ | |
38 | --filter-key-value <key>=<val> Filter section list to only include sections\n\ | |
39 | with given key/value pair.\n\ | |
40 | --lookup <key> Print a configuration setting to stdout.\n\ | |
41 | Returns 0 (success) if the configuration setting is\n\ | |
42 | found; 1 otherwise.\n\ | |
43 | -r|--resolve-search search for the first file that exists and\n\ | |
44 | can be opened in the resulted comma\n\ | |
45 | delimited search list.\n\ | |
b32b8144 | 46 | -D|--dump-all dump all variables.\n\ |
7c673cae FG |
47 | \n\ |
48 | FLAGS\n\ | |
49 | --name name Set type.id\n\ | |
50 | [-s <section>] Add to list of sections to search\n\ | |
b32b8144 FG |
51 | [--format plain|json|json-pretty]\n\ |
52 | dump variables in plain text, json or pretty\n\ | |
53 | json\n\ | |
7c673cae FG |
54 | \n\ |
55 | If there is no action given, the action will default to --lookup.\n\ | |
56 | \n\ | |
57 | EXAMPLES\n\ | |
58 | $ ceph-conf --name mon.0 -c /etc/ceph/ceph.conf 'mon addr'\n\ | |
224ce89b | 59 | Find out what the value of 'mon addr' is for monitor 0.\n\ |
7c673cae FG |
60 | \n\ |
61 | $ ceph-conf -l mon\n\ | |
62 | List sections beginning with 'mon'.\n\ | |
63 | \n\ | |
64 | RETURN CODE\n\ | |
65 | Return code will be 0 on success; error code otherwise.\n\ | |
66 | "; | |
67 | exit(1); | |
68 | } | |
69 | ||
70 | static int list_sections(const std::string &prefix, | |
71 | const std::list<string>& filter_key, | |
72 | const std::map<string,string>& filter_key_value) | |
73 | { | |
74 | std::vector <std::string> sections; | |
75 | int ret = g_conf->get_all_sections(sections); | |
76 | if (ret) | |
77 | return 2; | |
78 | for (std::vector<std::string>::const_iterator p = sections.begin(); | |
79 | p != sections.end(); ++p) { | |
80 | if (strncmp(prefix.c_str(), p->c_str(), prefix.size())) | |
81 | continue; | |
82 | ||
83 | std::vector<std::string> sec; | |
84 | sec.push_back(*p); | |
85 | ||
86 | int r = 0; | |
87 | for (std::list<string>::const_iterator q = filter_key.begin(); q != filter_key.end(); ++q) { | |
88 | string v; | |
89 | r = g_conf->get_val_from_conf_file(sec, q->c_str(), v, false); | |
90 | if (r < 0) | |
91 | break; | |
92 | } | |
93 | if (r < 0) | |
94 | continue; | |
95 | ||
96 | for (std::map<string,string>::const_iterator q = filter_key_value.begin(); | |
97 | q != filter_key_value.end(); | |
98 | ++q) { | |
99 | string v; | |
100 | r = g_conf->get_val_from_conf_file(sec, q->first.c_str(), v, false); | |
101 | if (r < 0 || v != q->second) { | |
102 | r = -1; | |
103 | break; | |
104 | } | |
105 | } | |
106 | if (r < 0) | |
107 | continue; | |
108 | ||
109 | cout << *p << std::endl; | |
110 | } | |
111 | return 0; | |
112 | } | |
113 | ||
114 | static int lookup(const std::deque<std::string> §ions, | |
115 | const std::string &key, bool resolve_search) | |
116 | { | |
117 | std::vector <std::string> my_sections; | |
118 | for (deque<string>::const_iterator s = sections.begin(); s != sections.end(); ++s) { | |
119 | my_sections.push_back(*s); | |
120 | } | |
121 | g_conf->get_my_sections(my_sections); | |
122 | std::string val; | |
123 | int ret = g_conf->get_val_from_conf_file(my_sections, key.c_str(), val, true); | |
124 | if (ret == -ENOENT) | |
125 | return 1; | |
126 | else if (ret == 0) { | |
127 | if (resolve_search) { | |
128 | string result; | |
129 | ret = ceph_resolve_file_search(val, result); | |
130 | if (!ret) | |
131 | puts(result.c_str()); | |
132 | } | |
133 | else { | |
134 | puts(val.c_str()); | |
135 | } | |
136 | return 0; | |
137 | } | |
138 | else { | |
139 | cerr << "error looking up '" << key << "': error " << ret << std::endl; | |
140 | return 2; | |
141 | } | |
142 | } | |
143 | ||
b32b8144 FG |
144 | static int dump_all(const string& format) |
145 | { | |
146 | if (format == "" || format == "plain") { | |
147 | g_conf->show_config(std::cout); | |
148 | return 0; | |
149 | } else { | |
150 | unique_ptr<Formatter> f(Formatter::create(format)); | |
151 | if (f) { | |
152 | f->open_object_section("ceph-conf"); | |
153 | g_conf->show_config(f.get()); | |
154 | f->close_section(); | |
155 | f->flush(std::cout); | |
156 | return 0; | |
157 | } | |
158 | cerr << "format '" << format << "' not recognized." << std::endl; | |
159 | usage(); | |
160 | return 1; | |
161 | } | |
162 | } | |
163 | ||
7c673cae FG |
164 | int main(int argc, const char **argv) |
165 | { | |
166 | vector<const char*> args; | |
167 | deque<std::string> sections; | |
168 | bool resolve_search = false; | |
169 | std::string action; | |
170 | std::string lookup_key; | |
171 | std::string section_list_prefix; | |
172 | std::list<string> filter_key; | |
173 | std::map<string,string> filter_key_value; | |
b32b8144 | 174 | std::string dump_format; |
7c673cae FG |
175 | |
176 | argv_to_vec(argc, argv, args); | |
177 | env_to_vec(args); | |
178 | vector<const char*> orig_args = args; | |
179 | ||
180 | global_pre_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON, | |
181 | CINIT_FLAG_NO_DAEMON_ACTIONS); | |
182 | std::unique_ptr<CephContext, | |
183 | std::function<void(CephContext*)> > cct_deleter{ | |
184 | g_ceph_context, | |
185 | [](CephContext *p) {p->put();} | |
186 | }; | |
187 | ||
188 | g_conf->apply_changes(NULL); | |
189 | g_conf->complain_about_parse_errors(g_ceph_context); | |
190 | ||
191 | // do not common_init_finish(); do not start threads; do not do any of thing | |
192 | // wonky things the daemon whose conf we are examining would do (like initialize | |
193 | // the admin socket). | |
194 | //common_init_finish(g_ceph_context); | |
195 | ||
196 | std::string val; | |
197 | for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) { | |
198 | if (ceph_argparse_double_dash(args, i)) { | |
199 | break; | |
200 | } else if (ceph_argparse_witharg(args, i, &val, "-s", "--section", (char*)NULL)) { | |
201 | sections.push_back(val); | |
202 | } else if (ceph_argparse_flag(args, i, "-r", "--resolve_search", (char*)NULL)) { | |
203 | resolve_search = true; | |
204 | } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) { | |
205 | action = "help"; | |
206 | } else if (ceph_argparse_witharg(args, i, &val, "--lookup", (char*)NULL)) { | |
207 | action = "lookup"; | |
208 | lookup_key = val; | |
209 | } else if (ceph_argparse_flag(args, i, "-L", "--list_all_sections", (char*)NULL)) { | |
210 | action = "list-sections"; | |
211 | section_list_prefix = ""; | |
212 | } else if (ceph_argparse_witharg(args, i, &val, "-l", "--list_sections", (char*)NULL)) { | |
213 | action = "list-sections"; | |
214 | section_list_prefix = val; | |
215 | } else if (ceph_argparse_witharg(args, i, &val, "--filter_key", (char*)NULL)) { | |
216 | filter_key.push_back(val); | |
217 | } else if (ceph_argparse_witharg(args, i, &val, "--filter_key_value", (char*)NULL)) { | |
218 | size_t pos = val.find_first_of('='); | |
219 | if (pos == string::npos) { | |
220 | cerr << "expecting argument like 'key=value' for --filter-key-value (not '" << val << "')" << std::endl; | |
221 | usage(); | |
222 | exit(1); | |
223 | } | |
224 | string key(val, 0, pos); | |
225 | string value(val, pos+1); | |
226 | filter_key_value[key] = value; | |
b32b8144 FG |
227 | } else if (ceph_argparse_flag(args, i, "-D", "--dump_all", (char*)NULL)) { |
228 | action = "dumpall"; | |
229 | } else if (ceph_argparse_witharg(args, i, &val, "--format", (char*)NULL)) { | |
230 | dump_format = val; | |
7c673cae FG |
231 | } else { |
232 | if (((action == "lookup") || (action == "")) && (lookup_key.empty())) { | |
233 | action = "lookup"; | |
234 | lookup_key = *i++; | |
235 | } else { | |
236 | cerr << "unable to parse option: '" << *i << "'" << std::endl; | |
237 | cerr << "args:"; | |
238 | for (std::vector<const char *>::iterator ci = orig_args.begin(); ci != orig_args.end(); ++ci) { | |
239 | cerr << " '" << *ci << "'"; | |
240 | } | |
241 | cerr << std::endl; | |
242 | usage(); | |
243 | exit(1); | |
244 | } | |
245 | } | |
246 | } | |
247 | ||
248 | g_ceph_context->_log->flush(); | |
249 | if (action == "help") { | |
250 | usage(); | |
251 | exit(0); | |
252 | } else if (action == "list-sections") { | |
253 | return list_sections(section_list_prefix, filter_key, filter_key_value); | |
254 | } else if (action == "lookup") { | |
255 | return lookup(sections, lookup_key, resolve_search); | |
b32b8144 FG |
256 | } else if (action == "dumpall") { |
257 | return dump_all(dump_format); | |
7c673cae FG |
258 | } else { |
259 | cerr << "You must give an action, such as --lookup or --list-all-sections." << std::endl; | |
260 | cerr << "Pass --help for more help." << std::endl; | |
261 | exit(1); | |
262 | } | |
263 | } |