]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/librados/test.cc
update sources to v12.1.1
[ceph.git] / ceph / src / test / librados / test.cc
CommitLineData
7c673cae
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 "include/rados/librados.h"
5#include "include/rados/librados.hpp"
6#include "test/librados/test.h"
7
8#include "include/stringify.h"
7c673cae
FG
9#include "common/ceph_context.h"
10#include "common/config.h"
11
12#include <errno.h>
13#include <sstream>
14#include <stdlib.h>
15#include <string>
16#include <time.h>
17#include <unistd.h>
18#include <iostream>
19#include "gtest/gtest.h"
20
21using namespace librados;
22
23std::string get_temp_pool_name(const std::string &prefix)
24{
25 char hostname[80];
26 char out[160];
27 memset(hostname, 0, sizeof(hostname));
28 memset(out, 0, sizeof(out));
29 gethostname(hostname, sizeof(hostname)-1);
30 static int num = 1;
31 snprintf(out, sizeof(out), "%s-%d-%d", hostname, getpid(), num);
32 num++;
33 return prefix + out;
34}
35
7c673cae
FG
36
37std::string create_one_pool(
38 const std::string &pool_name, rados_t *cluster, uint32_t pg_num)
39{
40 std::string err_str = connect_cluster(cluster);
41 if (err_str.length())
42 return err_str;
43
44 int ret = rados_pool_create(*cluster, pool_name.c_str());
45 if (ret) {
46 rados_shutdown(*cluster);
47 std::ostringstream oss;
48 oss << "create_one_pool(" << pool_name << ") failed with error " << ret;
49 return oss.str();
50 }
51
52 return "";
53}
54
55int destroy_ec_profile(rados_t *cluster,
56 const std::string& pool_name,
57 std::ostream &oss)
58{
59 char buf[1000];
60 snprintf(buf, sizeof(buf),
61 "{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile-%s\"}",
62 pool_name.c_str());
63 char *cmd[2];
64 cmd[0] = buf;
65 cmd[1] = NULL;
66 int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL,
67 0, NULL, 0);
68 if (ret)
69 oss << "rados_mon_command: erasure-code-profile rm testprofile-"
70 << pool_name << " failed with error " << ret;
71 return ret;
72}
73
74int destroy_ruleset(rados_t *cluster,
75 std::string ruleset,
76 std::ostream &oss)
77{
78 char *cmd[2];
79 std::string tmp = ("{\"prefix\": \"osd crush rule rm\", \"name\":\"" +
80 ruleset + "\"}");
81 cmd[0] = (char*)tmp.c_str();
82 cmd[1] = NULL;
83 int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0);
84 if (ret)
85 oss << "rados_mon_command: osd crush rule rm " + ruleset + " failed with error " << ret;
86 return ret;
87}
88
89int destroy_ec_profile_and_ruleset(rados_t *cluster,
90 std::string ruleset,
91 std::ostream &oss)
92{
93 int ret;
94 ret = destroy_ec_profile(cluster, ruleset, oss);
95 if (ret)
96 return ret;
97 return destroy_ruleset(cluster, ruleset, oss);
98}
99
7c673cae
FG
100
101std::string create_one_ec_pool(const std::string &pool_name, rados_t *cluster)
102{
103 std::string err = connect_cluster(cluster);
104 if (err.length())
105 return err;
106
107 std::ostringstream oss;
108 int ret = destroy_ec_profile_and_ruleset(cluster, pool_name, oss);
109 if (ret) {
110 rados_shutdown(*cluster);
111 return oss.str();
112 }
113
114 char *cmd[2];
115 cmd[1] = NULL;
116
224ce89b 117 std::string profile_create = "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile-" + pool_name + "\", \"profile\": [ \"k=2\", \"m=1\", \"crush-failure-domain=osd\"]}";
7c673cae
FG
118 cmd[0] = (char *)profile_create.c_str();
119 ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0);
120 if (ret) {
121 rados_shutdown(*cluster);
122 oss << "rados_mon_command erasure-code-profile set name:testprofile-" << pool_name << " failed with error " << ret;
123 return oss.str();
124 }
125
126 std::string cmdstr = "{\"prefix\": \"osd pool create\", \"pool\": \"" +
127 pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":8, \"pgp_num\":8, \"erasure_code_profile\":\"testprofile-" + pool_name + "\"}";
128 cmd[0] = (char *)cmdstr.c_str();
129 ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0);
130 if (ret) {
131 destroy_ec_profile(cluster, pool_name, oss);
132 rados_shutdown(*cluster);
133 oss << "rados_mon_command osd pool create failed with error " << ret;
134 return oss.str();
135 }
136
137 rados_wait_for_latest_osdmap(*cluster);
138 return "";
139}
140
141std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster)
142{
143 return create_one_pool_pp(pool_name, cluster, {});
144}
145std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster,
146 const std::map<std::string, std::string> &config)
147{
148 std::string err = connect_cluster_pp(cluster, config);
149 if (err.length())
150 return err;
151 int ret = cluster.pool_create(pool_name.c_str());
152 if (ret) {
153 cluster.shutdown();
154 std::ostringstream oss;
155 oss << "cluster.pool_create(" << pool_name << ") failed with error " << ret;
156 return oss.str();
157 }
158 return "";
159}
160
161int destroy_ruleset_pp(Rados &cluster,
162 std::string ruleset,
163 std::ostream &oss)
164{
165 bufferlist inbl;
166 int ret = cluster.mon_command("{\"prefix\": \"osd crush rule rm\", \"name\":\"" +
167 ruleset + "\"}", inbl, NULL, NULL);
168 if (ret)
169 oss << "mon_command: osd crush rule rm " + ruleset + " failed with error " << ret << std::endl;
170 return ret;
171}
172
173int destroy_ec_profile_pp(Rados &cluster, const std::string& pool_name,
174 std::ostream &oss)
175{
176 bufferlist inbl;
177 int ret = cluster.mon_command("{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile-" + pool_name + "\"}",
178 inbl, NULL, NULL);
179 if (ret)
180 oss << "mon_command: osd erasure-code-profile rm testprofile-" << pool_name << " failed with error " << ret << std::endl;
181 return ret;
182}
183
184int destroy_ec_profile_and_ruleset_pp(Rados &cluster,
185 std::string ruleset,
186 std::ostream &oss)
187{
188 int ret;
189 ret = destroy_ec_profile_pp(cluster, ruleset, oss);
190 if (ret)
191 return ret;
192 return destroy_ruleset_pp(cluster, ruleset, oss);
193}
194
195std::string create_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
196{
197 std::string err = connect_cluster_pp(cluster);
198 if (err.length())
199 return err;
200
201 std::ostringstream oss;
202 int ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss);
203 if (ret) {
204 cluster.shutdown();
205 return oss.str();
206 }
207
208 bufferlist inbl;
209 ret = cluster.mon_command(
224ce89b 210 "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile-" + pool_name + "\", \"profile\": [ \"k=2\", \"m=1\", \"crush-failure-domain=osd\"]}",
7c673cae
FG
211 inbl, NULL, NULL);
212 if (ret) {
213 cluster.shutdown();
214 oss << "mon_command erasure-code-profile set name:testprofile-" << pool_name << " failed with error " << ret;
215 return oss.str();
216 }
217
218 ret = cluster.mon_command(
219 "{\"prefix\": \"osd pool create\", \"pool\": \"" + pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":8, \"pgp_num\":8, \"erasure_code_profile\":\"testprofile-" + pool_name + "\"}",
220 inbl, NULL, NULL);
221 if (ret) {
222 bufferlist inbl;
223 destroy_ec_profile_pp(cluster, pool_name, oss);
224 cluster.shutdown();
225 oss << "mon_command osd pool create pool:" << pool_name << " pool_type:erasure failed with error " << ret;
226 return oss.str();
227 }
228
229 cluster.wait_for_latest_osdmap();
230 return "";
231}
232
233std::string connect_cluster(rados_t *cluster)
234{
235 char *id = getenv("CEPH_CLIENT_ID");
236 if (id) std::cerr << "Client id is: " << id << std::endl;
237
238 int ret;
239 ret = rados_create(cluster, NULL);
240 if (ret) {
241 std::ostringstream oss;
242 oss << "rados_create failed with error " << ret;
243 return oss.str();
244 }
245 ret = rados_conf_read_file(*cluster, NULL);
246 if (ret) {
247 rados_shutdown(*cluster);
248 std::ostringstream oss;
249 oss << "rados_conf_read_file failed with error " << ret;
250 return oss.str();
251 }
252 rados_conf_parse_env(*cluster, NULL);
253 ret = rados_connect(*cluster);
254 if (ret) {
255 rados_shutdown(*cluster);
256 std::ostringstream oss;
257 oss << "rados_connect failed with error " << ret;
258 return oss.str();
259 }
260 return "";
261}
262
263std::string connect_cluster_pp(librados::Rados &cluster)
264{
265 return connect_cluster_pp(cluster, {});
266}
267
268std::string connect_cluster_pp(librados::Rados &cluster,
269 const std::map<std::string, std::string> &config)
270{
271 char *id = getenv("CEPH_CLIENT_ID");
272 if (id) std::cerr << "Client id is: " << id << std::endl;
273
274 int ret;
275 ret = cluster.init(id);
276 if (ret) {
277 std::ostringstream oss;
278 oss << "cluster.init failed with error " << ret;
279 return oss.str();
280 }
281 ret = cluster.conf_read_file(NULL);
282 if (ret) {
283 cluster.shutdown();
284 std::ostringstream oss;
285 oss << "cluster.conf_read_file failed with error " << ret;
286 return oss.str();
287 }
288 cluster.conf_parse_env(NULL);
289
290 for (auto &setting : config) {
291 ret = cluster.conf_set(setting.first.c_str(), setting.second.c_str());
292 if (ret) {
293 std::ostringstream oss;
294 oss << "failed to set config value " << setting.first << " to '"
31f18b77 295 << setting.second << "': " << strerror(-ret);
7c673cae
FG
296 return oss.str();
297 }
298 }
299
300 ret = cluster.connect();
301 if (ret) {
302 cluster.shutdown();
303 std::ostringstream oss;
304 oss << "cluster.connect failed with error " << ret;
305 return oss.str();
306 }
307 return "";
308}
309
310int destroy_one_pool(const std::string &pool_name, rados_t *cluster)
311{
312 int ret = rados_pool_delete(*cluster, pool_name.c_str());
313 if (ret) {
314 rados_shutdown(*cluster);
315 return ret;
316 }
317 rados_shutdown(*cluster);
318 return 0;
319}
320
321int destroy_one_ec_pool(const std::string &pool_name, rados_t *cluster)
322{
323 int ret = rados_pool_delete(*cluster, pool_name.c_str());
324 if (ret) {
325 rados_shutdown(*cluster);
326 return ret;
327 }
328
329 CephContext *cct = static_cast<CephContext*>(rados_cct(*cluster));
330 if (!cct->_conf->mon_fake_pool_delete) { // hope this is in [global]
331 std::ostringstream oss;
332 ret = destroy_ec_profile_and_ruleset(cluster, pool_name, oss);
333 if (ret) {
334 rados_shutdown(*cluster);
335 return ret;
336 }
337 }
338
339 rados_wait_for_latest_osdmap(*cluster);
340 rados_shutdown(*cluster);
341 return ret;
342}
343
344int destroy_one_pool_pp(const std::string &pool_name, Rados &cluster)
345{
346 int ret = cluster.pool_delete(pool_name.c_str());
347 if (ret) {
348 cluster.shutdown();
349 return ret;
350 }
351 cluster.shutdown();
352 return 0;
353}
354
355int destroy_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
356{
357 int ret = cluster.pool_delete(pool_name.c_str());
358 if (ret) {
359 cluster.shutdown();
360 return ret;
361 }
362
363 CephContext *cct = static_cast<CephContext*>(cluster.cct());
364 if (!cct->_conf->mon_fake_pool_delete) { // hope this is in [global]
365 std::ostringstream oss;
366 ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss);
367 if (ret) {
368 cluster.shutdown();
369 return ret;
370 }
371 }
372
373 cluster.wait_for_latest_osdmap();
374 cluster.shutdown();
375 return ret;
376}
377
378void assert_eq_sparse(bufferlist& expected,
379 const std::map<uint64_t, uint64_t>& extents,
380 bufferlist& actual) {
381 auto i = expected.begin();
382 auto p = actual.begin();
383 uint64_t pos = 0;
384 for (auto extent : extents) {
385 const uint64_t start = extent.first;
386 const uint64_t end = start + extent.second;
387 for (; pos < end; ++i, ++pos) {
388 ASSERT_FALSE(i.end());
389 if (pos < start) {
390 // check the hole
391 ASSERT_EQ('\0', *i);
392 } else {
393 // then the extent
394 ASSERT_EQ(*i, *p);
395 ++p;
396 }
397 }
398 }
399 ASSERT_EQ(expected.length(), pos);
400}