]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: check image mirroring state when bootstrapping
authorMykola Golub <mgolub@mirantis.com>
Mon, 9 Jan 2017 09:40:46 +0000 (10:40 +0100)
committerNathan Cutler <ncutler@suse.com>
Tue, 4 Jul 2017 20:49:01 +0000 (22:49 +0200)
Fixes: http://tracker.ceph.com/issues/18447
Signed-off-by: Mykola Golub <mgolub@mirantis.com>
(cherry picked from commit 5fc5a8ac895524f05eed6e7db20b0dda3a8cb60f)

src/test/rbd_mirror/test_ImageReplayer.cc
src/tools/rbd_mirror/image_replayer/IsPrimaryRequest.cc
src/tools/rbd_mirror/image_replayer/IsPrimaryRequest.h

index 9916e362e57c3685748eff3b1e66bb7d84ddf8c1..5bd6c53a469803ec95d760504369495ab7a6983a 100644 (file)
@@ -99,6 +99,7 @@ public:
 
     EXPECT_EQ(0, m_remote_cluster.ioctx_create(m_remote_pool_name.c_str(),
                                               m_remote_ioctx));
+    EXPECT_EQ(0, librbd::mirror_mode_set(m_remote_ioctx, RBD_MIRROR_MODE_POOL));
 
     m_image_name = get_temp_image_name();
     uint64_t features = librbd::util::get_rbd_default_features(g_ceph_context);
@@ -392,7 +393,7 @@ TEST_F(TestImageReplayer, BootstrapErrorLocalImageExists)
 
 TEST_F(TestImageReplayer, BootstrapErrorNoJournal)
 {
-  // disable remote journal journaling
+  // disable remote image journaling
   librbd::ImageCtx *ictx;
   open_remote_image(&ictx);
   uint64_t features;
@@ -407,6 +408,58 @@ TEST_F(TestImageReplayer, BootstrapErrorNoJournal)
   ASSERT_EQ(-ENOENT, cond.wait());
 }
 
