Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / librados / test_common.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 "common/Formatter.h"
5 #include "include/stringify.h"
6 #include "json_spirit/json_spirit.h"
7 #include "test_common.h"
8
9 namespace {
10
11 using namespace ceph;
12
13 int wait_for_healthy(rados_t *cluster)
14 {
15   bool healthy = false;
16   // This timeout is very long because the tests are sometimes
17   // run on a thrashing cluster
18   int timeout = 3600;
19   int slept = 0;
20
21   while(!healthy) {
22     JSONFormatter cmd_f;
23     cmd_f.open_object_section("command");
24     cmd_f.dump_string("prefix", "status");
25     cmd_f.dump_string("format", "json");
26     cmd_f.close_section();
27     std::ostringstream cmd_stream;
28     cmd_f.flush(cmd_stream);
29     const std::string serialized_cmd = cmd_stream.str();
30
31     const char *cmd[2];
32     cmd[1] = NULL;
33     cmd[0] = serialized_cmd.c_str();
34
35     char *outbuf = NULL;
36     size_t outlen = 0;
37     int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0,
38         &outbuf, &outlen, NULL, NULL);
39     if (ret) {
40       return ret;
41     }
42
43     std::string out(outbuf, outlen);
44     rados_buffer_free(outbuf);
45
46     json_spirit::mValue root;
47     assert(json_spirit::read(out, root));
48     json_spirit::mObject root_obj = root.get_obj();
49     json_spirit::mObject pgmap = root_obj["pgmap"].get_obj();
50     json_spirit::mArray pgs_by_state = pgmap["pgs_by_state"].get_array();
51
52     if (pgs_by_state.size() == 1) {
53       json_spirit::mObject state = pgs_by_state[0].get_obj();
54       std::string state_name = state["state_name"].get_str();
55       if (state_name != std::string("active+clean")) {
56         healthy = false;
57       } else {
58         healthy = true;
59       }
60     } else {
61       healthy = false;
62     }
63
64     if (slept >= timeout) {
65       return -ETIMEDOUT;
66     };
67
68     if (!healthy) {
69       sleep(1);
70       slept += 1;
71     }
72   }
73
74   return 0;
75 }
76
77 int rados_pool_set(
78     rados_t *cluster,
79     const std::string &pool_name,
80     const std::string &var,
81     const std::string &val)
82 {
83   JSONFormatter cmd_f;
84   cmd_f.open_object_section("command");
85   cmd_f.dump_string("prefix", "osd pool set");
86   cmd_f.dump_string("pool", pool_name);
87   cmd_f.dump_string("var", var);
88   cmd_f.dump_string("val", val);
89   cmd_f.close_section();
90
91   std::ostringstream cmd_stream;
92   cmd_f.flush(cmd_stream);
93
94   const std::string serialized_cmd = cmd_stream.str();
95
96   const char *cmd[2];
97   cmd[1] = NULL;
98   cmd[0] = serialized_cmd.c_str();
99   int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL,
100       NULL, NULL, NULL);
101   return ret;
102 }
103
104 }
105
106 std::string set_pg_num(
107     rados_t *cluster, const std::string &pool_name, uint32_t pg_num)
108 {
109   // Wait for 'creating' to clear
110   int r = wait_for_healthy(cluster);
111   if (r != 0) {
112     goto err;
113   }
114
115   // Adjust pg_num
116   r = rados_pool_set(cluster, pool_name, "pg_num", stringify(pg_num));
117   if (r != 0) {
118     goto err;
119   }
120
121   // Wait for 'creating' to clear
122   r = wait_for_healthy(cluster);
123   if (r != 0) {
124     goto err;
125   }
126
127   return "";
128
129 err:
130   rados_shutdown(*cluster);
131   std::ostringstream oss;
132   oss << __func__ << "(" << pool_name << ") failed with error " << r;
133   return oss.str();
134 }