Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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  */