1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*
2 // vim: ts=8 sw=2 smarttab
4 #include "include/rados/librados.h"
5 #include "include/rados/librados.hpp"
6 #include "test/librados/test.h"
8 #include "include/stringify.h"
9 #include "common/ceph_context.h"
10 #include "common/config.h"
19 #include "gtest/gtest.h"
21 using namespace librados;
23 std::string get_temp_pool_name(const std::string &prefix)
27 memset(hostname, 0, sizeof(hostname));
28 memset(out, 0, sizeof(out));
29 gethostname(hostname, sizeof(hostname)-1);
31 snprintf(out, sizeof(out), "%s-%d-%d", hostname, getpid(), num);
37 std::string create_one_pool(
38 const std::string &pool_name, rados_t *cluster, uint32_t pg_num)
40 std::string err_str = connect_cluster(cluster);
44 int ret = rados_pool_create(*cluster, pool_name.c_str());
46 rados_shutdown(*cluster);
47 std::ostringstream oss;
48 oss << "create_one_pool(" << pool_name << ") failed with error " << ret;
53 ret = rados_ioctx_create(*cluster, pool_name.c_str(), &ioctx);
55 rados_shutdown(*cluster);
56 std::ostringstream oss;
57 oss << "rados_ioctx_create(" << pool_name << ") failed with error " << ret;
61 rados_application_enable(ioctx, "rados", 1);
62 rados_ioctx_destroy(ioctx);
66 int destroy_ec_profile(rados_t *cluster,
67 const std::string& pool_name,
71 snprintf(buf, sizeof(buf),
72 "{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile-%s\"}",
77 int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL,
80 oss << "rados_mon_command: erasure-code-profile rm testprofile-"
81 << pool_name << " failed with error " << ret;
85 int destroy_ruleset(rados_t *cluster,
90 std::string tmp = ("{\"prefix\": \"osd crush rule rm\", \"name\":\"" +
92 cmd[0] = (char*)tmp.c_str();
94 int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0);
96 oss << "rados_mon_command: osd crush rule rm " + ruleset + " failed with error " << ret;
100 int destroy_ec_profile_and_ruleset(rados_t *cluster,
105 ret = destroy_ec_profile(cluster, ruleset, oss);
108 return destroy_ruleset(cluster, ruleset, oss);
112 std::string create_one_ec_pool(const std::string &pool_name, rados_t *cluster)
114 std::string err = connect_cluster(cluster);
118 std::ostringstream oss;
119 int ret = destroy_ec_profile_and_ruleset(cluster, pool_name, oss);
121 rados_shutdown(*cluster);
128 std::string profile_create = "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile-" + pool_name + "\", \"profile\": [ \"k=2\", \"m=1\", \"crush-failure-domain=osd\"]}";
129 cmd[0] = (char *)profile_create.c_str();
130 ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0);
132 rados_shutdown(*cluster);
133 oss << "rados_mon_command erasure-code-profile set name:testprofile-" << pool_name << " failed with error " << ret;
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);
142 destroy_ec_profile(cluster, pool_name, oss);
143 rados_shutdown(*cluster);
144 oss << "rados_mon_command osd pool create failed with error " << ret;
148 rados_wait_for_latest_osdmap(*cluster);
152 std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster)
154 return create_one_pool_pp(pool_name, cluster, {});
156 std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster,
157 const std::map<std::string, std::string> &config)
159 std::string err = connect_cluster_pp(cluster, config);
162 int ret = cluster.pool_create(pool_name.c_str());
165 std::ostringstream oss;
166 oss << "cluster.pool_create(" << pool_name << ") failed with error " << ret;
171 ret = cluster.ioctx_create(pool_name.c_str(), ioctx);
174 std::ostringstream oss;
175 oss << "cluster.ioctx_create(" << pool_name << ") failed with error "
179 ioctx.application_enable("rados", true);
183 int destroy_ruleset_pp(Rados &cluster,
188 int ret = cluster.mon_command("{\"prefix\": \"osd crush rule rm\", \"name\":\"" +
189 ruleset + "\"}", inbl, NULL, NULL);
191 oss << "mon_command: osd crush rule rm " + ruleset + " failed with error " << ret << std::endl;
195 int destroy_ec_profile_pp(Rados &cluster, const std::string& pool_name,
199 int ret = cluster.mon_command("{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile-" + pool_name + "\"}",
202 oss << "mon_command: osd erasure-code-profile rm testprofile-" << pool_name << " failed with error " << ret << std::endl;
206 int destroy_ec_profile_and_ruleset_pp(Rados &cluster,
211 ret = destroy_ec_profile_pp(cluster, ruleset, oss);
214 return destroy_ruleset_pp(cluster, ruleset, oss);
217 std::string create_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
219 std::string err = connect_cluster_pp(cluster);
223 std::ostringstream oss;
224 int ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss);
231 ret = cluster.mon_command(
232 "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile-" + pool_name + "\", \"profile\": [ \"k=2\", \"m=1\", \"crush-failure-domain=osd\"]}",
236 oss << "mon_command erasure-code-profile set name:testprofile-" << pool_name << " failed with error " << ret;
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 + "\"}",
245 destroy_ec_profile_pp(cluster, pool_name, oss);
247 oss << "mon_command osd pool create pool:" << pool_name << " pool_type:erasure failed with error " << ret;
251 cluster.wait_for_latest_osdmap();
255 std::string connect_cluster(rados_t *cluster)
257 char *id = getenv("CEPH_CLIENT_ID");
258 if (id) std::cerr << "Client id is: " << id << std::endl;
261 ret = rados_create(cluster, NULL);
263 std::ostringstream oss;
264 oss << "rados_create failed with error " << ret;
267 ret = rados_conf_read_file(*cluster, NULL);
269 rados_shutdown(*cluster);
270 std::ostringstream oss;
271 oss << "rados_conf_read_file failed with error " << ret;
274 rados_conf_parse_env(*cluster, NULL);
275 ret = rados_connect(*cluster);
277 rados_shutdown(*cluster);
278 std::ostringstream oss;
279 oss << "rados_connect failed with error " << ret;
285 std::string connect_cluster_pp(librados::Rados &cluster)
287 return connect_cluster_pp(cluster, {});
290 std::string connect_cluster_pp(librados::Rados &cluster,
291 const std::map<std::string, std::string> &config)
293 char *id = getenv("CEPH_CLIENT_ID");
294 if (id) std::cerr << "Client id is: " << id << std::endl;
297 ret = cluster.init(id);
299 std::ostringstream oss;
300 oss << "cluster.init failed with error " << ret;
303 ret = cluster.conf_read_file(NULL);
306 std::ostringstream oss;
307 oss << "cluster.conf_read_file failed with error " << ret;
310 cluster.conf_parse_env(NULL);
312 for (auto &setting : config) {
313 ret = cluster.conf_set(setting.first.c_str(), setting.second.c_str());
315 std::ostringstream oss;
316 oss << "failed to set config value " << setting.first << " to '"
317 << setting.second << "': " << strerror(-ret);
322 ret = cluster.connect();
325 std::ostringstream oss;
326 oss << "cluster.connect failed with error " << ret;
332 int destroy_one_pool(const std::string &pool_name, rados_t *cluster)
334 int ret = rados_pool_delete(*cluster, pool_name.c_str());
336 rados_shutdown(*cluster);
339 rados_shutdown(*cluster);
343 int destroy_one_ec_pool(const std::string &pool_name, rados_t *cluster)
345 int ret = rados_pool_delete(*cluster, pool_name.c_str());
347 rados_shutdown(*cluster);
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);
356 rados_shutdown(*cluster);
361 rados_wait_for_latest_osdmap(*cluster);
362 rados_shutdown(*cluster);
366 int destroy_one_pool_pp(const std::string &pool_name, Rados &cluster)
368 int ret = cluster.pool_delete(pool_name.c_str());
377 int destroy_one_ec_pool_pp(const std::string &pool_name, Rados &cluster)
379 int ret = cluster.pool_delete(pool_name.c_str());
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);
395 cluster.wait_for_latest_osdmap();
400 void 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();
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());
421 ASSERT_EQ(expected.length(), pos);