return 0;
}
-int write_peer(cls_method_context_t hctx, const std::string &id,
- const cls::rbd::MirrorPeer &peer) {
+int write_peer(cls_method_context_t hctx, const cls::rbd::MirrorPeer &peer) {
bufferlist bl;
encode(peer, bl);
- int r = cls_cxx_map_set_val(hctx, peer_key(id), &bl);
+ int r = cls_cxx_map_set_val(hctx, peer_key(peer.uuid), &bl);
if (r < 0) {
- CLS_ERR("error writing peer '%s': %s", id.c_str(),
+ CLS_ERR("error writing peer '%s': %s", peer.uuid.c_str(),
cpp_strerror(r).c_str());
return r;
}
return 0;
}
+int check_mirroring_enabled(cls_method_context_t hctx) {
+ uint32_t mirror_mode_decode;
+ int r = read_key(hctx, mirror::MODE, &mirror_mode_decode);
+ if (r < 0 && r != -ENOENT) {
+ return r;
+ } else if (r == -ENOENT ||
+ mirror_mode_decode == cls::rbd::MIRROR_MODE_DISABLED) {
+ CLS_ERR("mirroring must be enabled on the pool");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int peer_ping(cls_method_context_t hctx, const std::string& site_name,
+ const std::string& fsid) {
+ int r = check_mirroring_enabled(hctx);
+ if (r < 0) {
+ return r;
+ }
+
+ if (site_name.empty() || fsid.empty()) {
+ return -EINVAL;
+ }
+
+ std::vector<cls::rbd::MirrorPeer> peers;
+ r = read_peers(hctx, &peers);
+ if (r < 0 && r != -ENOENT) {
+ return r;
+ }
+
+
+ cls::rbd::MirrorPeer mirror_peer;
+ auto site_it = std::find_if(peers.begin(), peers.end(),
+ [&site_name](auto& peer) {
+ return (peer.site_name == site_name);
+ });
+
+ auto fsid_it = peers.end();
+ if (site_it == peers.end() ||
+ (!site_it->fsid.empty() && site_it->fsid != fsid)) {
+ // search for existing peer w/ same fsid
+ fsid_it = std::find_if(peers.begin(), peers.end(),
+ [&fsid](auto& peer) {
+ return (peer.fsid == fsid);
+ });
+ }
+
+ auto it = peers.end();
+ if (site_it != peers.end() && fsid_it != peers.end()) {
+ // implies two peers -- match by fsid but don't update site name
+ it = fsid_it;
+ } else if (fsid_it != peers.end()) {
+ // implies site name has been updated in remote
+ fsid_it->site_name = site_name;
+ it = fsid_it;
+ } else if (site_it != peers.end()) {
+ // implies empty fsid in peer
+ site_it->fsid = fsid;
+ it = site_it;
+ } else {
+ CLS_LOG(10, "auto-generating new TX-only peer: %s", site_name.c_str());
+
+ uuid_d uuid_gen;
+ while (true) {
+ uuid_gen.generate_random();
+ mirror_peer.uuid = uuid_gen.to_string();
+
+ bufferlist bl;
+ r = cls_cxx_map_get_val(hctx, peer_key(mirror_peer.uuid), &bl);
+ if (r == -ENOENT) {
+ break;
+ } else if (r < 0) {
+ CLS_ERR("failed to retrieve mirror peer: %s", cpp_strerror(r).c_str());
+ return r;
+ }
+ }
+
+ mirror_peer.mirror_peer_direction = cls::rbd::MIRROR_PEER_DIRECTION_TX;
+ mirror_peer.site_name = site_name;
+ mirror_peer.fsid = fsid;
+ }
+
+ if (it != peers.end()) {
+ mirror_peer = *it;
+
+ if (mirror_peer.mirror_peer_direction ==
+ cls::rbd::MIRROR_PEER_DIRECTION_RX) {
+ CLS_LOG(10, "switching to RX/TX peer: %s", site_name.c_str());
+ mirror_peer.mirror_peer_direction = cls::rbd::MIRROR_PEER_DIRECTION_RX_TX;
+ }
+ }
+
+ mirror_peer.last_seen = ceph_clock_now();
+
+ if (!mirror_peer.is_valid()) {
+ CLS_ERR("attempting to update invalid peer: %s", site_name.c_str());
+ return -EINVAL;
+ }
+
+ r = write_peer(hctx, mirror_peer);
+ if (r < 0) {
+ return r;
+ }
+
+ return 0;
+}
+
+int peer_add(cls_method_context_t hctx, cls::rbd::MirrorPeer mirror_peer) {
+ int r = check_mirroring_enabled(hctx);
+ if (r < 0) {
+ return r;
+ }
+
+ if (!mirror_peer.is_valid()) {
+ CLS_ERR("mirror peer is not valid");
+ return -EINVAL;
+ }
+
+ std::string mirror_uuid;
+ r = uuid_get(hctx, &mirror_uuid);
+ if (r < 0) {
+ CLS_ERR("error retrieving mirroring uuid: %s", cpp_strerror(r).c_str());
+ return r;
+ } else if (mirror_peer.uuid == mirror_uuid) {
+ CLS_ERR("peer uuid '%s' matches pool mirroring uuid",
+ mirror_uuid.c_str());
+ return -EINVAL;
+ } else if (mirror_peer.mirror_peer_direction ==
+ cls::rbd::MIRROR_PEER_DIRECTION_TX) {
+ CLS_ERR("peer uuid '%s' cannot use TX-only direction",
+ mirror_peer.uuid.c_str());
+ return -EINVAL;
+ }
+
+ std::vector<cls::rbd::MirrorPeer> peers;
+ r = read_peers(hctx, &peers);
+ if (r < 0 && r != -ENOENT) {
+ return r;
+ }
+
+ for (auto const &peer : peers) {
+ if (peer.uuid == mirror_peer.uuid) {
+ CLS_ERR("peer uuid '%s' already exists",
+ peer.uuid.c_str());
+ return -ESTALE;
+ } else if (peer.site_name == mirror_peer.site_name) {
+ CLS_ERR("peer site name '%s' already exists",
+ peer.site_name.c_str());
+ return -EEXIST;
+ } else if (!mirror_peer.fsid.empty() && peer.fsid == mirror_peer.fsid) {
+ CLS_ERR("peer fsid '%s' already exists",
+ peer.fsid.c_str());
+ return -EEXIST;
+ }
+ }
+
+ r = write_peer(hctx, mirror_peer);
+ if (r < 0) {
+ return r;
+ }
+ return 0;
+}
+
+int peer_remove(cls_method_context_t hctx, const std::string& uuid) {
+ int r = cls_cxx_map_remove_key(hctx, peer_key(uuid));
+ if (r < 0 && r != -ENOENT) {
+ CLS_ERR("error removing peer: %s", cpp_strerror(r).c_str());
+ return r;
+ }
+ return 0;
+}
+
int image_get(cls_method_context_t hctx, const string &image_id,
cls::rbd::MirrorImage *mirror_image) {
bufferlist bl;
return 0;
}
+/**
+ * Input:
+ * @param unique peer site name (std::string)
+ * @param fsid (std::string)
+ * @param direction (MirrorPeerDirection) -- future use
+ *
+ * Output:
+ * @returns 0 on success, negative error code on failure
+ */
+int mirror_peer_ping(cls_method_context_t hctx, bufferlist *in,
+ bufferlist *out) {
+ std::string site_name;
+ std::string fsid;
+ cls::rbd::MirrorPeerDirection mirror_peer_direction;
+ try {
+ auto it = in->cbegin();
+ decode(site_name, it);
+ decode(fsid, it);
+
+ uint8_t direction;
+ decode(direction, it);
+ mirror_peer_direction = static_cast<cls::rbd::MirrorPeerDirection>(
+ direction);
+ } catch (const buffer::error &err) {
+ return -EINVAL;
+ }
+
+ if (mirror_peer_direction != cls::rbd::MIRROR_PEER_DIRECTION_TX) {
+ return -EINVAL;
+ }
+
+ int r = mirror::peer_ping(hctx, site_name, fsid);
+ if (r < 0) {
+ return r;
+ }
+
+ return 0;
+}
+
/**
* Input:
* none
return -EINVAL;
}
- uint32_t mirror_mode_decode;
- int r = read_key(hctx, mirror::MODE, &mirror_mode_decode);
- if (r < 0 && r != -ENOENT) {
- return r;
- } else if (r == -ENOENT ||
- mirror_mode_decode == cls::rbd::MIRROR_MODE_DISABLED) {
- CLS_ERR("mirroring must be enabled on the pool");
- return -EINVAL;
- } else if (!mirror_peer.is_valid()) {
- CLS_ERR("mirror peer is not valid");
- return -EINVAL;
- }
-
- std::string mirror_uuid;
- r = mirror::uuid_get(hctx, &mirror_uuid);
+ int r = mirror::peer_add(hctx, mirror_peer);
if (r < 0) {
- CLS_ERR("error retrieving mirroring uuid: %s", cpp_strerror(r).c_str());
- return r;
- } else if (mirror_peer.uuid == mirror_uuid) {
- CLS_ERR("peer uuid '%s' matches pool mirroring uuid",
- mirror_uuid.c_str());
- return -EINVAL;
- }
-
- std::vector<cls::rbd::MirrorPeer> peers;
- r = mirror::read_peers(hctx, &peers);
- if (r < 0 && r != -ENOENT) {
return r;
}
- for (auto const &peer : peers) {
- if (peer.uuid == mirror_peer.uuid) {
- CLS_ERR("peer uuid '%s' already exists",
- peer.uuid.c_str());
- return -ESTALE;
- } else if (peer.cluster_name == mirror_peer.cluster_name) {
- CLS_ERR("peer cluster name '%s' already exists",
- peer.cluster_name.c_str());
- return -EEXIST;
- }
- }
-
- bufferlist bl;
- encode(mirror_peer, bl);
- r = cls_cxx_map_set_val(hctx, mirror::peer_key(mirror_peer.uuid),
- &bl);
- if (r < 0) {
- CLS_ERR("error adding peer: %s", cpp_strerror(r).c_str());
- return r;
- }
return 0;
}
return -EINVAL;
}
- int r = cls_cxx_map_remove_key(hctx, mirror::peer_key(uuid));
- if (r < 0 && r != -ENOENT) {
- CLS_ERR("error removing peer: %s", cpp_strerror(r).c_str());
+ int r = mirror::peer_remove(hctx, uuid);
+ if (r < 0) {
return r;
}
return 0;
}
peer.client_name = client_name;
- r = mirror::write_peer(hctx, uuid, peer);
+ r = mirror::write_peer(hctx, peer);
if (r < 0) {
return r;
}
/**
* Input:
* @param uuid (std::string)
- * @param cluster_name (std::string)
+ * @param site_name (std::string)
*
* Output:
* @returns 0 on success, negative error code on failure
int mirror_peer_set_cluster(cls_method_context_t hctx, bufferlist *in,
bufferlist *out) {
std::string uuid;
- std::string cluster_name;
+ std::string site_name;
try {
auto it = in->cbegin();
decode(uuid, it);
- decode(cluster_name, it);
+ decode(site_name, it);
} catch (const buffer::error &err) {
return -EINVAL;
}
- cls::rbd::MirrorPeer peer;
- int r = mirror::read_peer(hctx, uuid, &peer);
- if (r < 0) {
+ cls::rbd::MirrorPeer* peer = nullptr;
+ std::vector<cls::rbd::MirrorPeer> peers;
+ int r = mirror::read_peers(hctx, &peers);
+ if (r < 0 && r != -ENOENT) {
return r;
}
- peer.cluster_name = cluster_name;
- r = mirror::write_peer(hctx, uuid, peer);
+ for (auto& p : peers) {
+ if (p.uuid == uuid) {
+ peer = &p;
+ } else if (p.site_name == site_name) {
+ return -EEXIST;
+ }
+ }
+
+ if (peer == nullptr) {
+ return -ENOENT;
+ }
+
+ peer->site_name = site_name;
+ r = mirror::write_peer(hctx, *peer);
if (r < 0) {
return r;
}
cls_method_handle_t h_mirror_uuid_set;
cls_method_handle_t h_mirror_mode_get;
cls_method_handle_t h_mirror_mode_set;
+ cls_method_handle_t h_mirror_peer_ping;
cls_method_handle_t h_mirror_peer_list;
cls_method_handle_t h_mirror_peer_add;
cls_method_handle_t h_mirror_peer_remove;
cls_register_cxx_method(h_class, "mirror_mode_set",
CLS_METHOD_RD | CLS_METHOD_WR,
mirror_mode_set, &h_mirror_mode_set);
+ cls_register_cxx_method(h_class, "mirror_peer_ping",
+ CLS_METHOD_RD | CLS_METHOD_WR,
+ mirror_peer_ping, &h_mirror_peer_ping);
cls_register_cxx_method(h_class, "mirror_peer_list", CLS_METHOD_RD,
mirror_peer_list, &h_mirror_peer_list);
cls_register_cxx_method(h_class, "mirror_peer_add",
return 0;
}
-int mirror_peer_add(librados::IoCtx *ioctx, const std::string &uuid,
- const std::string &cluster_name,
- const std::string &client_name) {
- cls::rbd::MirrorPeer peer(uuid, cluster_name, client_name);
+int mirror_peer_ping(librados::IoCtx *ioctx,
+ const std::string& site_name,
+ const std::string& fsid) {
+ librados::ObjectWriteOperation op;
+ mirror_peer_ping(&op, site_name, fsid);
+
+ int r = ioctx->operate(RBD_MIRRORING, &op);
+ if (r < 0) {
+ return r;
+ }
+
+ return 0;
+}
+
+void mirror_peer_ping(librados::ObjectWriteOperation *op,
+ const std::string& site_name,
+ const std::string& fsid) {
bufferlist in_bl;
- encode(peer, in_bl);
+ encode(site_name, in_bl);
+ encode(fsid, in_bl);
+ encode(static_cast<uint8_t>(cls::rbd::MIRROR_PEER_DIRECTION_TX), in_bl);
- bufferlist out_bl;
- int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_peer_add", in_bl,
- out_bl);
+ op->exec("rbd", "mirror_peer_ping", in_bl);
+}
+
+int mirror_peer_add(librados::IoCtx *ioctx,
+ const cls::rbd::MirrorPeer& mirror_peer) {
+ librados::ObjectWriteOperation op;
+ mirror_peer_add(&op, mirror_peer);
+
+ int r = ioctx->operate(RBD_MIRRORING, &op);
if (r < 0) {
return r;
}
+
return 0;
}
+void mirror_peer_add(librados::ObjectWriteOperation *op,
+ const cls::rbd::MirrorPeer& mirror_peer) {
+ bufferlist in_bl;
+ encode(mirror_peer, in_bl);
+
+ op->exec("rbd", "mirror_peer_add", in_bl);
+}
+
int mirror_peer_remove(librados::IoCtx *ioctx,
const std::string &uuid) {
bufferlist in_bl;
cls::rbd::MirrorMode *mirror_mode);
int mirror_mode_set(librados::IoCtx *ioctx,
cls::rbd::MirrorMode mirror_mode);
+
+int mirror_peer_ping(librados::IoCtx *ioctx,
+ const std::string& site_name,
+ const std::string& fsid);
+void mirror_peer_ping(librados::ObjectWriteOperation *op,
+ const std::string& site_name,
+ const std::string& fsid);
int mirror_peer_list(librados::IoCtx *ioctx,
std::vector<cls::rbd::MirrorPeer> *peers);
-int mirror_peer_add(librados::IoCtx *ioctx, const std::string &uuid,
- const std::string &cluster_name,
- const std::string &client_name);
+int mirror_peer_add(librados::IoCtx *ioctx,
+ const cls::rbd::MirrorPeer& mirror_peer);
+void mirror_peer_add(librados::ObjectWriteOperation *op,
+ const cls::rbd::MirrorPeer& mirror_peer);
int mirror_peer_remove(librados::IoCtx *ioctx,
const std::string &uuid);
int mirror_peer_set_client(librados::IoCtx *ioctx,
int mirror_peer_set_cluster(librados::IoCtx *ioctx,
const std::string &uuid,
const std::string &cluster_name);
+
void mirror_image_list_start(librados::ObjectReadOperation *op,
const std::string &start, uint64_t max_return);
int mirror_image_list_finish(bufferlist::const_iterator *it,
namespace cls {
namespace rbd {
+std::ostream& operator<<(std::ostream& os,
+ MirrorPeerDirection mirror_peer_direction) {
+ switch (mirror_peer_direction) {
+ case MIRROR_PEER_DIRECTION_RX:
+ os << "RX";
+ break;
+ case MIRROR_PEER_DIRECTION_TX:
+ os << "TX";
+ break;
+ case MIRROR_PEER_DIRECTION_RX_TX:
+ os << "RX/TX";
+ break;
+ default:
+ os << "unknown";
+ break;
+ }
+ return os;
+}
+
void MirrorPeer::encode(bufferlist &bl) const {
- ENCODE_START(1, 1, bl);
+ ENCODE_START(2, 1, bl);
encode(uuid, bl);
- encode(cluster_name, bl);
+ encode(site_name, bl);
encode(client_name, bl);
int64_t pool_id = -1;
encode(pool_id, bl);
+
+ // v2
+ encode(static_cast<uint8_t>(mirror_peer_direction), bl);
+ encode(fsid, bl);
+ encode(last_seen, bl);
ENCODE_FINISH(bl);
}
void MirrorPeer::decode(bufferlist::const_iterator &it) {
- DECODE_START(1, it);
+ DECODE_START(2, it);
decode(uuid, it);
- decode(cluster_name, it);
+ decode(site_name, it);
decode(client_name, it);
int64_t pool_id;
decode(pool_id, it);
+
+ if (struct_v >= 2) {
+ uint8_t mpd;
+ decode(mpd, it);
+ mirror_peer_direction = static_cast<MirrorPeerDirection>(mpd);
+ decode(fsid, it);
+ decode(last_seen, it);
+ }
+
DECODE_FINISH(it);
}
void MirrorPeer::dump(Formatter *f) const {
f->dump_string("uuid", uuid);
- f->dump_string("cluster_name", cluster_name);
+ f->dump_stream("direction") << mirror_peer_direction;
+ f->dump_string("site_name", site_name);
+ f->dump_string("fsid", fsid);
f->dump_string("client_name", client_name);
+ f->dump_stream("last_seen") << last_seen;
}
void MirrorPeer::generate_test_instances(std::list<MirrorPeer*> &o) {
o.push_back(new MirrorPeer());
- o.push_back(new MirrorPeer("uuid-123", "cluster name", "client name"));
+ o.push_back(new MirrorPeer("uuid-123", MIRROR_PEER_DIRECTION_RX, "site A",
+ "client name", ""));
+ o.push_back(new MirrorPeer("uuid-234", MIRROR_PEER_DIRECTION_TX, "site B",
+ "", "fsid"));
+ o.push_back(new MirrorPeer("uuid-345", MIRROR_PEER_DIRECTION_RX_TX, "site C",
+ "client name", "fsid"));
}
bool MirrorPeer::operator==(const MirrorPeer &rhs) const {
return (uuid == rhs.uuid &&
- cluster_name == rhs.cluster_name &&
- client_name == rhs.client_name);
+ mirror_peer_direction == rhs.mirror_peer_direction &&
+ site_name == rhs.site_name &&
+ client_name == rhs.client_name &&
+ fsid == rhs.fsid &&
+ last_seen == rhs.last_seen);
}
std::ostream& operator<<(std::ostream& os, const MirrorMode& mirror_mode) {
std::ostream& operator<<(std::ostream& os, const MirrorPeer& peer) {
os << "["
<< "uuid=" << peer.uuid << ", "
- << "cluster_name=" << peer.cluster_name << ", "
- << "client_name=" << peer.client_name
+ << "direction=" << peer.mirror_peer_direction << ", "
+ << "site_name=" << peer.site_name << ", "
+ << "client_name=" << peer.client_name << ", "
+ << "fsid=" << peer.fsid << ", "
+ << "last_seen=" << peer.last_seen
<< "]";
return os;
}
state = static_cast<GroupImageLinkState>(int_state);
}
+enum MirrorPeerDirection {
+ MIRROR_PEER_DIRECTION_RX = 0,
+ MIRROR_PEER_DIRECTION_TX = 1,
+ MIRROR_PEER_DIRECTION_RX_TX = 2
+};
+
+std::ostream& operator<<(std::ostream& os,
+ MirrorPeerDirection mirror_peer_direction);
+
struct MirrorPeer {
MirrorPeer() {
}
- MirrorPeer(const std::string &uuid, const std::string &cluster_name,
- const std::string &client_name)
- : uuid(uuid), cluster_name(cluster_name), client_name(client_name) {
+ MirrorPeer(const std::string &uuid,
+ MirrorPeerDirection mirror_peer_direction,
+ const std::string& site_name,
+ const std::string& client_name,
+ const std::string& fsid)
+ : uuid(uuid), mirror_peer_direction(mirror_peer_direction),
+ site_name(site_name), client_name(client_name), fsid(fsid) {
}
std::string uuid;
- std::string cluster_name;
- std::string client_name;
+
+ MirrorPeerDirection mirror_peer_direction = MIRROR_PEER_DIRECTION_RX_TX;
+ std::string site_name;
+ std::string client_name; // RX property
+ std::string fsid;
+ utime_t last_seen;
inline bool is_valid() const {
- return (!uuid.empty() && !cluster_name.empty() && !client_name.empty());
+ switch (mirror_peer_direction) {
+ case MIRROR_PEER_DIRECTION_TX:
+ break;
+ case MIRROR_PEER_DIRECTION_RX:
+ case MIRROR_PEER_DIRECTION_RX_TX:
+ if (client_name.empty()) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ return (!uuid.empty() && !site_name.empty());
}
void encode(bufferlist &bl) const;
static void generate_test_instances(std::list<MirrorPeer*> &o);
bool operator==(const MirrorPeer &rhs) const;
+ bool operator!=(const MirrorPeer &rhs) const {
+ return (!(*this == rhs));
+ }
};
std::ostream& operator<<(std::ostream& os, const MirrorMode& mirror_mode);
uuid_gen.generate_random();
*uuid = uuid_gen.to_string();
- r = cls_client::mirror_peer_add(&io_ctx, *uuid, cluster_name,
- client_name);
+ r = cls_client::mirror_peer_add(
+ &io_ctx,
+ {*uuid, cls::rbd::MIRROR_PEER_DIRECTION_RX, cluster_name, client_name,
+ ""});
if (r == -ESTALE) {
ldout(cct, 5) << "duplicate UUID detected, retrying" << dendl;
} else if (r < 0) {
for (auto &mirror_peer : mirror_peers) {
mirror_peer_t peer;
peer.uuid = mirror_peer.uuid;
- peer.cluster_name = mirror_peer.cluster_name;
+ peer.cluster_name = mirror_peer.site_name;
peer.client_name = mirror_peer.client_name;
peers->push_back(peer);
}
using namespace std;
using namespace librbd::cls_client;
+using cls::rbd::MIRROR_PEER_DIRECTION_RX;
+using cls::rbd::MIRROR_PEER_DIRECTION_TX;
+using cls::rbd::MIRROR_PEER_DIRECTION_RX_TX;
using ::librbd::ParentImageInfo;
using ceph::encode;
using ceph::decode;
std::string uuid;
ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid));
- ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client"));
+ ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, {"uuid1", MIRROR_PEER_DIRECTION_RX,
+ "siteA", "client", "fsid"}));
+ ASSERT_EQ(-EINVAL, mirror_peer_ping(&ioctx, "siteA", "fsid"));
cls::rbd::MirrorMode mirror_mode;
ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
ASSERT_EQ(cls::rbd::MIRROR_MODE_POOL, mirror_mode);
- ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, "mirror-uuid", "cluster1", "client"));
- ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client"));
- ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid2", "cluster2", "admin"));
- ASSERT_EQ(-ESTALE, mirror_peer_add(&ioctx, "uuid2", "cluster3", "foo"));
- ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid3", "cluster1", "foo"));
- ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid3", "cluster3", "admin", 123));
- ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin"));
- ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin", 123));
- ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin", 234));
+ ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, {"mirror-uuid",
+ MIRROR_PEER_DIRECTION_RX, "siteA",
+ "client", ""}));
+ ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, {"uuid1", MIRROR_PEER_DIRECTION_TX,
+ "siteA", "client", "fsid"}));
+ ASSERT_EQ(0, mirror_peer_add(&ioctx, {"uuid1", MIRROR_PEER_DIRECTION_RX,
+ "siteA", "client", "fsidA"}));
+ ASSERT_EQ(0, mirror_peer_add(&ioctx, {"uuid2", MIRROR_PEER_DIRECTION_RX,
+ "siteB", "admin", ""}));
+ ASSERT_EQ(-ESTALE, mirror_peer_add(&ioctx, {"uuid2", MIRROR_PEER_DIRECTION_RX,
+ "siteC", "foo", ""}));
+ ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, {"uuid3", MIRROR_PEER_DIRECTION_RX,
+ "siteA", "foo", ""}));
+ ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, {"uuid3", MIRROR_PEER_DIRECTION_RX,
+ "siteC", "client", "fsidA"}));
+ ASSERT_EQ(0, mirror_peer_add(&ioctx, {"uuid3", MIRROR_PEER_DIRECTION_RX,
+ "siteC", "admin", ""}));
+ ASSERT_EQ(0, mirror_peer_add(&ioctx, {"uuid4", MIRROR_PEER_DIRECTION_RX,
+ "siteD", "admin", ""}));
ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
std::vector<cls::rbd::MirrorPeer> expected_peers = {
- {"uuid1", "cluster1", "client", -1},
- {"uuid2", "cluster2", "admin", -1},
- {"uuid3", "cluster3", "admin", 123},
- {"uuid4", "cluster3", "admin", 234}};
+ {"uuid1", MIRROR_PEER_DIRECTION_RX, "siteA", "client", "fsidA"},
+ {"uuid2", MIRROR_PEER_DIRECTION_RX, "siteB", "admin", ""},
+ {"uuid3", MIRROR_PEER_DIRECTION_RX, "siteC", "admin", ""},
+ {"uuid4", MIRROR_PEER_DIRECTION_RX, "siteD", "admin", ""}};
ASSERT_EQ(expected_peers, peers);
ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid5"));
ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid4"));
ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid2"));
+ ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
+ expected_peers = {
+ {"uuid1", MIRROR_PEER_DIRECTION_RX, "siteA", "client", "fsidA"},
+ {"uuid3", MIRROR_PEER_DIRECTION_RX, "siteC", "admin", ""}};
+ ASSERT_EQ(expected_peers, peers);
+
ASSERT_EQ(-ENOENT, mirror_peer_set_client(&ioctx, "uuid4", "new client"));
ASSERT_EQ(0, mirror_peer_set_client(&ioctx, "uuid1", "new client"));
- ASSERT_EQ(-ENOENT, mirror_peer_set_cluster(&ioctx, "uuid4", "new cluster"));
- ASSERT_EQ(0, mirror_peer_set_cluster(&ioctx, "uuid3", "new cluster"));
+ ASSERT_EQ(-ENOENT, mirror_peer_set_cluster(&ioctx, "uuid4", "new site"));
+ ASSERT_EQ(0, mirror_peer_set_cluster(&ioctx, "uuid3", "new site"));
ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
expected_peers = {
- {"uuid1", "cluster1", "new client", -1},
- {"uuid3", "new cluster", "admin", 123}};
+ {"uuid1", MIRROR_PEER_DIRECTION_RX, "siteA", "new client", "fsidA"},
+ {"uuid3", MIRROR_PEER_DIRECTION_RX, "new site", "admin", ""}};
ASSERT_EQ(expected_peers, peers);
- ASSERT_EQ(-EBUSY, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_DISABLED));
- ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid3"));
ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid1"));
+
+ ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
+ expected_peers = {
+ {"uuid3", MIRROR_PEER_DIRECTION_RX, "new site", "admin", ""}};
+ ASSERT_EQ(expected_peers, peers);
+
+ ASSERT_EQ(-EINVAL, mirror_peer_ping(&ioctx, "", "fsid"));
+ ASSERT_EQ(-EINVAL, mirror_peer_ping(&ioctx, "new site", ""));
+ ASSERT_EQ(0, mirror_peer_ping(&ioctx, "new site", "fsid"));
+
+ ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
+ ASSERT_EQ(1U, peers.size());
+ ASSERT_LT(utime_t{}, peers[0].last_seen);
+ expected_peers = {
+ {"uuid3", MIRROR_PEER_DIRECTION_RX_TX, "new site", "admin", "fsid"}};
+ expected_peers[0].last_seen = peers[0].last_seen;
+ ASSERT_EQ(expected_peers, peers);
+ ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid3"));
+
+ ASSERT_EQ(0, mirror_peer_ping(&ioctx, "siteA", "fsid"));
+
+ ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
+ ASSERT_EQ(1U, peers.size());
+ ASSERT_FALSE(peers[0].uuid.empty());
+ ASSERT_LT(utime_t{}, peers[0].last_seen);
+ expected_peers = {
+ {peers[0].uuid, MIRROR_PEER_DIRECTION_TX, "siteA", "", "fsid"}};
+ expected_peers[0].last_seen = peers[0].last_seen;
+ ASSERT_EQ(expected_peers, peers);
+
+ ASSERT_EQ(-EBUSY, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_DISABLED));
+ ASSERT_EQ(0, mirror_peer_remove(&ioctx, peers[0].uuid));
+
+ ASSERT_EQ(0, mirror_peer_remove(&ioctx, "DNE"));
ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
expected_peers = {};
ASSERT_EQ(expected_peers, peers);