+TEST_F(TestImageReplayer, BootstrapErrorMirrorDisabled)
+{
+  // disable remote image mirroring
+  ASSERT_EQ(0, librbd::mirror_mode_set(m_remote_ioctx, RBD_MIRROR_MODE_IMAGE));
+  librbd::ImageCtx *ictx;
+  open_remote_image(&ictx);
+  ASSERT_EQ(0, librbd::mirror_image_disable(ictx, true));
+  close_image(ictx);
+
+  create_replayer<>();
+  C_SaferCond cond;
+  m_replayer->start(&cond);
+  ASSERT_EQ(-ENOENT, cond.wait());
+}
+
+TEST_F(TestImageReplayer, BootstrapMirrorDisabling)
+{
+  // set remote image mirroring state to DISABLING
+  ASSERT_EQ(0, librbd::mirror_mode_set(m_remote_ioctx, RBD_MIRROR_MODE_IMAGE));
+  librbd::ImageCtx *ictx;
+  open_remote_image(&ictx);
+  ASSERT_EQ(0, librbd::mirror_image_enable(ictx));
+  cls::rbd::MirrorImage mirror_image;
+  ASSERT_EQ(0, librbd::cls_client::mirror_image_get(&m_remote_ioctx, ictx->id,
+                                                    &mirror_image));
+  mirror_image.state = cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_DISABLING;
+  ASSERT_EQ(0, librbd::cls_client::mirror_image_set(&m_remote_ioctx, ictx->id,
+                                                    mirror_image));
+  close_image(ictx);
+
+  create_replayer<>();
+  C_SaferCond cond;
+  m_replayer->start(&cond);
+  ASSERT_EQ(0, cond.wait());
+  ASSERT_TRUE(m_replayer->is_stopped());
+}
+
+TEST_F(TestImageReplayer, BootstrapDemoted)
+{
+  // demote remote image
+  librbd::ImageCtx *ictx;
+  open_remote_image(&ictx);
+  ASSERT_EQ(0, librbd::mirror_image_demote(ictx));
+  close_image(ictx);
+
+  create_replayer<>();
+  C_SaferCond cond;
+  m_replayer->start(&cond);
+  ASSERT_EQ(0, cond.wait());
+  ASSERT_TRUE(m_replayer->is_stopped());
+}
+
 TEST_F(TestImageReplayer, StartInterrupted)
 {
   create_replayer<>();
index a9169f0808a1cf1c3087c8b252b17ce13a081e9c..8a45a95081bef97e39a133a558f465902b5ec272 100644 (file)
@@ -4,6 +4,7 @@
 #include "IsPrimaryRequest.h"
 #include "common/errno.h"
 #include "common/WorkQueue.h"
+#include "cls/rbd/cls_rbd_client.h"
 #include "librbd/ImageCtx.h"
 #include "librbd/Journal.h"
 #include "librbd/Utils.h"
@@ -20,6 +21,7 @@ namespace mirror {
 namespace image_replayer {
 
 using librbd::util::create_context_callback;
+using librbd::util::create_rados_ack_callback;
 
 template <typename I>
 IsPrimaryRequest<I>::IsPrimaryRequest(I *image_ctx, bool *primary,
@@ -29,7 +31,53 @@ IsPrimaryRequest<I>::IsPrimaryRequest(I *image_ctx, bool *primary,
 
 template <typename I>
 void IsPrimaryRequest<I>::send() {
-  send_is_tag_owner();
+  send_get_mirror_state();
+}
+
+template <typename I>
+void IsPrimaryRequest<I>::send_get_mirror_state() {
+  dout(20) << dendl;
+
+  librados::ObjectReadOperation op;
+  librbd::cls_client::mirror_image_get_start(&op, m_image_ctx->id);
+
+  librados::AioCompletion *aio_comp = create_rados_ack_callback<
+    IsPrimaryRequest<I>, &IsPrimaryRequest<I>::handle_get_mirror_state>(this);
+  int r = m_image_ctx->md_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op,
+                                          &m_out_bl);
+  assert(r == 0);
+  aio_comp->release();
+}
+
+template <typename I>
+void IsPrimaryRequest<I>::handle_get_mirror_state(int r) {
+  dout(20) << ": r=" << r << dendl;
+
+  cls::rbd::MirrorImage mirror_image;
+  if (r == 0) {
+    bufferlist::iterator iter = m_out_bl.begin();
+    r = librbd::cls_client::mirror_image_get_finish(&iter, &mirror_image);
+    if (r == 0) {
+      if (mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
+        send_is_tag_owner();
+        return;
+      } else if (mirror_image.state == cls::rbd::MIRROR_IMAGE_STATE_DISABLING) {
+        dout(5) << ": image mirroring is being disabled" << dendl;
+        *m_primary = false;
+      } else {
+        derr << ": image mirroring is disabled" << dendl;
+        r = -EINVAL;
+      }
+    } else {
+      derr << ": failed to decode image mirror state: " << cpp_strerror(r)
+           << dendl;
+    }
+  } else {
+    derr << ": failed to retrieve image mirror state: " << cpp_strerror(r)
+         << dendl;
+  }
+
+  finish(r);
 }
 
 template <typename I>
index e3482084b8a275abe7d2344545fc83a661e39282..ddb332cbfe69c1f98c760bea70aaa0819b1c5f17 100644 (file)
@@ -4,6 +4,8 @@
 #ifndef RBD_MIRROR_IMAGE_REPLAYER_IS_PRIMARY_REQUEST_H
 #define RBD_MIRROR_IMAGE_REPLAYER_IS_PRIMARY_REQUEST_H
 
+#include "include/buffer.h"
+
 class Context;
 class ContextWQ;
 namespace librbd { class ImageCtx; }
@@ -31,8 +33,11 @@ private:
    * <start>
    *    |
    *    v
-   * IS_TAG_OWNER * * * * * * *
-   *    |                     * (error)
+   * GET_MIRROR_STATE * * * * *
+   *    |                     *
+   *    v                     *
+   * IS_TAG_OWNER * * * * * * * (error)
+   *    |                     *
    *    v                     *
    * <finish> < * * * * * * * *
    *
@@ -42,6 +47,11 @@ private:
   bool *m_primary;
   Context *m_on_finish;
 
+  bufferlist m_out_bl;
+
+  void send_get_mirror_state();
+  void handle_get_mirror_state(int r);
+
   void send_is_tag_owner();
   void handle_is_tag_owner(int r);