diff options
Diffstat (limited to 'src/librbd/migration/NativeFormat.cc')
-rw-r--r-- | src/librbd/migration/NativeFormat.cc | 121 |
1 files changed, 102 insertions, 19 deletions
diff --git a/src/librbd/migration/NativeFormat.cc b/src/librbd/migration/NativeFormat.cc index 6d4c3bcbba4..4bbeee0535c 100644 --- a/src/librbd/migration/NativeFormat.cc +++ b/src/librbd/migration/NativeFormat.cc @@ -2,17 +2,14 @@ // vim: ts=8 sw=2 smarttab #include "librbd/migration/NativeFormat.h" -#include "include/neorados/RADOS.hpp" +#include "common/ceph_argparse.h" +#include "common/common_init.h" #include "common/dout.h" #include "common/errno.h" +#include "include/scope_guard.h" #include "librbd/ImageCtx.h" -#include "librbd/ImageState.h" -#include "librbd/Utils.h" -#include "librbd/asio/ContextWQ.h" -#include "librbd/io/ImageDispatchSpec.h" #include "json_spirit/json_spirit.h" #include "boost/lexical_cast.hpp" -#include <sstream> #define dout_subsys ceph_subsys_rbd #undef dout_prefix @@ -25,6 +22,8 @@ namespace migration { namespace { const std::string TYPE_KEY{"type"}; +const std::string CLUSTER_NAME_KEY{"cluster_name"}; +const std::string CLIENT_NAME_KEY{"client_name"}; const std::string POOL_ID_KEY{"pool_id"}; const std::string POOL_NAME_KEY{"pool_name"}; const std::string POOL_NAMESPACE_KEY{"pool_namespace"}; @@ -63,24 +62,48 @@ template <typename I> int NativeFormat<I>::create_image_ctx( librados::IoCtx& dst_io_ctx, const json_spirit::mObject& source_spec_object, - bool import_only, uint64_t src_snap_id, I** src_image_ctx) { + bool import_only, uint64_t src_snap_id, I** src_image_ctx, + librados::Rados** src_rados) { auto cct = reinterpret_cast<CephContext*>(dst_io_ctx.cct()); + std::string cluster_name; + std::string client_name; + std::string pool_name; int64_t pool_id = -1; std::string pool_namespace; std::string image_name; std::string image_id; std::string snap_name; uint64_t snap_id = CEPH_NOSNAP; + int r; + + if (auto it = source_spec_object.find(CLUSTER_NAME_KEY); + it != source_spec_object.end()) { + if (it->second.type() == json_spirit::str_type) { + cluster_name = it->second.get_str(); + } else { + lderr(cct) << "invalid cluster name" << dendl; + return -EINVAL; + } + } + + if (auto it = source_spec_object.find(CLIENT_NAME_KEY); + it != source_spec_object.end()) { + if (cluster_name.empty()) { + lderr(cct) << "cannot specify client name without cluster name" << dendl; + return -EINVAL; + } + if (it->second.type() == json_spirit::str_type) { + client_name = it->second.get_str(); + } else { + lderr(cct) << "invalid client name" << dendl; + return -EINVAL; + } + } if (auto it = source_spec_object.find(POOL_NAME_KEY); it != source_spec_object.end()) { if (it->second.type() == json_spirit::str_type) { - librados::Rados rados(dst_io_ctx); - pool_id = rados.pool_lookup(it->second.get_str().c_str()); - if (pool_id < 0) { - lderr(cct) << "failed to lookup pool" << dendl; - return static_cast<int>(pool_id); - } + pool_name = it->second.get_str(); } else { lderr(cct) << "invalid pool name" << dendl; return -EINVAL; @@ -89,7 +112,7 @@ int NativeFormat<I>::create_image_ctx( if (auto it = source_spec_object.find(POOL_ID_KEY); it != source_spec_object.end()) { - if (pool_id != -1) { + if (!pool_name.empty()) { lderr(cct) << "cannot specify both pool name and pool id" << dendl; return -EINVAL; } @@ -107,7 +130,7 @@ int NativeFormat<I>::create_image_ctx( } } - if (pool_id == -1) { + if (pool_name.empty() && pool_id == -1) { lderr(cct) << "missing pool name or pool id" << dendl; return -EINVAL; } @@ -177,7 +200,7 @@ int NativeFormat<I>::create_image_ctx( // snapshot is required for import to keep source read-only if (import_only && snap_name.empty() && snap_id == CEPH_NOSNAP) { - lderr(cct) << "snapshot required for import" << dendl; + lderr(cct) << "snap name or snap id required for import" << dendl; return -EINVAL; } @@ -188,14 +211,67 @@ int NativeFormat<I>::create_image_ctx( snap_id = src_snap_id; } - // TODO add support for external clusters + std::unique_ptr<librados::Rados> rados_ptr; + if (!cluster_name.empty()) { + // manually bootstrap a CephContext, skipping reading environment + // variables for now -- since we don't have access to command line + // arguments here, the least confusing option is to limit initial + // remote cluster config to a file in the default location + // TODO: support specifying mon_host and key via source spec + // TODO: support merging in effective local cluster config to get + // overrides for log levels, etc + CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT); + if (!client_name.empty() && !iparams.name.from_str(client_name)) { + lderr(cct) << "failed to set remote client name" << dendl; + return -EINVAL; + } + + auto remote_cct = common_preinit(iparams, CODE_ENVIRONMENT_LIBRARY, 0); + auto put_remote_cct = make_scope_guard([remote_cct] { remote_cct->put(); }); + + remote_cct->_conf->cluster = cluster_name; + + // pass CEPH_CONF_FILE_DEFAULT instead of nullptr to prevent + // CEPH_CONF environment variable from being picked up + r = remote_cct->_conf.parse_config_files(CEPH_CONF_FILE_DEFAULT, nullptr, + 0); + if (r < 0) { + remote_cct->_conf.complain_about_parse_error(cct); + lderr(cct) << "failed to read ceph conf for remote cluster: " + << cpp_strerror(r) << dendl; + return r; + } + + remote_cct->_conf.apply_changes(nullptr); + + rados_ptr.reset(new librados::Rados()); + r = rados_ptr->init_with_context(remote_cct); + ceph_assert(r == 0); + + r = rados_ptr->connect(); + if (r < 0) { + lderr(cct) << "failed to connect to remote cluster: " << cpp_strerror(r) + << dendl; + return r; + } + } else { + rados_ptr.reset(new librados::Rados(dst_io_ctx)); + } + librados::IoCtx src_io_ctx; - int r = util::create_ioctx(dst_io_ctx, "source image", pool_id, - pool_namespace, &src_io_ctx); + if (!pool_name.empty()) { + r = rados_ptr->ioctx_create(pool_name.c_str(), src_io_ctx); + } else { + r = rados_ptr->ioctx_create2(pool_id, src_io_ctx); + } if (r < 0) { + lderr(cct) << "failed to open source image pool: " << cpp_strerror(r) + << dendl; return r; } + src_io_ctx.set_namespace(pool_namespace); + if (!snap_name.empty() && snap_id == CEPH_NOSNAP) { *src_image_ctx = I::create(image_name, image_id, snap_name.c_str(), src_io_ctx, true); @@ -203,6 +279,13 @@ int NativeFormat<I>::create_image_ctx( *src_image_ctx = I::create(image_name, image_id, snap_id, src_io_ctx, true); } + + if (!cluster_name.empty()) { + *src_rados = rados_ptr.release(); + } else { + *src_rados = nullptr; + } + return 0; } |