From 0ec038abca13d4c163a96c3eb61b26f7a9ab50dd Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Thu, 18 Feb 2016 15:43:59 -0500 Subject: [PATCH] librbd: support image and pool-level mirroring modes If pool-level mirroring is enabled, all journaled images within the pool are eligible for mirroring. If image-level mirroring is enabled, mirroring needs to be explicitly enabled on each image. Signed-off-by: Jason Dillaman --- src/cls/rbd/cls_rbd.cc | 88 ++++++++++------------ src/cls/rbd/cls_rbd_client.cc | 18 +++-- src/cls/rbd/cls_rbd_client.h | 6 +- src/cls/rbd/cls_rbd_types.cc | 18 +++++ src/cls/rbd/cls_rbd_types.h | 7 ++ src/include/rbd/librbd.h | 12 ++- src/include/rbd/librbd.hpp | 4 +- src/librbd/internal.cc | 44 +++++++++-- src/librbd/internal.h | 4 +- src/librbd/librbd.cc | 22 +++--- src/test/cli/rbd/help.t | 3 +- src/test/cli/rbd/not-enough-args.t | 10 +++ src/test/cls_rbd/test_cls_rbd.cc | 25 +++--- src/test/librbd/test_librbd.cc | 19 +++-- src/test/rbd_mirror/test_ClusterWatcher.cc | 2 +- src/test/rbd_mirror/test_PoolWatcher.cc | 2 +- src/tools/rbd/action/MirrorPool.cc | 66 ++++++++++++---- src/tools/rbd_mirror/ClusterWatcher.cc | 6 +- src/tools/rbd_mirror/PoolWatcher.cc | 6 +- 19 files changed, 239 insertions(+), 123 deletions(-) diff --git a/src/cls/rbd/cls_rbd.cc b/src/cls/rbd/cls_rbd.cc index 36271dab444..5f0cb11faba 100644 --- a/src/cls/rbd/cls_rbd.cc +++ b/src/cls/rbd/cls_rbd.cc @@ -111,8 +111,8 @@ cls_method_handle_t h_old_snapshots_list; cls_method_handle_t h_old_snapshot_add; cls_method_handle_t h_old_snapshot_remove; cls_method_handle_t h_old_snapshot_rename; -cls_method_handle_t h_mirror_is_enabled; -cls_method_handle_t h_mirror_set_enabled; +cls_method_handle_t h_mirror_mode_get; +cls_method_handle_t h_mirror_mode_set; cls_method_handle_t h_mirror_peer_list; cls_method_handle_t h_mirror_peer_add; cls_method_handle_t h_mirror_peer_remove; @@ -2925,35 +2925,13 @@ int old_snapshot_rename(cls_method_context_t hctx, bufferlist *in, bufferlist *o namespace mirror { +static const std::string MODE("mirror_mode"); static const std::string PEER_KEY_PREFIX("mirror_peer_"); std::string peer_key(const std::string &uuid) { return PEER_KEY_PREFIX + uuid; } -int is_enabled(cls_method_context_t hctx, bool *enabled) { - bufferlist bl; - int r = cls_cxx_map_get_val(hctx, "mirror_enabled", &bl); - if (r < 0 && r != -ENOENT) { - CLS_ERR("error reading mirror enabled flag: %s", - cpp_strerror(r).c_str()); - return r; - } - - if (r == 0) { - try { - bufferlist::iterator bl_it = bl.begin(); - ::decode(*enabled, bl_it); - } catch (const buffer::error &err) { - CLS_ERR("could not decode flag"); - return -EIO; - } - } else { - *enabled = false; - } - return 0; -} - int read_peers(cls_method_context_t hctx, std::vector *peers) { std::string last_read = PEER_KEY_PREFIX; @@ -3024,44 +3002,58 @@ int write_peer(cls_method_context_t hctx, const std::string &uuid, * none * * Output: - * @param bool: true if enabled + * @param cls::rbd::MirrorMode (uint32_t) * @returns 0 on success, negative error code on failure */ -int mirror_is_enabled(cls_method_context_t hctx, bufferlist *in, - bufferlist *out) { - bool enabled; - int r = mirror::is_enabled(hctx, &enabled); +int mirror_mode_get(cls_method_context_t hctx, bufferlist *in, + bufferlist *out) { + uint32_t mirror_mode_decode; + int r = read_key(hctx, mirror::MODE, &mirror_mode_decode); if (r < 0) { return r; } - ::encode(enabled, *out); + ::encode(mirror_mode_decode, *out); return 0; } /** * Input: - * @param enabled (bool) + * @param mirror_mode (cls::rbd::MirrorMode) (uint32_t) * * Output: * @returns 0 on success, negative error code on failure */ -int mirror_set_enabled(cls_method_context_t hctx, bufferlist *in, - bufferlist *out) { - bool enabled; +int mirror_mode_set(cls_method_context_t hctx, bufferlist *in, + bufferlist *out) { + uint32_t mirror_mode_decode; try { bufferlist::iterator bl_it = in->begin(); - ::decode(enabled, bl_it); + ::decode(mirror_mode_decode, bl_it); } catch (const buffer::error &err) { return -EINVAL; } + bool enabled; + switch (static_cast(mirror_mode_decode)) { + case cls::rbd::MIRROR_MODE_DISABLED: + enabled = false; + break; + case cls::rbd::MIRROR_MODE_IMAGE: + case cls::rbd::MIRROR_MODE_POOL: + enabled = true; + break; + default: + CLS_ERR("invalid mirror mode: %d", mirror_mode_decode); + return -EINVAL; + } + int r; if (enabled) { bufferlist bl; - ::encode(enabled, bl); + ::encode(mirror_mode_decode, bl); - r = cls_cxx_map_set_val(hctx, "mirror_enabled", &bl); + r = cls_cxx_map_set_val(hctx, mirror::MODE, &bl); if (r < 0) { CLS_ERR("error enabling mirroring: %s", cpp_strerror(r).c_str()); return r; @@ -3078,7 +3070,7 @@ int mirror_set_enabled(cls_method_context_t hctx, bufferlist *in, return -EBUSY; } - r = cls_cxx_map_remove_key(hctx, "mirror_enabled"); + r = cls_cxx_map_remove_key(hctx, mirror::MODE); if (r < 0 && r != -ENOENT) { CLS_ERR("error disabling mirroring: %s", cpp_strerror(r).c_str()); return r; @@ -3124,12 +3116,12 @@ int mirror_peer_add(cls_method_context_t hctx, bufferlist *in, return -EINVAL; } - bool enabled; - int r = mirror::is_enabled(hctx, &enabled); - if (r < 0) { + uint32_t mirror_mode_decode; + int r = read_key(hctx, mirror::MODE, &mirror_mode_decode); + if (r < 0 && r != -ENOENT) { return r; - } - if (!enabled) { + } else if (r == -ENOENT || + mirror_mode_decode == cls::rbd::MIRROR_MODE_DISABLED) { CLS_ERR("mirroring must be enabled on the pool"); return -EINVAL; } @@ -3414,11 +3406,11 @@ void __cls_init() old_snapshot_rename, &h_old_snapshot_rename); /* methods for the rbd_pool_settings object */ - cls_register_cxx_method(h_class, "mirror_is_enabled", CLS_METHOD_RD, - mirror_is_enabled, &h_mirror_is_enabled); - cls_register_cxx_method(h_class, "mirror_set_enabled", + cls_register_cxx_method(h_class, "mirror_mode_get", CLS_METHOD_RD, + mirror_mode_get, &h_mirror_mode_get); + cls_register_cxx_method(h_class, "mirror_mode_set", CLS_METHOD_RD | CLS_METHOD_WR, - mirror_set_enabled, &h_mirror_set_enabled); + mirror_mode_set, &h_mirror_mode_set); 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", diff --git a/src/cls/rbd/cls_rbd_client.cc b/src/cls/rbd/cls_rbd_client.cc index d8199e5de68..06a2c03ddb5 100644 --- a/src/cls/rbd/cls_rbd_client.cc +++ b/src/cls/rbd/cls_rbd_client.cc @@ -968,13 +968,14 @@ namespace librbd { return 0; } - int mirror_is_enabled(librados::IoCtx *ioctx, bool *enabled) { + int mirror_mode_get(librados::IoCtx *ioctx, + cls::rbd::MirrorMode *mirror_mode) { bufferlist in_bl; bufferlist out_bl; - int r = ioctx->exec(RBD_POOL_SETTINGS, "rbd", "mirror_is_enabled", in_bl, + int r = ioctx->exec(RBD_POOL_SETTINGS, "rbd", "mirror_mode_get", in_bl, out_bl); if (r == -ENOENT) { - *enabled = false; + *mirror_mode = cls::rbd::MIRROR_MODE_DISABLED; return 0; } else if (r < 0) { return r; @@ -982,19 +983,22 @@ namespace librbd { try { bufferlist::iterator bl_it = out_bl.begin(); - ::decode(*enabled, bl_it); + uint32_t mirror_mode_decode; + ::decode(mirror_mode_decode, bl_it); + *mirror_mode = static_cast(mirror_mode_decode); } catch (const buffer::error &err) { return -EBADMSG; } return 0; } - int mirror_set_enabled(librados::IoCtx *ioctx, bool enabled) { + int mirror_mode_set(librados::IoCtx *ioctx, + cls::rbd::MirrorMode mirror_mode) { bufferlist in_bl; - ::encode(enabled, in_bl); + ::encode(static_cast(mirror_mode), in_bl); bufferlist out_bl; - int r = ioctx->exec(RBD_POOL_SETTINGS, "rbd", "mirror_set_enabled", in_bl, + int r = ioctx->exec(RBD_POOL_SETTINGS, "rbd", "mirror_mode_set", in_bl, out_bl); if (r < 0) { return r; diff --git a/src/cls/rbd/cls_rbd_client.h b/src/cls/rbd/cls_rbd_client.h index 928158a42f0..f749867f5b4 100644 --- a/src/cls/rbd/cls_rbd_client.h +++ b/src/cls/rbd/cls_rbd_client.h @@ -204,8 +204,10 @@ namespace librbd { ::SnapContext *snapc); // operations on the rbd_pool_settings object - int mirror_is_enabled(librados::IoCtx *ioctx, bool *enabled); - int mirror_set_enabled(librados::IoCtx *ioctx, bool enabled); + int mirror_mode_get(librados::IoCtx *ioctx, + cls::rbd::MirrorMode *mirror_mode); + int mirror_mode_set(librados::IoCtx *ioctx, + cls::rbd::MirrorMode mirror_mode); int mirror_peer_list(librados::IoCtx *ioctx, std::vector *peers); int mirror_peer_add(librados::IoCtx *ioctx, const std::string &cluster_uuid, diff --git a/src/cls/rbd/cls_rbd_types.cc b/src/cls/rbd/cls_rbd_types.cc index dca84c54e65..02554cc82e4 100644 --- a/src/cls/rbd/cls_rbd_types.cc +++ b/src/cls/rbd/cls_rbd_types.cc @@ -40,6 +40,24 @@ bool MirrorPeer::operator==(const MirrorPeer &rhs) const { client_name == rhs.client_name); } +std::ostream& operator<<(std::ostream& os, const MirrorMode& mirror_mode) { + switch (mirror_mode) { + case MIRROR_MODE_DISABLED: + os << "disabled"; + break; + case MIRROR_MODE_IMAGE: + os << "image"; + break; + case MIRROR_MODE_POOL: + os << "pool"; + break; + default: + os << "unknown (" << static_cast(mirror_mode) << ")"; + break; + } + return os; +} + std::ostream& operator<<(std::ostream& os, const MirrorPeer& peer) { os << "[" << "cluster_uuid=" << peer.cluster_uuid << ", " diff --git a/src/cls/rbd/cls_rbd_types.h b/src/cls/rbd/cls_rbd_types.h index a4564ce8421..55be86d8bf5 100644 --- a/src/cls/rbd/cls_rbd_types.h +++ b/src/cls/rbd/cls_rbd_types.h @@ -15,6 +15,12 @@ namespace ceph { class Formatter; } namespace cls { namespace rbd { +enum MirrorMode { + MIRROR_MODE_DISABLED = 0, + MIRROR_MODE_IMAGE = 1, + MIRROR_MODE_POOL = 2 +}; + struct MirrorPeer { MirrorPeer() { } @@ -37,6 +43,7 @@ struct MirrorPeer { bool operator==(const MirrorPeer &rhs) const; }; +std::ostream& operator<<(std::ostream& os, const MirrorMode& mirror_mode); std::ostream& operator<<(std::ostream& os, const MirrorPeer& peer); WRITE_CLASS_ENCODER(MirrorPeer); diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index dde1a61934b..0ee602145d0 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -89,6 +89,12 @@ typedef struct { char parent_name[RBD_MAX_IMAGE_NAME_SIZE]; /* deprecated */ } rbd_image_info_t; +typedef enum { + RBD_MIRROR_MODE_DISABLED, /* mirroring is disabled */ + RBD_MIRROR_MODE_IMAGE, /* mirroring enabled on a per-image basis */ + RBD_MIRROR_MODE_POOL /* mirroring enabled on all journaled images */ +} rbd_mirror_mode_t; + typedef struct { char *cluster_uuid; char *cluster_name; @@ -170,8 +176,10 @@ CEPH_RBD_API int rbd_rename(rados_ioctx_t src_io_ctx, const char *srcname, const char *destname); /* pool mirroring */ -CEPH_RBD_API int rbd_mirror_is_enabled(rados_ioctx_t io_ctx, bool *enabled); -CEPH_RBD_API int rbd_mirror_set_enabled(rados_ioctx_t io_ctx, bool enabled); +CEPH_RBD_API int rbd_mirror_mode_get(rados_ioctx_t io_ctx, + rbd_mirror_mode_t *mirror_mode); +CEPH_RBD_API int rbd_mirror_mode_set(rados_ioctx_t io_ctx, + rbd_mirror_mode_t mirror_mode); CEPH_RBD_API int rbd_mirror_peer_add(rados_ioctx_t io_ctx, const char *cluster_uuid, const char *cluster_name, diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 7a4a2c7bdda..13590554441 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -113,8 +113,8 @@ public: int rename(IoCtx& src_io_ctx, const char *srcname, const char *destname); // RBD pool mirroring support functions - int mirror_is_enabled(IoCtx& io_ctx, bool *enabled); - int mirror_set_enabled(IoCtx& io_ctx, bool enabled); + int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode); + int mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode); int mirror_peer_add(IoCtx& io_ctx, const std::string &cluster_uuid, const std::string &cluster_name, const std::string &client_name); diff --git a/src/librbd/internal.cc b/src/librbd/internal.cc index 36beb1d368d..d173197bf58 100644 --- a/src/librbd/internal.cc +++ b/src/librbd/internal.cc @@ -2296,26 +2296,54 @@ int validate_pool(IoCtx &io_ctx, CephContext *cct) { return cls_client::metadata_list(&ictx->md_ctx, ictx->header_oid, start, max, pairs); } - int mirror_is_enabled(IoCtx& io_ctx, bool *enabled) { + int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode) { CephContext *cct = reinterpret_cast(io_ctx.cct()); ldout(cct, 20) << __func__ << dendl; - int r = cls_client::mirror_is_enabled(&io_ctx, enabled); + cls::rbd::MirrorMode mirror_mode_internal; + int r = cls_client::mirror_mode_get(&io_ctx, &mirror_mode_internal); if (r < 0) { - lderr(cct) << "Failed to retrieve mirror flag: " << cpp_strerror(r) + lderr(cct) << "Failed to retrieve mirror mode: " << cpp_strerror(r) << dendl; return r; } + + switch (mirror_mode_internal) { + case cls::rbd::MIRROR_MODE_DISABLED: + case cls::rbd::MIRROR_MODE_IMAGE: + case cls::rbd::MIRROR_MODE_POOL: + *mirror_mode = static_cast(mirror_mode_internal); + break; + default: + lderr(cct) << "Unknown mirror mode (" + << static_cast(mirror_mode_internal) << ")" + << dendl; + return -EINVAL; + } return 0; } - int mirror_set_enabled(IoCtx& io_ctx, bool enabled) { + int mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode) { CephContext *cct = reinterpret_cast(io_ctx.cct()); - ldout(cct, 20) << __func__ << ": enabled=" << enabled << dendl; + ldout(cct, 20) << __func__ << dendl; - int r = cls_client::mirror_set_enabled(&io_ctx, enabled); - if (r < 0 && r != -ENOENT) { - lderr(cct) << "Failed to set mirror flag: " << cpp_strerror(r) << dendl; + cls::rbd::MirrorMode mirror_mode_internal; + switch (mirror_mode) { + case RBD_MIRROR_MODE_DISABLED: + case RBD_MIRROR_MODE_IMAGE: + case RBD_MIRROR_MODE_POOL: + mirror_mode_internal = static_cast( + mirror_mode); + break; + default: + lderr(cct) << "Unknown mirror mode (" + << static_cast(mirror_mode) << ")" << dendl; + return -EINVAL; + } + + int r = cls_client::mirror_mode_set(&io_ctx, mirror_mode_internal); + if (r < 0) { + lderr(cct) << "Failed to set mirror mode: " << cpp_strerror(r) << dendl; return r; } return 0; diff --git a/src/librbd/internal.h b/src/librbd/internal.h index b5179df173a..a377562a412 100644 --- a/src/librbd/internal.h +++ b/src/librbd/internal.h @@ -171,8 +171,8 @@ namespace librbd { int metadata_set(ImageCtx *ictx, const std::string &key, const std::string &value); int metadata_remove(ImageCtx *ictx, const std::string &key); - int mirror_is_enabled(IoCtx& io_ctx, bool *enabled); - int mirror_set_enabled(IoCtx& io_ctx, bool enabled); + int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode); + int mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode); int mirror_peer_add(IoCtx& io_ctx, const std::string &cluster_uuid, const std::string &cluster_name, const std::string &client_name); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 4a47ab25760..d48f5ef86f3 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -379,12 +379,12 @@ namespace librbd { return r; } - int RBD::mirror_is_enabled(IoCtx& io_ctx, bool *enabled) { - return librbd::mirror_is_enabled(io_ctx, enabled); + int RBD::mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode) { + return librbd::mirror_mode_get(io_ctx, mirror_mode); } - int RBD::mirror_set_enabled(IoCtx& io_ctx, bool enabled) { - return librbd::mirror_set_enabled(io_ctx, enabled); + int RBD::mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode) { + return librbd::mirror_mode_set(io_ctx, mirror_mode); } int RBD::mirror_peer_add(IoCtx& io_ctx, const std::string &cluster_uuid, @@ -1305,20 +1305,18 @@ extern "C" int rbd_image_options_is_empty(rbd_image_options_t opts) } /* pool mirroring */ -extern "C" int rbd_mirror_is_enabled(rados_ioctx_t p, bool *enabled) { +extern "C" int rbd_mirror_mode_get(rados_ioctx_t p, + rbd_mirror_mode_t *mirror_mode) { librados::IoCtx io_ctx; librados::IoCtx::from_rados_ioctx_t(p, io_ctx); - int r = librbd::mirror_is_enabled(io_ctx, enabled); - if (r < 0) { - return r; - } - return 0; + return librbd::mirror_mode_get(io_ctx, mirror_mode); } -extern "C" int rbd_mirror_set_enabled(rados_ioctx_t p, bool enabled) { +extern "C" int rbd_mirror_mode_set(rados_ioctx_t p, + rbd_mirror_mode_t mirror_mode) { librados::IoCtx io_ctx; librados::IoCtx::from_rados_ioctx_t(p, io_ctx); - return librbd::mirror_set_enabled(io_ctx, enabled); + return librbd::mirror_mode_set(io_ctx, mirror_mode); } extern "C" int rbd_mirror_peer_add(rados_ioctx_t p, diff --git a/src/test/cli/rbd/help.t b/src/test/cli/rbd/help.t index 6832012631a..fb2e6edf58e 100644 --- a/src/test/cli/rbd/help.t +++ b/src/test/cli/rbd/help.t @@ -756,12 +756,13 @@ rbd help mirror pool enable usage: rbd mirror pool enable [--pool ] - + Enable RBD mirroring by default within a pool. Positional arguments pool name + mirror mode [image or pool] Optional arguments -p [ --pool ] arg pool name diff --git a/src/test/cli/rbd/not-enough-args.t b/src/test/cli/rbd/not-enough-args.t index 10283a3cd4b..a63fcdb15d5 100644 --- a/src/test/cli/rbd/not-enough-args.t +++ b/src/test/cli/rbd/not-enough-args.t @@ -190,3 +190,13 @@ $ rbd bench-write rbd: image name was not specified [22] + $ rbd mirror pool enable rbd + rbd: must specify 'image' or 'pool' mode. + [22] + $ rbd mirror pool peer add rbd + rbd: remote cluster was not specified + [22] + $ rbd mirror pool peer remove rbd + rbd: must specify cluster uuid + [22] + diff --git a/src/test/cls_rbd/test_cls_rbd.cc b/src/test/cls_rbd/test_cls_rbd.cc index 218505d5cf0..a4218fa9ff7 100644 --- a/src/test/cls_rbd/test_cls_rbd.cc +++ b/src/test/cls_rbd/test_cls_rbd.cc @@ -1293,12 +1293,17 @@ TEST_F(TestClsRbd, mirror) { ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client")); - bool enabled; - ASSERT_EQ(0, mirror_is_enabled(&ioctx, &enabled)); - ASSERT_FALSE(enabled); - ASSERT_EQ(0, mirror_set_enabled(&ioctx, true)); - ASSERT_EQ(0, mirror_is_enabled(&ioctx, &enabled)); - ASSERT_TRUE(enabled); + cls::rbd::MirrorMode mirror_mode; + ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode)); + ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED, mirror_mode); + + ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_IMAGE)); + ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode)); + ASSERT_EQ(cls::rbd::MIRROR_MODE_IMAGE, mirror_mode); + + ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_POOL)); + ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode)); + ASSERT_EQ(cls::rbd::MIRROR_MODE_POOL, mirror_mode); ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client")); ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid2", "cluster2", "admin")); @@ -1327,7 +1332,7 @@ TEST_F(TestClsRbd, mirror) { {"uuid1", "cluster1", "new client"}, {"uuid3", "new cluster", "admin"}}; ASSERT_EQ(expected_peers, peers); - ASSERT_EQ(-EBUSY, mirror_set_enabled(&ioctx, false)); + 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")); @@ -1335,7 +1340,7 @@ TEST_F(TestClsRbd, mirror) { expected_peers = {}; ASSERT_EQ(expected_peers, peers); - ASSERT_EQ(0, mirror_set_enabled(&ioctx, false)); - ASSERT_EQ(0, mirror_is_enabled(&ioctx, &enabled)); - ASSERT_FALSE(enabled); + ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_DISABLED)); + ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode)); + ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED, mirror_mode); } diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index 25c28f8d266..7f0fc4be15e 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -4048,12 +4048,17 @@ TEST_F(TestLibRBD, Mirror) { ASSERT_EQ(-EINVAL, rbd.mirror_peer_add(ioctx, "uuid1", "cluster1", "client")); - bool enabled; - ASSERT_EQ(0, rbd.mirror_is_enabled(ioctx, &enabled)); - ASSERT_FALSE(enabled); - ASSERT_EQ(0, rbd.mirror_set_enabled(ioctx, true)); - ASSERT_EQ(0, rbd.mirror_is_enabled(ioctx, &enabled)); - ASSERT_TRUE(enabled); + rbd_mirror_mode_t mirror_mode; + ASSERT_EQ(0, rbd.mirror_mode_get(ioctx, &mirror_mode)); + ASSERT_EQ(RBD_MIRROR_MODE_DISABLED, mirror_mode); + + ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_IMAGE)); + ASSERT_EQ(0, rbd.mirror_mode_get(ioctx, &mirror_mode)); + ASSERT_EQ(RBD_MIRROR_MODE_IMAGE, mirror_mode); + + ASSERT_EQ(0, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_POOL)); + ASSERT_EQ(0, rbd.mirror_mode_get(ioctx, &mirror_mode)); + ASSERT_EQ(RBD_MIRROR_MODE_POOL, mirror_mode); ASSERT_EQ(0, rbd.mirror_peer_add(ioctx, "uuid1", "cluster1", "client")); ASSERT_EQ(0, rbd.mirror_peer_add(ioctx, "uuid2", "cluster2", "admin")); @@ -4084,5 +4089,5 @@ TEST_F(TestLibRBD, Mirror) { {"uuid3", "new cluster", "admin"}}; ASSERT_EQ(expected_peers, peers); - ASSERT_EQ(-EBUSY, rbd.mirror_set_enabled(ioctx, false)); + ASSERT_EQ(-EBUSY, rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_DISABLED)); } diff --git a/src/test/rbd_mirror/test_ClusterWatcher.cc b/src/test/rbd_mirror/test_ClusterWatcher.cc index 97f485979c5..35d5b2c3380 100644 --- a/src/test/rbd_mirror/test_ClusterWatcher.cc +++ b/src/test/rbd_mirror/test_ClusterWatcher.cc @@ -51,7 +51,7 @@ public: if (enable_mirroring) { librados::IoCtx ioctx; ASSERT_EQ(0, m_cluster->ioctx_create2(pool_id, ioctx)); - ASSERT_EQ(0, librbd::mirror_set_enabled(ioctx, true)); + ASSERT_EQ(0, librbd::mirror_mode_set(ioctx, RBD_MIRROR_MODE_POOL)); ASSERT_EQ(0, librbd::mirror_peer_add(ioctx, peer.cluster_uuid, peer.cluster_name, peer.client_name)); diff --git a/src/test/rbd_mirror/test_PoolWatcher.cc b/src/test/rbd_mirror/test_PoolWatcher.cc index d176828606d..57bdb4defee 100644 --- a/src/test/rbd_mirror/test_PoolWatcher.cc +++ b/src/test/rbd_mirror/test_PoolWatcher.cc @@ -61,7 +61,7 @@ TestPoolWatcher() : m_lock("TestPoolWatcherLock"), if (enable_mirroring) { librados::IoCtx ioctx; ASSERT_EQ(0, m_cluster->ioctx_create2(pool_id, ioctx)); - ASSERT_EQ(0, librbd::mirror_set_enabled(ioctx, true)); + ASSERT_EQ(0, librbd::mirror_mode_set(ioctx, RBD_MIRROR_MODE_POOL)); ASSERT_EQ(0, librbd::mirror_peer_add(ioctx, peer.cluster_uuid, peer.cluster_name, peer.client_name)); diff --git a/src/tools/rbd/action/MirrorPool.cc b/src/tools/rbd/action/MirrorPool.cc index 4d37ec129f0..f71118de193 100644 --- a/src/tools/rbd/action/MirrorPool.cc +++ b/src/tools/rbd/action/MirrorPool.cc @@ -302,15 +302,20 @@ int execute_peer_set(const po::variables_map &vm) { return 0; } -void get_enable_disable_arguments(po::options_description *positional, - po::options_description *options) { +void get_disable_arguments(po::options_description *positional, + po::options_description *options) { at::add_pool_options(positional, options); } -int execute_enable_disable(const po::variables_map &vm, bool enabled) { - size_t arg_index = 0; - std::string pool_name = utils::get_pool_name(vm, &arg_index); +void get_enable_arguments(po::options_description *positional, + po::options_description *options) { + at::add_pool_options(positional, options); + positional->add_options() + ("mode", "mirror mode [image or pool]"); +} +int execute_enable_disable(const std::string &pool_name, + rbd_mirror_mode_t mirror_mode) { librados::Rados rados; librados::IoCtx io_ctx; int r = utils::init(pool_name, &rados, &io_ctx); @@ -319,7 +324,7 @@ int execute_enable_disable(const po::variables_map &vm, bool enabled) { } librbd::RBD rbd; - r = rbd.mirror_set_enabled(io_ctx, enabled); + r = rbd.mirror_mode_set(io_ctx, mirror_mode); if (r < 0) { return r; } @@ -327,11 +332,28 @@ int execute_enable_disable(const po::variables_map &vm, bool enabled) { } int execute_disable(const po::variables_map &vm) { - return execute_enable_disable(vm, false); + size_t arg_index = 0; + std::string pool_name = utils::get_pool_name(vm, &arg_index); + + return execute_enable_disable(pool_name, RBD_MIRROR_MODE_DISABLED); } int execute_enable(const po::variables_map &vm) { - return execute_enable_disable(vm, true); + size_t arg_index = 0; + std::string pool_name = utils::get_pool_name(vm, &arg_index); + + rbd_mirror_mode_t mirror_mode; + std::string mode = utils::get_positional_argument(vm, arg_index++); + if (mode == "image") { + mirror_mode = RBD_MIRROR_MODE_IMAGE; + } else if (mode == "pool") { + mirror_mode = RBD_MIRROR_MODE_POOL; + } else { + std::cerr << "rbd: must specify 'image' or 'pool' mode." << std::endl; + return -EINVAL; + } + + return execute_enable_disable(pool_name, mirror_mode); } void get_info_arguments(po::options_description *positional, @@ -363,8 +385,8 @@ int execute_info(const po::variables_map &vm) { } librbd::RBD rbd; - bool enabled; - r = rbd.mirror_is_enabled(io_ctx, &enabled); + rbd_mirror_mode_t mirror_mode; + r = rbd.mirror_mode_get(io_ctx, &mirror_mode); if (r < 0) { return r; } @@ -375,11 +397,27 @@ int execute_info(const po::variables_map &vm) { return r; } + std::string mirror_mode_desc; + switch (mirror_mode) { + case RBD_MIRROR_MODE_DISABLED: + mirror_mode_desc = "disabled"; + break; + case RBD_MIRROR_MODE_IMAGE: + mirror_mode_desc = "image"; + break; + case RBD_MIRROR_MODE_POOL: + mirror_mode_desc = "pool"; + break; + default: + mirror_mode_desc = "unknown"; + break; + } + if (formatter != nullptr) { formatter->open_object_section("mirror"); - formatter->dump_bool("enabled", enabled); + formatter->dump_string("mode", mirror_mode_desc); } else { - std::cout << "Enabled: " << (enabled ? "true" : "false") << std::endl; + std::cout << "Mode: " << mirror_mode_desc << std::endl; } format_mirror_peers(config_path, formatter, mirror_peers); @@ -406,11 +444,11 @@ Shell::Action action_set( Shell::Action action_disable( {"mirror", "pool", "disable"}, {}, "Disable RBD mirroring by default within a pool.", "", - &get_enable_disable_arguments, &execute_disable); + &get_disable_arguments, &execute_disable); Shell::Action action_enable( {"mirror", "pool", "enable"}, {}, "Enable RBD mirroring by default within a pool.", "", - &get_enable_disable_arguments, &execute_enable); + &get_enable_arguments, &execute_enable); Shell::Action action_info( {"mirror", "pool", "info"}, {}, "Show information about the pool mirroring configuration.", {}, diff --git a/src/tools/rbd_mirror/ClusterWatcher.cc b/src/tools/rbd_mirror/ClusterWatcher.cc index 91a7c5a3e3c..be3b6ad4049 100644 --- a/src/tools/rbd_mirror/ClusterWatcher.cc +++ b/src/tools/rbd_mirror/ClusterWatcher.cc @@ -94,14 +94,14 @@ void ClusterWatcher::read_configs(map > *peer_configs, continue; } - bool enabled; - r = librbd::mirror_is_enabled(ioctx, &enabled); + rbd_mirror_mode_t mirror_mode; + r = librbd::mirror_mode_get(ioctx, &mirror_mode); if (r < 0) { derr << "could not tell whether mirroring was enabled for " << pool_name << " : " << cpp_strerror(r) << dendl; continue; } - if (!enabled) { + if (mirror_mode == RBD_MIRROR_MODE_DISABLED) { dout(10) << "mirroring is disabled for pool " << pool_name << dendl; continue; } diff --git a/src/tools/rbd_mirror/PoolWatcher.cc b/src/tools/rbd_mirror/PoolWatcher.cc index 480df57cf8e..f55eee5a154 100644 --- a/src/tools/rbd_mirror/PoolWatcher.cc +++ b/src/tools/rbd_mirror/PoolWatcher.cc @@ -95,14 +95,14 @@ void PoolWatcher::refresh_images(bool reschedule) // TODO: read mirrored images from mirroring settings object. For // now just treat all images in a pool with mirroring enabled as mirrored - bool enabled; - r = librbd::mirror_is_enabled(ioctx, &enabled); + rbd_mirror_mode_t mirror_mode; + r = librbd::mirror_mode_get(ioctx, &mirror_mode); if (r < 0) { derr << "could not tell whether mirroring was enabled for " << pool_name << " : " << cpp_strerror(r) << dendl; continue; } - if (!enabled) { + if (mirror_mode == RBD_MIRROR_MODE_DISABLED) { dout(20) << "pool " << pool_name << " has mirroring disabled" << dendl; continue; } -- 2.39.5