Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librados / cmd.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "mds/mdstypes.h"
5 #include "include/buffer.h"
6 #include "include/rbd_types.h"
7 #include "include/rados/librados.h"
8 #include "include/rados/librados.hpp"
9 #include "include/stringify.h"
10 #include "test/librados/test.h"
11
12 #include "common/Cond.h"
13
14 #include "gtest/gtest.h"
15 #include <errno.h>
16 #include <map>
17 #include <sstream>
18 #include <string>
19
20 using namespace librados;
21 using std::map;
22 using std::ostringstream;
23 using std::string;
24
25 TEST(LibRadosCmd, MonDescribe) {
26   rados_t cluster;
27   ASSERT_EQ("", connect_cluster(&cluster));
28
29   char *buf, *st;
30   size_t buflen, stlen;
31   char *cmd[2];
32
33   cmd[1] = NULL;
34
35   cmd[0] = (char *)"{\"prefix\":\"get_command_descriptions\"}";
36   ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
37   ASSERT_LT(0u, buflen);
38   rados_buffer_free(buf);
39   rados_buffer_free(st);
40
41   cmd[0] = (char *)"get_command_descriptions";
42   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
43   rados_buffer_free(buf);
44   rados_buffer_free(st);
45
46   cmd[0] = (char *)"asdfqwer";
47   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "{}", 2, &buf, &buflen, &st, &stlen));
48   rados_buffer_free(buf);
49   rados_buffer_free(st);
50
51   cmd[0] = (char *)"";
52   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "{}", 2, &buf, &buflen, &st, &stlen));
53   rados_buffer_free(buf);
54   rados_buffer_free(st);
55
56   cmd[0] = (char *)"{}";
57   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
58   rados_buffer_free(buf);
59   rados_buffer_free(st);
60
61   cmd[0] = (char *)"{\"abc\":\"something\"}";
62   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
63   rados_buffer_free(buf);
64   rados_buffer_free(st);
65
66   cmd[0] = (char *)"{\"prefix\":\"\"}";
67   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
68   rados_buffer_free(buf);
69   rados_buffer_free(st);
70
71   cmd[0] = (char *)"{\"prefix\":\"    \"}";
72   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
73   rados_buffer_free(buf);
74   rados_buffer_free(st);
75
76   cmd[0] = (char *)"{\"prefix\":\";;;,,,;;,,\"}";
77   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
78   rados_buffer_free(buf);
79   rados_buffer_free(st);
80
81   cmd[0] = (char *)"{\"prefix\":\"extra command\"}";
82   ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
83   rados_buffer_free(buf);
84   rados_buffer_free(st);
85
86   cmd[0] = (char *)"{\"prefix\":\"mon_status\"}";
87   ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
88   ASSERT_LT(0u, buflen);
89   //ASSERT_LT(0u, stlen);
90   rados_buffer_free(buf);
91   rados_buffer_free(st);
92   rados_shutdown(cluster);
93 }
94
95 TEST(LibRadosCmd, MonDescribePP) {
96   Rados cluster;
97   ASSERT_EQ("", connect_cluster_pp(cluster));
98   bufferlist inbl, outbl;
99   string outs;
100   ASSERT_EQ(0, cluster.mon_command("{\"prefix\": \"get_command_descriptions\"}",
101                                    inbl, &outbl, &outs));
102   ASSERT_LT(0u, outbl.length());
103   ASSERT_LE(0u, outs.length());
104   cluster.shutdown();
105 }
106
107 TEST(LibRadosCmd, OSDCmd) {
108   rados_t cluster;
109   ASSERT_EQ("", connect_cluster(&cluster));
110   int r;
111   char *buf, *st;
112   size_t buflen, stlen;
113   char *cmd[2];
114   cmd[1] = NULL;
115
116   // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
117   cmd[0] = (char *)"asdfasdf";
118   r = rados_osd_command(cluster, 0, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
119   rados_buffer_free(buf);
120   rados_buffer_free(st);
121   ASSERT_TRUE(r == -22 || r == -ENXIO);
122   cmd[0] = (char *)"version";
123   r = rados_osd_command(cluster, 0, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
124   rados_buffer_free(buf);
125   rados_buffer_free(st);
126   ASSERT_TRUE(r == -22 || r == -ENXIO);
127   cmd[0] = (char *)"{\"prefix\":\"version\"}";
128   r = rados_osd_command(cluster, 0, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
129   ASSERT_TRUE((r == 0 && buflen > 0) || (r == -ENXIO && buflen == 0));
130   rados_buffer_free(buf);
131   rados_buffer_free(st);
132   rados_shutdown(cluster);
133 }
134
135 TEST(LibRadosCmd, OSDCmdPP) {
136   Rados cluster;
137   ASSERT_EQ("", connect_cluster_pp(cluster));
138   int r;
139   bufferlist inbl, outbl;
140   string outs;
141   string cmd;
142
143   // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
144   cmd = "asdfasdf";
145   r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
146   ASSERT_TRUE(r == -22 || r == -ENXIO);
147   cmd = "version";
148   r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
149   ASSERT_TRUE(r == -22 || r == -ENXIO);
150   cmd = "{\"prefix\":\"version\"}";
151   r = cluster.osd_command(0, cmd, inbl, &outbl, &outs);
152   ASSERT_TRUE((r == 0 && outbl.length() > 0) || (r == -ENXIO && outbl.length() == 0));
153   cluster.shutdown();
154 }
155
156 TEST(LibRadosCmd, PGCmd) {
157   rados_t cluster;
158   std::string pool_name = get_temp_pool_name();
159   ASSERT_EQ("", create_one_pool(pool_name, &cluster));
160
161   char *buf, *st;
162   size_t buflen, stlen;
163   char *cmd[2];
164   cmd[1] = NULL;
165
166   int64_t poolid = rados_pool_lookup(cluster, pool_name.c_str());
167   ASSERT_LT(0, poolid);
168
169   string pgid = stringify(poolid) + ".0";
170
171   cmd[0] = (char *)"asdfasdf";
172   // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
173   int r = rados_pg_command(cluster, pgid.c_str(), (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen);
174   ASSERT_TRUE(r == -22 || r == -ENXIO);
175   rados_buffer_free(buf);
176   rados_buffer_free(st);
177
178   // make sure the pg exists on the osd before we query it
179   rados_ioctx_t io;
180   rados_ioctx_create(cluster, pool_name.c_str(), &io);
181   for (int i=0; i<100; i++) {
182     string oid = "obj" + stringify(i);
183     ASSERT_EQ(-ENOENT, rados_stat(io, oid.c_str(), NULL, NULL));
184   }
185   rados_ioctx_destroy(io);
186
187   string qstr = "{\"prefix\":\"pg\", \"cmd\":\"query\", \"pgid\":\"" +  pgid + "\"}";
188   cmd[0] = (char *)qstr.c_str();
189   // note: tolerate ENOENT/ENXIO here if hte osd is thrashing out underneath us
190   r = rados_pg_command(cluster, pgid.c_str(), (const char **)cmd, 1, "", 0,  &buf, &buflen, &st, &stlen);
191   ASSERT_TRUE(r == 0 || r == -ENOENT || r == -ENXIO);
192
193   ASSERT_LT(0u, buflen);
194   rados_buffer_free(buf);
195   rados_buffer_free(st);
196
197   ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
198 }
199
200 TEST(LibRadosCmd, PGCmdPP) {
201   Rados cluster;
202   std::string pool_name = get_temp_pool_name();
203   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
204
205   int r;
206   bufferlist inbl, outbl;
207   string outs;
208   string cmd;
209
210   int64_t poolid = cluster.pool_lookup(pool_name.c_str());
211   ASSERT_LT(0, poolid);
212
213   string pgid = stringify(poolid) + ".0";
214
215   cmd = "asdfasdf";
216   // note: tolerate NXIO here in case the cluster is thrashing out underneath us.
217   r = cluster.pg_command(pgid.c_str(), cmd, inbl, &outbl, &outs);
218   ASSERT_TRUE(r == -22 || r == -ENXIO);
219
220   // make sure the pg exists on the osd before we query it
221   IoCtx io;
222   cluster.ioctx_create(pool_name.c_str(), io);
223   for (int i=0; i<100; i++) {
224     string oid = "obj" + stringify(i);
225     ASSERT_EQ(-ENOENT, io.stat(oid, NULL, NULL));
226   }
227   io.close();
228
229   cmd = "{\"prefix\":\"pg\", \"cmd\":\"query\", \"pgid\":\"" +  pgid + "\"}";
230   // note: tolerate ENOENT/ENXIO here if hte osd is thrashing out underneath us
231   r = cluster.pg_command(pgid.c_str(), cmd, inbl, &outbl, &outs);
232   ASSERT_TRUE(r == 0 || r == -ENOENT || r == -ENXIO);
233
234   ASSERT_LT(0u, outbl.length());
235
236   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
237 }
238
239 struct Log {
240   list<string> log;
241   Cond cond;
242   Mutex lock;
243
244   Log() : lock("l::lock") {}
245
246   bool contains(string str) {
247     Mutex::Locker l(lock);
248     for (list<string>::iterator p = log.begin(); p != log.end(); ++p) {
249       if (p->find(str) != std::string::npos)
250         return true;
251     }
252     return false;
253   }
254 };
255
256 void log_cb(void *arg,
257              const char *line,
258              const char *who, uint64_t stampsec, uint64_t stamp_nsec,
259              uint64_t seq, const char *level,
260              const char *msg) {
261   Log *l = static_cast<Log *>(arg);
262   Mutex::Locker locker(l->lock);
263   l->log.push_back(line);
264   l->cond.Signal();
265   cout << "got: " << line << std::endl;
266 }
267
268 TEST(LibRadosCmd, WatchLog) {
269   rados_t cluster;
270   ASSERT_EQ("", connect_cluster(&cluster));
271   char *buf, *st;
272   char *cmd[2];
273   cmd[1] = NULL;
274   size_t buflen, stlen;
275   Log l;
276
277   ASSERT_EQ(0, rados_monitor_log(cluster, "info", log_cb, &l));
278   cmd[0] = (char *)"{\"prefix\":\"log\", \"logtext\":[\"onexx\"]}";
279   ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
280   for (int i=0; !l.contains("onexx"); i++) {
281     ASSERT_TRUE(i<100);
282     sleep(1);
283   }
284   ASSERT_TRUE(l.contains("onexx"));
285
286   cmd[0] = (char *)"{\"prefix\":\"log\", \"logtext\":[\"twoxx\"]}";
287   ASSERT_EQ(0, rados_monitor_log(cluster, "err", log_cb, &l));
288   ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
289   sleep(2);
290   ASSERT_FALSE(l.contains("twoxx"));
291
292   ASSERT_EQ(0, rados_monitor_log(cluster, "info", log_cb, &l));
293   cmd[0] = (char *)"{\"prefix\":\"log\", \"logtext\":[\"threexx\"]}";
294   ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
295   for (int i=0; !l.contains("threexx"); i++) {
296     ASSERT_TRUE(i<100);
297     sleep(1);
298   }
299
300   ASSERT_EQ(0, rados_monitor_log(cluster, "info", NULL, NULL));
301   cmd[0] = (char *)"{\"prefix\":\"log\", \"logtext\":[\"fourxx\"]}";
302   ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
303   sleep(2);
304   ASSERT_FALSE(l.contains("fourxx"));
305   rados_shutdown(cluster);
306 }