]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados/test_common.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / librados / test_common.cc
CommitLineData
31f18b77
FG
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
20effc67
TL
9using namespace std;
10
31f18b77
FG
11namespace {
12
13using namespace ceph;
14
15int wait_for_healthy(rados_t *cluster)
16{
17 bool healthy = false;
18 // This timeout is very long because the tests are sometimes
19 // run on a thrashing cluster
20 int timeout = 3600;
21 int slept = 0;
22
23 while(!healthy) {
24 JSONFormatter cmd_f;
25 cmd_f.open_object_section("command");
26 cmd_f.dump_string("prefix", "status");
27 cmd_f.dump_string("format", "json");
28 cmd_f.close_section();
29 std::ostringstream cmd_stream;
30 cmd_f.flush(cmd_stream);
31 const std::string serialized_cmd = cmd_stream.str();
32
33 const char *cmd[2];
34 cmd[1] = NULL;
35 cmd[0] = serialized_cmd.c_str();
36
37 char *outbuf = NULL;
38 size_t outlen = 0;
39 int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0,
40 &outbuf, &outlen, NULL, NULL);
41 if (ret) {
42 return ret;
43 }
44
45 std::string out(outbuf, outlen);
46 rados_buffer_free(outbuf);
47
48 json_spirit::mValue root;
11fdf7f2
TL
49 [[maybe_unused]] bool json_parse_success = json_spirit::read(out, root);
50 ceph_assert(json_parse_success);
31f18b77
FG
51 json_spirit::mObject root_obj = root.get_obj();
52 json_spirit::mObject pgmap = root_obj["pgmap"].get_obj();
53 json_spirit::mArray pgs_by_state = pgmap["pgs_by_state"].get_array();
54
55 if (pgs_by_state.size() == 1) {
56 json_spirit::mObject state = pgs_by_state[0].get_obj();
57 std::string state_name = state["state_name"].get_str();
58 if (state_name != std::string("active+clean")) {
59 healthy = false;
60 } else {
61 healthy = true;
62 }
63 } else {
64 healthy = false;
65 }
66
67 if (slept >= timeout) {
68 return -ETIMEDOUT;
69 };
70
71 if (!healthy) {
72 sleep(1);
73 slept += 1;
74 }
75 }
76
77 return 0;
78}
79
80int rados_pool_set(
81 rados_t *cluster,
82 const std::string &pool_name,
83 const std::string &var,
84 const std::string &val)
85{
86 JSONFormatter cmd_f;
87 cmd_f.open_object_section("command");
88 cmd_f.dump_string("prefix", "osd pool set");
89 cmd_f.dump_string("pool", pool_name);
90 cmd_f.dump_string("var", var);
91 cmd_f.dump_string("val", val);
92 cmd_f.close_section();
93
94 std::ostringstream cmd_stream;
95 cmd_f.flush(cmd_stream);
96
97 const std::string serialized_cmd = cmd_stream.str();
98
99 const char *cmd[2];
100 cmd[1] = NULL;
101 cmd[0] = serialized_cmd.c_str();
102 int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL,
103 NULL, NULL, NULL);
104 return ret;
105}
106
28e407b8
AA
107struct pool_op_error : std::exception {
108 string msg;
109 pool_op_error(const std::string& pool_name,
110 const std::string& func_name,
111 int err) {
112 std::ostringstream oss;
113 oss << func_name << "(" << pool_name << ") failed with error " << err;
114 msg = oss.str();
31f18b77 115 }
28e407b8
AA
116 const char* what() const noexcept override {
117 return msg.c_str();
31f18b77 118 }
28e407b8 119};
31f18b77 120
28e407b8
AA
121template<typename Func>
122std::string with_healthy_cluster(rados_t* cluster,
123 const std::string& pool_name,
124 Func&& func)
125{
126 try {
127 // Wait for 'creating/backfilling' to clear
11fdf7f2 128 if (int r = wait_for_healthy(cluster); r != 0) {
28e407b8
AA
129 throw pool_op_error{pool_name, "wait_for_healthy", r};
130 }
131 func();
132 // Wait for 'creating/backfilling' to clear
11fdf7f2 133 if (int r = wait_for_healthy(cluster); r != 0) {
28e407b8
AA
134 throw pool_op_error{pool_name, "wait_for_healthy", r};
135 }
136 } catch (const pool_op_error& e) {
28e407b8 137 return e.what();
31f18b77 138 }
31f18b77 139 return "";
28e407b8
AA
140}
141}
142
143std::string set_pg_num(
144 rados_t *cluster, const std::string &pool_name, uint32_t pg_num)
145{
146 return with_healthy_cluster(cluster, pool_name, [&] {
147 // Adjust pg_num
11fdf7f2
TL
148 if (int r = rados_pool_set(cluster, pool_name, "pg_num",
149 stringify(pg_num));
150 r != 0) {
28e407b8
AA
151 throw pool_op_error{pool_name, "set_pg_num", r};
152 }
153 });
154}
31f18b77 155
28e407b8
AA
156std::string set_pgp_num(
157 rados_t *cluster, const std::string &pool_name, uint32_t pgp_num)
158{
159 return with_healthy_cluster(cluster, pool_name, [&] {
160 // Adjust pgp_num
11fdf7f2
TL
161 if (int r = rados_pool_set(cluster, pool_name, "pgp_num",
162 stringify(pgp_num));
163 r != 0) {
28e407b8
AA
164 throw pool_op_error{pool_name, "set_pgp_num", r};
165 }
166 });
31f18b77 167}