summaryrefslogtreecommitdiffstats
path: root/src/librbd/migration/NativeFormat.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/librbd/migration/NativeFormat.cc')
-rw-r--r--src/librbd/migration/NativeFormat.cc121
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;
}