X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Ftest%2Flibrados%2Ftest.cc;fp=src%2Fceph%2Fsrc%2Ftest%2Flibrados%2Ftest.cc;h=42269b074bf58666ade58bf3998fa824a7c8b172;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/test/librados/test.cc b/src/ceph/src/test/librados/test.cc new file mode 100644 index 0000000..42269b0 --- /dev/null +++ b/src/ceph/src/test/librados/test.cc @@ -0,0 +1,422 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -* +// vim: ts=8 sw=2 smarttab + +#include "include/rados/librados.h" +#include "include/rados/librados.hpp" +#include "test/librados/test.h" + +#include "include/stringify.h" +#include "common/ceph_context.h" +#include "common/config.h" + +#include +#include +#include +#include +#include +#include +#include +#include "gtest/gtest.h" + +using namespace librados; + +std::string get_temp_pool_name(const std::string &prefix) +{ + char hostname[80]; + char out[160]; + memset(hostname, 0, sizeof(hostname)); + memset(out, 0, sizeof(out)); + gethostname(hostname, sizeof(hostname)-1); + static int num = 1; + snprintf(out, sizeof(out), "%s-%d-%d", hostname, getpid(), num); + num++; + return prefix + out; +} + + +std::string create_one_pool( + const std::string &pool_name, rados_t *cluster, uint32_t pg_num) +{ + std::string err_str = connect_cluster(cluster); + if (err_str.length()) + return err_str; + + int ret = rados_pool_create(*cluster, pool_name.c_str()); + if (ret) { + rados_shutdown(*cluster); + std::ostringstream oss; + oss << "create_one_pool(" << pool_name << ") failed with error " << ret; + return oss.str(); + } + + rados_ioctx_t ioctx; + ret = rados_ioctx_create(*cluster, pool_name.c_str(), &ioctx); + if (ret < 0) { + rados_shutdown(*cluster); + std::ostringstream oss; + oss << "rados_ioctx_create(" << pool_name << ") failed with error " << ret; + return oss.str(); + } + + rados_application_enable(ioctx, "rados", 1); + rados_ioctx_destroy(ioctx); + return ""; +} + +int destroy_ec_profile(rados_t *cluster, + const std::string& pool_name, + std::ostream &oss) +{ + char buf[1000]; + snprintf(buf, sizeof(buf), + "{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile-%s\"}", + pool_name.c_str()); + char *cmd[2]; + cmd[0] = buf; + cmd[1] = NULL; + int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, + 0, NULL, 0); + if (ret) + oss << "rados_mon_command: erasure-code-profile rm testprofile-" + << pool_name << " failed with error " << ret; + return ret; +} + +int destroy_ruleset(rados_t *cluster, + std::string ruleset, + std::ostream &oss) +{ + char *cmd[2]; + std::string tmp = ("{\"prefix\": \"osd crush rule rm\", \"name\":\"" + + ruleset + "\"}"); + cmd[0] = (char*)tmp.c_str(); + cmd[1] = NULL; + int ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0); + if (ret) + oss << "rados_mon_command: osd crush rule rm " + ruleset + " failed with error " << ret; + return ret; +} + +int destroy_ec_profile_and_ruleset(rados_t *cluster, + std::string ruleset, + std::ostream &oss) +{ + int ret; + ret = destroy_ec_profile(cluster, ruleset, oss); + if (ret) + return ret; + return destroy_ruleset(cluster, ruleset, oss); +} + + +std::string create_one_ec_pool(const std::string &pool_name, rados_t *cluster) +{ + std::string err = connect_cluster(cluster); + if (err.length()) + return err; + + std::ostringstream oss; + int ret = destroy_ec_profile_and_ruleset(cluster, pool_name, oss); + if (ret) { + rados_shutdown(*cluster); + return oss.str(); + } + + char *cmd[2]; + cmd[1] = NULL; + + std::string profile_create = "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile-" + pool_name + "\", \"profile\": [ \"k=2\", \"m=1\", \"crush-failure-domain=osd\"]}"; + cmd[0] = (char *)profile_create.c_str(); + ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0); + if (ret) { + rados_shutdown(*cluster); + oss << "rados_mon_command erasure-code-profile set name:testprofile-" << pool_name << " failed with error " << ret; + return oss.str(); + } + + std::string cmdstr = "{\"prefix\": \"osd pool create\", \"pool\": \"" + + pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":8, \"pgp_num\":8, \"erasure_code_profile\":\"testprofile-" + pool_name + "\"}"; + cmd[0] = (char *)cmdstr.c_str(); + ret = rados_mon_command(*cluster, (const char **)cmd, 1, "", 0, NULL, 0, NULL, 0); + if (ret) { + destroy_ec_profile(cluster, pool_name, oss); + rados_shutdown(*cluster); + oss << "rados_mon_command osd pool create failed with error " << ret; + return oss.str(); + } + + rados_wait_for_latest_osdmap(*cluster); + return ""; +} + +std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster) +{ + return create_one_pool_pp(pool_name, cluster, {}); +} +std::string create_one_pool_pp(const std::string &pool_name, Rados &cluster, + const std::map &config) +{ + std::string err = connect_cluster_pp(cluster, config); + if (err.length()) + return err; + int ret = cluster.pool_create(pool_name.c_str()); + if (ret) { + cluster.shutdown(); + std::ostringstream oss; + oss << "cluster.pool_create(" << pool_name << ") failed with error " << ret; + return oss.str(); + } + + IoCtx ioctx; + ret = cluster.ioctx_create(pool_name.c_str(), ioctx); + if (ret < 0) { + cluster.shutdown(); + std::ostringstream oss; + oss << "cluster.ioctx_create(" << pool_name << ") failed with error " + << ret; + return oss.str(); + } + ioctx.application_enable("rados", true); + return ""; +} + +int destroy_ruleset_pp(Rados &cluster, + std::string ruleset, + std::ostream &oss) +{ + bufferlist inbl; + int ret = cluster.mon_command("{\"prefix\": \"osd crush rule rm\", \"name\":\"" + + ruleset + "\"}", inbl, NULL, NULL); + if (ret) + oss << "mon_command: osd crush rule rm " + ruleset + " failed with error " << ret << std::endl; + return ret; +} + +int destroy_ec_profile_pp(Rados &cluster, const std::string& pool_name, + std::ostream &oss) +{ + bufferlist inbl; + int ret = cluster.mon_command("{\"prefix\": \"osd erasure-code-profile rm\", \"name\": \"testprofile-" + pool_name + "\"}", + inbl, NULL, NULL); + if (ret) + oss << "mon_command: osd erasure-code-profile rm testprofile-" << pool_name << " failed with error " << ret << std::endl; + return ret; +} + +int destroy_ec_profile_and_ruleset_pp(Rados &cluster, + std::string ruleset, + std::ostream &oss) +{ + int ret; + ret = destroy_ec_profile_pp(cluster, ruleset, oss); + if (ret) + return ret; + return destroy_ruleset_pp(cluster, ruleset, oss); +} + +std::string create_one_ec_pool_pp(const std::string &pool_name, Rados &cluster) +{ + std::string err = connect_cluster_pp(cluster); + if (err.length()) + return err; + + std::ostringstream oss; + int ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss); + if (ret) { + cluster.shutdown(); + return oss.str(); + } + + bufferlist inbl; + ret = cluster.mon_command( + "{\"prefix\": \"osd erasure-code-profile set\", \"name\": \"testprofile-" + pool_name + "\", \"profile\": [ \"k=2\", \"m=1\", \"crush-failure-domain=osd\"]}", + inbl, NULL, NULL); + if (ret) { + cluster.shutdown(); + oss << "mon_command erasure-code-profile set name:testprofile-" << pool_name << " failed with error " << ret; + return oss.str(); + } + + ret = cluster.mon_command( + "{\"prefix\": \"osd pool create\", \"pool\": \"" + pool_name + "\", \"pool_type\":\"erasure\", \"pg_num\":8, \"pgp_num\":8, \"erasure_code_profile\":\"testprofile-" + pool_name + "\"}", + inbl, NULL, NULL); + if (ret) { + bufferlist inbl; + destroy_ec_profile_pp(cluster, pool_name, oss); + cluster.shutdown(); + oss << "mon_command osd pool create pool:" << pool_name << " pool_type:erasure failed with error " << ret; + return oss.str(); + } + + cluster.wait_for_latest_osdmap(); + return ""; +} + +std::string connect_cluster(rados_t *cluster) +{ + char *id = getenv("CEPH_CLIENT_ID"); + if (id) std::cerr << "Client id is: " << id << std::endl; + + int ret; + ret = rados_create(cluster, NULL); + if (ret) { + std::ostringstream oss; + oss << "rados_create failed with error " << ret; + return oss.str(); + } + ret = rados_conf_read_file(*cluster, NULL); + if (ret) { + rados_shutdown(*cluster); + std::ostringstream oss; + oss << "rados_conf_read_file failed with error " << ret; + return oss.str(); + } + rados_conf_parse_env(*cluster, NULL); + ret = rados_connect(*cluster); + if (ret) { + rados_shutdown(*cluster); + std::ostringstream oss; + oss << "rados_connect failed with error " << ret; + return oss.str(); + } + return ""; +} + +std::string connect_cluster_pp(librados::Rados &cluster) +{ + return connect_cluster_pp(cluster, {}); +} + +std::string connect_cluster_pp(librados::Rados &cluster, + const std::map &config) +{ + char *id = getenv("CEPH_CLIENT_ID"); + if (id) std::cerr << "Client id is: " << id << std::endl; + + int ret; + ret = cluster.init(id); + if (ret) { + std::ostringstream oss; + oss << "cluster.init failed with error " << ret; + return oss.str(); + } + ret = cluster.conf_read_file(NULL); + if (ret) { + cluster.shutdown(); + std::ostringstream oss; + oss << "cluster.conf_read_file failed with error " << ret; + return oss.str(); + } + cluster.conf_parse_env(NULL); + + for (auto &setting : config) { + ret = cluster.conf_set(setting.first.c_str(), setting.second.c_str()); + if (ret) { + std::ostringstream oss; + oss << "failed to set config value " << setting.first << " to '" + << setting.second << "': " << strerror(-ret); + return oss.str(); + } + } + + ret = cluster.connect(); + if (ret) { + cluster.shutdown(); + std::ostringstream oss; + oss << "cluster.connect failed with error " << ret; + return oss.str(); + } + return ""; +} + +int destroy_one_pool(const std::string &pool_name, rados_t *cluster) +{ + int ret = rados_pool_delete(*cluster, pool_name.c_str()); + if (ret) { + rados_shutdown(*cluster); + return ret; + } + rados_shutdown(*cluster); + return 0; +} + +int destroy_one_ec_pool(const std::string &pool_name, rados_t *cluster) +{ + int ret = rados_pool_delete(*cluster, pool_name.c_str()); + if (ret) { + rados_shutdown(*cluster); + return ret; + } + + CephContext *cct = static_cast(rados_cct(*cluster)); + if (!cct->_conf->mon_fake_pool_delete) { // hope this is in [global] + std::ostringstream oss; + ret = destroy_ec_profile_and_ruleset(cluster, pool_name, oss); + if (ret) { + rados_shutdown(*cluster); + return ret; + } + } + + rados_wait_for_latest_osdmap(*cluster); + rados_shutdown(*cluster); + return ret; +} + +int destroy_one_pool_pp(const std::string &pool_name, Rados &cluster) +{ + int ret = cluster.pool_delete(pool_name.c_str()); + if (ret) { + cluster.shutdown(); + return ret; + } + cluster.shutdown(); + return 0; +} + +int destroy_one_ec_pool_pp(const std::string &pool_name, Rados &cluster) +{ + int ret = cluster.pool_delete(pool_name.c_str()); + if (ret) { + cluster.shutdown(); + return ret; + } + + CephContext *cct = static_cast(cluster.cct()); + if (!cct->_conf->mon_fake_pool_delete) { // hope this is in [global] + std::ostringstream oss; + ret = destroy_ec_profile_and_ruleset_pp(cluster, pool_name, oss); + if (ret) { + cluster.shutdown(); + return ret; + } + } + + cluster.wait_for_latest_osdmap(); + cluster.shutdown(); + return ret; +} + +void assert_eq_sparse(bufferlist& expected, + const std::map& extents, + bufferlist& actual) { + auto i = expected.begin(); + auto p = actual.begin(); + uint64_t pos = 0; + for (auto extent : extents) { + const uint64_t start = extent.first; + const uint64_t end = start + extent.second; + for (; pos < end; ++i, ++pos) { + ASSERT_FALSE(i.end()); + if (pos < start) { + // check the hole + ASSERT_EQ('\0', *i); + } else { + // then the extent + ASSERT_EQ(*i, *p); + ++p; + } + } + } + ASSERT_EQ(expected.length(), pos); +}