]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/daemon_config.cc
update sources to 12.2.2
[ceph.git] / ceph / src / test / daemon_config.cc
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) 2011 New Dream Network
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 "gtest/gtest.h"
16 #include "common/ceph_argparse.h"
17 #include "common/config.h"
18 #include "global/global_context.h"
19 #include "include/cephfs/libcephfs.h"
20 #include "include/rados/librados.h"
21
22 #include <errno.h>
23 #include <sstream>
24 #include <string>
25 #include <string.h>
26
27 #include <boost/lexical_cast.hpp>
28
29
30 using std::string;
31
32 TEST(DaemonConfig, SimpleSet) {
33 int ret;
34 ret = g_ceph_context->_conf->set_val("log_graylog_port", "21");
35 ASSERT_EQ(0, ret);
36 g_ceph_context->_conf->apply_changes(NULL);
37 char buf[128];
38 memset(buf, 0, sizeof(buf));
39 char *tmp = buf;
40 ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf));
41 ASSERT_EQ(0, ret);
42 ASSERT_EQ(string("21"), string(buf));
43 }
44
45 TEST(DaemonConfig, Substitution) {
46 int ret;
47 ret = g_ceph_context->_conf->set_val("internal_safe_to_start_threads", "false");
48 ASSERT_EQ(0, ret);
49 ret = g_ceph_context->_conf->set_val("host", "foo");
50 ASSERT_EQ(0, ret);
51 ret = g_ceph_context->_conf->set_val("public_network", "bar$host.baz", false);
52 ASSERT_EQ(0, ret);
53 g_ceph_context->_conf->apply_changes(NULL);
54 char buf[128];
55 memset(buf, 0, sizeof(buf));
56 char *tmp = buf;
57 ret = g_ceph_context->_conf->get_val("public_network", &tmp, sizeof(buf));
58 ASSERT_EQ(0, ret);
59 ASSERT_EQ(string("barfoo.baz"), string(buf));
60 }
61
62 TEST(DaemonConfig, SubstitutionTrailing) {
63 int ret;
64 ret = g_ceph_context->_conf->set_val("internal_safe_to_start_threads", "false");
65 ASSERT_EQ(0, ret);
66 ret = g_ceph_context->_conf->set_val("host", "foo");
67 ASSERT_EQ(0, ret);
68 ret = g_ceph_context->_conf->set_val("public_network", "bar$host", false);
69 ASSERT_EQ(0, ret);
70 g_ceph_context->_conf->apply_changes(NULL);
71 char buf[128];
72 memset(buf, 0, sizeof(buf));
73 char *tmp = buf;
74 ret = g_ceph_context->_conf->get_val("public_network", &tmp, sizeof(buf));
75 ASSERT_EQ(0, ret);
76 ASSERT_EQ(string("barfoo"), string(buf));
77 }
78
79 TEST(DaemonConfig, SubstitutionBraces) {
80 int ret;
81 ret = g_ceph_context->_conf->set_val("internal_safe_to_start_threads", "false");
82 ASSERT_EQ(0, ret);
83 ret = g_ceph_context->_conf->set_val("host", "foo");
84 ASSERT_EQ(0, ret);
85 ret = g_ceph_context->_conf->set_val("public_network", "bar${host}baz", false);
86 ASSERT_EQ(0, ret);
87 g_ceph_context->_conf->apply_changes(NULL);
88 char buf[128];
89 memset(buf, 0, sizeof(buf));
90 char *tmp = buf;
91 ret = g_ceph_context->_conf->get_val("public_network", &tmp, sizeof(buf));
92 ASSERT_EQ(0, ret);
93 ASSERT_EQ(string("barfoobaz"), string(buf));
94 }
95 TEST(DaemonConfig, SubstitutionBracesTrailing) {
96 int ret;
97 ret = g_ceph_context->_conf->set_val("internal_safe_to_start_threads", "false");
98 ASSERT_EQ(0, ret);
99 ret = g_ceph_context->_conf->set_val("host", "foo");
100 ASSERT_EQ(0, ret);
101 ret = g_ceph_context->_conf->set_val("public_network", "bar${host}", false);
102 ASSERT_EQ(0, ret);
103 g_ceph_context->_conf->apply_changes(NULL);
104 char buf[128];
105 memset(buf, 0, sizeof(buf));
106 char *tmp = buf;
107 ret = g_ceph_context->_conf->get_val("public_network", &tmp, sizeof(buf));
108 ASSERT_EQ(0, ret);
109 ASSERT_EQ(string("barfoo"), string(buf));
110 }
111
112 // config: variable substitution happen only once http://tracker.ceph.com/issues/7103
113 TEST(DaemonConfig, SubstitutionMultiple) {
114 int ret;
115 ret = g_ceph_context->_conf->set_val("mon_host", "localhost", false);
116 ASSERT_EQ(0, ret);
117 ret = g_ceph_context->_conf->set_val("keyring", "$mon_host/$cluster.keyring,$mon_host/$cluster.mon.keyring", false);
118 ASSERT_EQ(0, ret);
119 g_ceph_context->_conf->apply_changes(NULL);
120 char buf[512];
121 memset(buf, 0, sizeof(buf));
122 char *tmp = buf;
123 ret = g_ceph_context->_conf->get_val("keyring", &tmp, sizeof(buf));
124 ASSERT_EQ(0, ret);
125 ASSERT_EQ(string("localhost/ceph.keyring,localhost/ceph.mon.keyring"), tmp);
126 ASSERT_TRUE(strchr(buf, '$') == NULL);
127 }
128
129 TEST(DaemonConfig, ArgV) {
130 ASSERT_EQ(0, g_ceph_context->_conf->set_val("internal_safe_to_start_threads",
131 "false"));
132
133 int ret;
134 const char *argv[] = { "foo", "--log-graylog-port", "22",
135 "--keyfile", "/tmp/my-keyfile", NULL };
136 size_t argc = (sizeof(argv) / sizeof(argv[0])) - 1;
137 vector<const char*> args;
138 argv_to_vec(argc, argv, args);
139 g_ceph_context->_conf->parse_argv(args);
140 g_ceph_context->_conf->apply_changes(NULL);
141
142 char buf[128];
143 char *tmp = buf;
144 memset(buf, 0, sizeof(buf));
145 ret = g_ceph_context->_conf->get_val("keyfile", &tmp, sizeof(buf));
146 ASSERT_EQ(0, ret);
147 ASSERT_EQ(string("/tmp/my-keyfile"), string(buf));
148
149 memset(buf, 0, sizeof(buf));
150 ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf));
151 ASSERT_EQ(0, ret);
152 ASSERT_EQ(string("22"), string(buf));
153
154 ASSERT_EQ(0, g_ceph_context->_conf->set_val("internal_safe_to_start_threads",
155 "true"));
156 }
157
158 TEST(DaemonConfig, InjectArgs) {
159 int ret;
160 std::string injection("--log-graylog-port 56 --leveldb-max-open-files 42");
161 ret = g_ceph_context->_conf->injectargs(injection, &cout);
162 ASSERT_EQ(0, ret);
163
164 char buf[128];
165 char *tmp = buf;
166 memset(buf, 0, sizeof(buf));
167 ret = g_ceph_context->_conf->get_val("leveldb_max_open_files", &tmp, sizeof(buf));
168 ASSERT_EQ(0, ret);
169 ASSERT_EQ(string("42"), string(buf));
170
171 memset(buf, 0, sizeof(buf));
172 ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf));
173 ASSERT_EQ(0, ret);
174 ASSERT_EQ(string("56"), string(buf));
175
176 injection = "--log-graylog-port 57";
177 ret = g_ceph_context->_conf->injectargs(injection, &cout);
178 ASSERT_EQ(0, ret);
179 ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf));
180 ASSERT_EQ(0, ret);
181 ASSERT_EQ(string("57"), string(buf));
182 }
183
184 TEST(DaemonConfig, InjectArgsReject) {
185 int ret;
186 char buf[128];
187 char *tmp = buf;
188 char buf2[128];
189 char *tmp2 = buf2;
190
191 // We should complain about the garbage in the input
192 std::string injection("--random-garbage-in-injectargs 26 --log-graylog-port 28");
193 ret = g_ceph_context->_conf->injectargs(injection, &cout);
194 ASSERT_EQ(-EINVAL, ret);
195
196 // But, debug should still be set...
197 memset(buf, 0, sizeof(buf));
198 ret = g_ceph_context->_conf->get_val("log_graylog_port", &tmp, sizeof(buf));
199 ASSERT_EQ(0, ret);
200 ASSERT_EQ(string("28"), string(buf));
201
202 // What's the current value of osd_data?
203 memset(buf, 0, sizeof(buf));
204 ret = g_ceph_context->_conf->get_val("osd_data", &tmp, sizeof(buf));
205 ASSERT_EQ(0, ret);
206
207 // Injectargs shouldn't let us change this, since it is a string-valued
208 // variable and there isn't an observer for it.
209 std::string injection2("--osd_data /tmp/some-other-directory --log-graylog-port 4");
210 ret = g_ceph_context->_conf->injectargs(injection2, &cout);
211 ASSERT_EQ(-ENOSYS, ret);
212
213 // It should be unchanged.
214 memset(buf2, 0, sizeof(buf2));
215 ret = g_ceph_context->_conf->get_val("osd_data", &tmp2, sizeof(buf2));
216 ASSERT_EQ(0, ret);
217 ASSERT_EQ(string(buf), string(buf2));
218
219 // We should complain about the missing arguments.
220 std::string injection3("--log-graylog-port 28 --debug_ms");
221 ret = g_ceph_context->_conf->injectargs(injection3, &cout);
222 ASSERT_EQ(-EINVAL, ret);
223 }
224
225 TEST(DaemonConfig, InjectArgsBooleans) {
226 int ret;
227 char buf[128];
228 char *tmp = buf;
229
230 // Change log_to_syslog
231 std::string injection("--log_to_syslog --log-graylog-port 28");
232 ret = g_ceph_context->_conf->injectargs(injection, &cout);
233 ASSERT_EQ(0, ret);
234
235 // log_to_syslog should be set...
236 memset(buf, 0, sizeof(buf));
237 ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf));
238 ASSERT_EQ(0, ret);
239 ASSERT_EQ(string("true"), string(buf));
240
241 // Turn off log_to_syslog
242 injection = "--log_to_syslog=false --log-graylog-port 28";
243 ret = g_ceph_context->_conf->injectargs(injection, &cout);
244 ASSERT_EQ(0, ret);
245
246 // log_to_syslog should be cleared...
247 memset(buf, 0, sizeof(buf));
248 ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf));
249 ASSERT_EQ(0, ret);
250 ASSERT_EQ(string("false"), string(buf));
251
252 // Turn on log_to_syslog
253 injection = "--log-graylog-port=1 --log_to_syslog=true --leveldb-max-open-files 40";
254 ret = g_ceph_context->_conf->injectargs(injection, &cout);
255 ASSERT_EQ(0, ret);
256
257 // log_to_syslog should be set...
258 memset(buf, 0, sizeof(buf));
259 ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf));
260 ASSERT_EQ(0, ret);
261 ASSERT_EQ(string("true"), string(buf));
262
263 // parse error
264 injection = "--log-graylog-port 1 --log_to_syslog=falsey --leveldb-max-open-files 42";
265 ret = g_ceph_context->_conf->injectargs(injection, &cout);
266 ASSERT_EQ(-EINVAL, ret);
267
268 // log_to_syslog should still be set...
269 memset(buf, 0, sizeof(buf));
270 ret = g_ceph_context->_conf->get_val("log_to_syslog", &tmp, sizeof(buf));
271 ASSERT_EQ(0, ret);
272 ASSERT_EQ(string("true"), string(buf));
273
274 // debug-ms should still become 42...
275 memset(buf, 0, sizeof(buf));
276 ret = g_ceph_context->_conf->get_val("leveldb_max_open_files", &tmp, sizeof(buf));
277 ASSERT_EQ(0, ret);
278 ASSERT_EQ(string("42"), string(buf));
279 }
280
281 TEST(DaemonConfig, InjectArgsLogfile) {
282 int ret;
283 char tmpfile[PATH_MAX];
284 const char *tmpdir = getenv("TMPDIR");
285 if (!tmpdir)
286 tmpdir = "/tmp";
287 snprintf(tmpfile, sizeof(tmpfile), "%s/daemon_config_test.%d",
288 tmpdir, getpid());
289 std::string injection("--log_file ");
290 injection += tmpfile;
291 // We're allowed to change log_file because there is an observer.
292 ret = g_ceph_context->_conf->injectargs(injection, &cout);
293 ASSERT_EQ(0, ret);
294
295 // It should have taken effect.
296 char buf[128];
297 char *tmp = buf;
298 memset(buf, 0, sizeof(buf));
299 ret = g_ceph_context->_conf->get_val("log_file", &tmp, sizeof(buf));
300 ASSERT_EQ(0, ret);
301 ASSERT_EQ(string(buf), string(tmpfile));
302
303 // The logfile should exist.
304 ASSERT_EQ(0, access(tmpfile, R_OK));
305
306 // Let's turn off the logfile.
307 ret = g_ceph_context->_conf->set_val("log_file", "");
308 ASSERT_EQ(0, ret);
309 g_ceph_context->_conf->apply_changes(NULL);
310 ret = g_ceph_context->_conf->get_val("log_file", &tmp, sizeof(buf));
311 ASSERT_EQ(0, ret);
312 ASSERT_EQ(string(""), string(buf));
313
314 // Clean up the garbage
315 unlink(tmpfile);
316 }
317
318 TEST(DaemonConfig, ThreadSafety1) {
319 int ret;
320 // Verify that we can't change this, since internal_safe_to_start_threads has
321 // been set.
322 ret = g_ceph_context->_conf->set_val("osd_data", "");
323 ASSERT_EQ(-ENOSYS, ret);
324
325 ASSERT_EQ(0, g_ceph_context->_conf->set_val("internal_safe_to_start_threads",
326 "false"));
327
328 // Ok, now we can change this. Since this is just a test, and there are no
329 // OSD threads running, we know changing osd_data won't actually blow up the
330 // world.
331 ret = g_ceph_context->_conf->set_val("osd_data", "/tmp/crazydata");
332 ASSERT_EQ(0, ret);
333
334 char buf[128];
335 char *tmp = buf;
336 memset(buf, 0, sizeof(buf));
337 ret = g_ceph_context->_conf->get_val("osd_data", &tmp, sizeof(buf));
338 ASSERT_EQ(0, ret);
339 ASSERT_EQ(string("/tmp/crazydata"), string(buf));
340
341 ASSERT_EQ(0, g_ceph_context->_conf->set_val("internal_safe_to_start_threads",
342 "false"));
343 ASSERT_EQ(0, ret);
344 }
345
346 TEST(DaemonConfig, InvalidIntegers) {
347 {
348 int ret = g_ceph_context->_conf->set_val("log_graylog_port", "rhubarb");
349 ASSERT_EQ(-EINVAL, ret);
350 }
351
352 {
353 int64_t max = std::numeric_limits<int64_t>::max();
354 string str = boost::lexical_cast<string>(max);
355 str = str + "999"; // some extra digits to take us out of bounds
356 int ret = g_ceph_context->_conf->set_val("log_graylog_port", str);
357 ASSERT_EQ(-EINVAL, ret);
358 }
359 }
360
361 TEST(DaemonConfig, InvalidFloats) {
362 {
363 double bad_value = 2 * (double)std::numeric_limits<float>::max();
364 string str = boost::lexical_cast<string>(-bad_value);
365 int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", str);
366 ASSERT_EQ(-EINVAL, ret);
367 }
368 {
369 double bad_value = 2 * (double)std::numeric_limits<float>::max();
370 string str = boost::lexical_cast<string>(bad_value);
371 int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", str);
372 ASSERT_EQ(-EINVAL, ret);
373 }
374 {
375 int ret = g_ceph_context->_conf->set_val("log_stop_at_utilization", "not a float");
376 ASSERT_EQ(-EINVAL, ret);
377 }
378 }
379
380 /*
381 * Local Variables:
382 * compile-command: "cd .. ; make unittest_daemon_config && ./unittest_daemon_config"
383 * End:
384 */