]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: support image and pool-level mirroring modes
authorJason Dillaman <dillaman@redhat.com>
Thu, 18 Feb 2016 20:43:59 +0000 (15:43 -0500)
committerJason Dillaman <dillaman@redhat.com>
Fri, 19 Feb 2016 21:12:12 +0000 (16:12 -0500)
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 <dillaman@redhat.com>
19 files changed:
src/cls/rbd/cls_rbd.cc
src/cls/rbd/cls_rbd_client.cc
src/cls/rbd/cls_rbd_client.h
src/cls/rbd/cls_rbd_types.cc
src/cls/rbd/cls_rbd_types.h
src/include/rbd/librbd.h
src/include/rbd/librbd.hpp
src/librbd/internal.cc
src/librbd/internal.h
src/librbd/librbd.cc
src/test/cli/rbd/help.t
src/test/cli/rbd/not-enough-args.t
src/test/cls_rbd/test_cls_rbd.cc
src/test/librbd/test_librbd.cc
src/test/rbd_mirror/test_ClusterWatcher.cc
src/test/rbd_mirror/test_PoolWatcher.cc
src/tools/rbd/action/MirrorPool.cc
src/tools/rbd_mirror/ClusterWatcher.cc
src/tools/rbd_mirror/PoolWatcher.cc

index 36271dab4443eb8f039079f5ad90410ccd88a2f5..5f0cb11fabaddc14839f59ead9cdc3e162defdc2 100644 (file)
@@ -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<cls::rbd::MirrorPeer> *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<cls::rbd::MirrorMode>(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",
index d8199e5de680295283c386fefc39438c72013c7b..06a2c03ddb5c10bd2f2eed1294e17da5840d1822 100644 (file)
@@ -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<cls::rbd::MirrorMode>(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<uint32_t>(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;
index 928158a42f086b5749be3cd06993cda088ae6b5b..f749867f5b4e458288a02deb72eb547809bf6771 100644 (file)
@@ -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<cls::rbd::MirrorPeer> *peers);
     int mirror_peer_add(librados::IoCtx *ioctx, const std::string &cluster_uuid,
index dca84c54e658315fab7c6fc129d9c9403b400d64..02554cc82e4d72a185903f86e3a8eb685441c5ce 100644 (file)
@@ -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<uint32_t>(mirror_mode) << ")";
+    break;
+  }
+  return os;
+}
+
 std::ostream& operator<<(std::ostream& os, const MirrorPeer& peer) {
   os << "["
      << "cluster_uuid=" << peer.cluster_uuid << ", "
index a4564ce84215b4686d7609c785a8a2d123562378..55be86d8bf51de235d37c5baf14eff30deef58c9 100644 (file)
@@ -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);
index dde1a61934bdc0e8e5302ea36fbbf5b25b0775ce..0ee602145d01a5c488dc35e6c3bc8c57ddbffd63 100644 (file)
@@ -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,
index 7a4a2c7bdda6dfdbc869f78bbcd279f5deb4168e..13590554441dfe57dd861b30f3debdd96da708b7 100644 (file)
@@ -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);
index 36beb1d368d482eac57a26d78971ddd1a8e568fd..d173197bf58dbba84649dd31058f1d4a099cc527 100644 (file)
@@ -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<CephContext *>(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<rbd_mirror_mode_t>(mirror_mode_internal);
+      break;
+    default:
+      lderr(cct) << "Unknown mirror mode ("
+                 << static_cast<uint32_t>(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<CephContext *>(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<cls::rbd::MirrorMode>(
+        mirror_mode);
+      break;
+    default:
+      lderr(cct) << "Unknown mirror mode ("
+                 << static_cast<uint32_t>(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;
index b5179df173a7cb61e86bd3efbe94c5b8c3debe1c..a377562a41262a88970c37b59ce55119ffab3b31 100644 (file)
@@ -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);
index 4a47ab25760aae9615de99637f43b910b35a5a07..d48f5ef86f368c440f6cd6cce0a6100e6e1e9774 100644 (file)
@@ -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,
index 6832012631af9c3c2960d73a1ee3a4d40ea412c7..fb2e6edf58ef8409d1e306d8777b13da93c1bdd7 100644 (file)
   
   rbd help mirror pool enable
   usage: rbd mirror pool enable [--pool <pool>] 
-                                <pool-name> 
+                                <pool-name> <mode> 
   
   Enable RBD mirroring by default within a pool.
   
   Positional arguments
     <pool-name>          pool name
+    <mode>               mirror mode [image or pool]
   
   Optional arguments
     -p [ --pool ] arg    pool name
index 10283a3cd4beed4c7423a9724ad0c11760574d9c..a63fcdb15d52a6e8904682e728336c21ff6fd527 100644 (file)
   $ 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]
+
index 218505d5cf02ab8bb349dc6fdde4c1203dab6436..a4218fa9ff7eb99000ec547819f593748d82520e 100644 (file)
@@ -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);
 }
index 25c28f8d266156d755a8d1ec3c1b4b48fe3cf044..7f0fc4be15e4ecd1f8ba5ad6b861c37be662f4e5 100644 (file)
@@ -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));
 }
index 97f485979c506437b2ff1cb6840901ea41064a60..35d5b2c3380977d58662c690fc74e252cab9afd2 100644 (file)
@@ -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));
index d176828606d21f6a12dfeb6070b5b3b43525d954..57bdb4defee27d76261e927e8425ddca36880eb7 100644 (file)
@@ -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));
index 4d37ec129f0de112aaf869b040d7e327bd166a45..f71118de193f9731a07eba9a1c3be1d85169f283 100644 (file)
@@ -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.", {},
index 91a7c5a3e3c51ec002543f25dbc215a3d55206cc..be3b6ad40498cc713e857c17a80db06cf63548d1 100644 (file)
@@ -94,14 +94,14 @@ void ClusterWatcher::read_configs(map<peer_t, set<int64_t> > *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;
     }
index 480df57cf8e98c7f76200a774a28fcbec7d2d490..f55eee5a1548abb56b59790cbd74afd3c6981cc4 100644 (file)
@@ -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;
     }