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