]>
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" | |
20 | ||
21 | using std::deque; | |
22 | using std::string; | |
23 | ||
24 | static void usage() | |
25 | { | |
26 | // TODO: add generic_usage once cerr/derr issues are resolved | |
27 | cerr << "Ceph configuration query tool\n\ | |
28 | \n\ | |
29 | USAGE\n\ | |
30 | ceph-conf <flags> <action>\n\ | |
31 | \n\ | |
32 | ACTIONS\n\ | |
33 | -L|--list-all-sections List all sections\n\ | |
34 | -l|--list-sections <prefix> List sections with the given prefix\n\ | |
35 | --filter-key <key> Filter section list to only include sections\n\ | |
36 | with given key defined.\n\ | |
37 | --filter-key-value <key>=<val> Filter section list to only include sections\n\ | |
38 | with given key/value pair.\n\ | |
39 | --lookup <key> Print a configuration setting to stdout.\n\ | |
40 | Returns 0 (success) if the configuration setting is\n\ | |
41 | found; 1 otherwise.\n\ | |
42 | -r|--resolve-search search for the first file that exists and\n\ | |
43 | can be opened in the resulted comma\n\ | |
44 | delimited search list.\n\ | |
45 | \n\ | |
46 | FLAGS\n\ | |
47 | --name name Set type.id\n\ | |
48 | [-s <section>] Add to list of sections to search\n\ | |
49 | \n\ | |
50 | If there is no action given, the action will default to --lookup.\n\ | |
51 | \n\ | |
52 | EXAMPLES\n\ | |
53 | $ ceph-conf --name mon.0 -c /etc/ceph/ceph.conf 'mon addr'\n\ | |
224ce89b | 54 | Find out what the value of 'mon addr' is for monitor 0.\n\ |
7c673cae FG |
55 | \n\ |
56 | $ ceph-conf -l mon\n\ | |
57 | List sections beginning with 'mon'.\n\ | |
58 | \n\ | |
59 | RETURN CODE\n\ | |
60 | Return code will be 0 on success; error code otherwise.\n\ | |
61 | "; | |
62 | exit(1); | |
63 | } | |
64 | ||
65 | static int list_sections(const std::string &prefix, | |
66 | const std::list<string>& filter_key, | |
67 | const std::map<string,string>& filter_key_value) | |
68 | { | |
69 | std::vector <std::string> sections; | |
70 | int ret = g_conf->get_all_sections(sections); | |
71 | if (ret) | |
72 | return 2; | |
73 | for (std::vector<std::string>::const_iterator p = sections.begin(); | |
74 | p != sections.end(); ++p) { | |
75 | if (strncmp(prefix.c_str(), p->c_str(), prefix.size())) | |
76 | continue; | |
77 | ||
78 | std::vector<std::string> sec; | |
79 | sec.push_back(*p); | |
80 | ||
81 | int r = 0; | |
82 | for (std::list<string>::const_iterator q = filter_key.begin(); q != filter_key.end(); ++q) { | |
83 | string v; | |
84 | r = g_conf->get_val_from_conf_file(sec, q->c_str(), v, false); | |
85 | if (r < 0) | |
86 | break; | |
87 | } | |
88 | if (r < 0) | |
89 | continue; | |
90 | ||
91 | for (std::map<string,string>::const_iterator q = filter_key_value.begin(); | |
92 | q != filter_key_value.end(); | |
93 | ++q) { | |
94 | string v; | |
95 | r = g_conf->get_val_from_conf_file(sec, q->first.c_str(), v, false); | |
96 | if (r < 0 || v != q->second) { | |
97 | r = -1; | |
98 | break; | |
99 | } | |
100 | } | |
101 | if (r < 0) | |
102 | continue; | |
103 | ||
104 | cout << *p << std::endl; | |
105 | } | |
106 | return 0; | |
107 | } | |
108 | ||
109 | static int lookup(const std::deque<std::string> §ions, | |
110 | const std::string &key, bool resolve_search) | |
111 | { | |
112 | std::vector <std::string> my_sections; | |
113 | for (deque<string>::const_iterator s = sections.begin(); s != sections.end(); ++s) { | |
114 | my_sections.push_back(*s); | |
115 | } | |
116 | g_conf->get_my_sections(my_sections); | |
117 | std::string val; | |
118 | int ret = g_conf->get_val_from_conf_file(my_sections, key.c_str(), val, true); | |
119 | if (ret == -ENOENT) | |
120 | return 1; | |
121 | else if (ret == 0) { | |
122 | if (resolve_search) { | |
123 | string result; | |
124 | ret = ceph_resolve_file_search(val, result); | |
125 | if (!ret) | |
126 | puts(result.c_str()); | |
127 | } | |
128 | else { | |
129 | puts(val.c_str()); | |
130 | } | |
131 | return 0; | |
132 | } | |
133 | else { | |
134 | cerr << "error looking up '" << key << "': error " << ret << std::endl; | |
135 | return 2; | |
136 | } | |
137 | } | |
138 | ||
139 | int main(int argc, const char **argv) | |
140 | { | |
141 | vector<const char*> args; | |
142 | deque<std::string> sections; | |
143 | bool resolve_search = false; | |
144 | std::string action; | |
145 | std::string lookup_key; | |
146 | std::string section_list_prefix; | |
147 | std::list<string> filter_key; | |
148 | std::map<string,string> filter_key_value; | |
149 | ||
150 | argv_to_vec(argc, argv, args); | |
151 | env_to_vec(args); | |
152 | vector<const char*> orig_args = args; | |
153 | ||
154 | global_pre_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON, | |
155 | CINIT_FLAG_NO_DAEMON_ACTIONS); | |
156 | std::unique_ptr<CephContext, | |
157 | std::function<void(CephContext*)> > cct_deleter{ | |
158 | g_ceph_context, | |
159 | [](CephContext *p) {p->put();} | |
160 | }; | |
161 | ||
162 | g_conf->apply_changes(NULL); | |
163 | g_conf->complain_about_parse_errors(g_ceph_context); | |
164 | ||
165 | // do not common_init_finish(); do not start threads; do not do any of thing | |
166 | // wonky things the daemon whose conf we are examining would do (like initialize | |
167 | // the admin socket). | |
168 | //common_init_finish(g_ceph_context); | |
169 | ||
170 | std::string val; | |
171 | for (std::vector<const char*>::iterator i = args.begin(); i != args.end(); ) { | |
172 | if (ceph_argparse_double_dash(args, i)) { | |
173 | break; | |
174 | } else if (ceph_argparse_witharg(args, i, &val, "-s", "--section", (char*)NULL)) { | |
175 | sections.push_back(val); | |
176 | } else if (ceph_argparse_flag(args, i, "-r", "--resolve_search", (char*)NULL)) { | |
177 | resolve_search = true; | |
178 | } else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) { | |
179 | action = "help"; | |
180 | } else if (ceph_argparse_witharg(args, i, &val, "--lookup", (char*)NULL)) { | |
181 | action = "lookup"; | |
182 | lookup_key = val; | |
183 | } else if (ceph_argparse_flag(args, i, "-L", "--list_all_sections", (char*)NULL)) { | |
184 | action = "list-sections"; | |
185 | section_list_prefix = ""; | |
186 | } else if (ceph_argparse_witharg(args, i, &val, "-l", "--list_sections", (char*)NULL)) { | |
187 | action = "list-sections"; | |
188 | section_list_prefix = val; | |
189 | } else if (ceph_argparse_witharg(args, i, &val, "--filter_key", (char*)NULL)) { | |
190 | filter_key.push_back(val); | |
191 | } else if (ceph_argparse_witharg(args, i, &val, "--filter_key_value", (char*)NULL)) { | |
192 | size_t pos = val.find_first_of('='); | |
193 | if (pos == string::npos) { | |
194 | cerr << "expecting argument like 'key=value' for --filter-key-value (not '" << val << "')" << std::endl; | |
195 | usage(); | |
196 | exit(1); | |
197 | } | |
198 | string key(val, 0, pos); | |
199 | string value(val, pos+1); | |
200 | filter_key_value[key] = value; | |
201 | } else { | |
202 | if (((action == "lookup") || (action == "")) && (lookup_key.empty())) { | |
203 | action = "lookup"; | |
204 | lookup_key = *i++; | |
205 | } else { | |
206 | cerr << "unable to parse option: '" << *i << "'" << std::endl; | |
207 | cerr << "args:"; | |
208 | for (std::vector<const char *>::iterator ci = orig_args.begin(); ci != orig_args.end(); ++ci) { | |
209 | cerr << " '" << *ci << "'"; | |
210 | } | |
211 | cerr << std::endl; | |
212 | usage(); | |
213 | exit(1); | |
214 | } | |
215 | } | |
216 | } | |
217 | ||
218 | g_ceph_context->_log->flush(); | |
219 | if (action == "help") { | |
220 | usage(); | |
221 | exit(0); | |
222 | } else if (action == "list-sections") { | |
223 | return list_sections(section_list_prefix, filter_key, filter_key_value); | |
224 | } else if (action == "lookup") { | |
225 | return lookup(sections, lookup_key, resolve_search); | |
226 | } else { | |
227 | cerr << "You must give an action, such as --lookup or --list-all-sections." << std::endl; | |
228 | cerr << "Pass --help for more help." << std::endl; | |
229 | exit(1); | |
230 | } | |
231 | } |