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