]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados/test_common.cc
update sources to 12.2.7
[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
9namespace {
10
11using namespace ceph;
12
13int 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
77int 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
28e407b8
AA
104struct pool_op_error : std::exception {
105 string msg;
106 pool_op_error(const std::string& pool_name,
107 const std::string& func_name,
108 int err) {
109 std::ostringstream oss;
110 oss << func_name << "(" << pool_name << ") failed with error " << err;
111 msg = oss.str();
31f18b77 112 }
28e407b8
AA
113 const char* what() const noexcept override {
114 return msg.c_str();
31f18b77 115 }
28e407b8 116};
31f18b77 117
28e407b8
AA
118template<typename Func>
119std::string with_healthy_cluster(rados_t* cluster,
120 const std::string& pool_name,
121 Func&& func)
122{
123 try {
124 // Wait for 'creating/backfilling' to clear
125 int r = wait_for_healthy(cluster);
126 if (r != 0) {
127 throw pool_op_error{pool_name, "wait_for_healthy", r};
128 }
129 func();
130 // Wait for 'creating/backfilling' to clear
131 r = wait_for_healthy(cluster);
132 if (r != 0) {
133 throw pool_op_error{pool_name, "wait_for_healthy", r};
134 }
135 } catch (const pool_op_error& e) {
136 rados_shutdown(*cluster);
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
148 int r = rados_pool_set(cluster, pool_name, "pg_num",
149 stringify(pg_num));
150 if (r != 0) {
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
161 int r = rados_pool_set(cluster, pool_name, "pgp_num",
162 stringify(pgp_num));
163 if (r != 0) {
164 throw pool_op_error{pool_name, "set_pgp_num", r};
165 }
166 });
31f18b77 167}