}
auto replayer = std::make_unique<PeerReplayer>(
- m_cct, this, m_filesystem, peer, m_directories, m_mount, m_service_daemon);
+ m_cct, this, m_cluster, m_filesystem, peer, m_directories, m_mount, m_service_daemon);
int r = init_replayer(replayer.get());
if (r < 0) {
m_service_daemon->add_or_update_peer_attribute(m_filesystem.fscid, peer,
#include "PeerReplayer.h"
#include "Utils.h"
+#include "json_spirit/json_spirit.h"
+
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_cephfs_mirror
#undef dout_prefix
namespace {
+const std::string PEER_CONFIG_KEY_PREFIX = "cephfs/mirror/peer";
+
std::string snapshot_dir_path(CephContext *cct, const std::string &path) {
return path + "/" + cct->_conf->client_snapdir;
}
return metadata;
}
+std::string peer_config_key(const std::string &fs_name, const std::string &uuid) {
+ return PEER_CONFIG_KEY_PREFIX + "/" + fs_name + "/" + uuid;
+}
+
class PeerAdminSocketCommand {
public:
virtual ~PeerAdminSocketCommand() {
};
PeerReplayer::PeerReplayer(CephContext *cct, FSMirror *fs_mirror,
- const Filesystem &filesystem, const Peer &peer,
- const std::set<std::string, std::less<>> &directories,
+ RadosRef local_cluster, const Filesystem &filesystem,
+ const Peer &peer, const std::set<std::string, std::less<>> &directories,
MountRef mount, ServiceDaemon *service_daemon)
: m_cct(cct),
m_fs_mirror(fs_mirror),
+ m_local_cluster(local_cluster),
m_filesystem(filesystem),
m_peer(peer),
m_directories(directories.begin(), directories.end()),
auto &remote_cluster = m_peer.remote.cluster_name;
auto remote_filesystem = Filesystem{0, m_peer.remote.fs_name};
- int r = connect(remote_client, remote_cluster, &m_remote_cluster);
+ std::string key = peer_config_key(m_filesystem.fs_name, m_peer.uuid);
+ std::string cmd =
+ "{"
+ "\"prefix\": \"config-key get\", "
+ "\"key\": \"" + key + "\""
+ "}";
+
+ bufferlist in_bl;
+ bufferlist out_bl;
+
+ int r = m_local_cluster->mon_command(cmd, in_bl, &out_bl, nullptr);
+ dout(5) << ": mon command r=" << r << dendl;
+ if (r < 0 && r != -ENOENT) {
+ return r;
+ }
+
+ std::string mon_host;
+ std::string cephx_key;
+ if (!r) {
+ json_spirit::mValue root;
+ if (!json_spirit::read(out_bl.to_str(), root)) {
+ derr << ": invalid config-key JSON" << dendl;
+ return -EBADMSG;
+ }
+ try {
+ auto &root_obj = root.get_obj();
+ mon_host = root_obj.at("mon_host").get_str();
+ cephx_key = root_obj.at("key").get_str();
+ dout(0) << ": remote monitor host=" << mon_host << dendl;
+ } catch (std::runtime_error&) {
+ derr << ": unexpected JSON received" << dendl;
+ return -EBADMSG;
+ }
+ }
+
+ r = connect(remote_client, remote_cluster, &m_remote_cluster, mon_host, cephx_key);
if (r < 0) {
derr << ": error connecting to remote cluster: " << cpp_strerror(r)
<< dendl;
class PeerReplayer {
public:
PeerReplayer(CephContext *cct, FSMirror *fs_mirror,
- const Filesystem &filesystem, const Peer &peer,
- const std::set<std::string, std::less<>> &directories,
+ RadosRef local_cluster, const Filesystem &filesystem,
+ const Peer &peer, const std::set<std::string, std::less<>> &directories,
MountRef mount, ServiceDaemon *service_daemon);
~PeerReplayer();
CephContext *m_cct;
FSMirror *m_fs_mirror;
+ RadosRef m_local_cluster;
Filesystem m_filesystem;
Peer m_peer;
// probably need to be encapsulated when supporting cancelations
namespace mirror {
int connect(std::string_view client_name, std::string_view cluster_name,
- RadosRef *cluster) {
+ RadosRef *cluster, std::string_view mon_host, std::string_view cephx_key) {
dout(20) << ": connecting to cluster=" << cluster_name << ", client=" << client_name
- << dendl;
+ << ", mon_host=" << mon_host << dendl;
CephInitParameters iparams(CEPH_ENTITY_TYPE_CLIENT);
if (client_name.empty() || !iparams.name.from_str(client_name)) {
cct->_conf->cluster = cluster_name;
int r = cct->_conf.parse_config_files(nullptr, nullptr, 0);
- if (r < 0) {
+ if (r < 0 && r != -ENOENT) {
derr << ": could not read ceph conf: " << ": " << cpp_strerror(r) << dendl;
return r;
}
}
cct->_conf.parse_env(cct->get_module_type());
+ if (!mon_host.empty()) {
+ r = cct->_conf.set_val("mon_host", std::string(mon_host));
+ if (r < 0) {
+ derr << "failed to set mon_host config: " << cpp_strerror(r) << dendl;
+ cct->put();
+ return r;
+ }
+ }
+ if (!cephx_key.empty()) {
+ r = cct->_conf.set_val("key", std::string(cephx_key));
+ if (r < 0) {
+ derr << "failed to set key config: " << cpp_strerror(r) << dendl;
+ cct->put();
+ return r;
+ }
+ }
+
cluster->reset(new librados::Rados());
r = (*cluster)->init_with_context(cct);