]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd-mirror: retrieve remote image mirror mode during prepare
authorJason Dillaman <dillaman@redhat.com>
Tue, 7 Jan 2020 01:15:13 +0000 (20:15 -0500)
committerJason Dillaman <dillaman@redhat.com>
Thu, 9 Jan 2020 15:48:52 +0000 (10:48 -0500)
The remote image's mirroring mode is needed to determine which
style of mirroring the image should use.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc
src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc
src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h

index 9814b9bfb5352e16b053fba33fbb5ca6999647d1..ceeab552302bd9abd8ca11619155c47e457165b8 100644 (file)
@@ -122,6 +122,23 @@ public:
                       Return(r)));
   }
 
+  void expect_get_mirror_mode(librados::IoCtx &io_ctx,
+                              cls::rbd::MirrorImageMode mode, int r) {
+    cls::rbd::MirrorImage mirror_image;
+    mirror_image.mode = mode;
+
+    bufferlist bl;
+    encode(mirror_image, bl);
+
+    EXPECT_CALL(get_mock_io_ctx(io_ctx),
+                exec(RBD_MIRRORING, _, StrEq("rbd"),
+                     StrEq("mirror_image_get"), _, _, _))
+      .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) {
+                                          *out_bl = bl;
+                                        })),
+                      Return(r)));
+  }
+
   void expect_journaler_get_client(::journal::MockJournaler &mock_journaler,
                                    const std::string &client_id,
                                    cls::journal::Client &client, int r) {
@@ -157,6 +174,9 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) {
   expect_get_mirror_image_id(mock_get_mirror_image_id_request,
                              "remote image id", 0);
 
+  expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+                         0);
+
   EXPECT_CALL(mock_remote_journaler, construct());
 
   librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
@@ -205,6 +225,9 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessNotRegistered) {
   expect_get_mirror_image_id(mock_get_mirror_image_id_request,
                              "remote image id", 0);
 
+  expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+                         0);
+
   EXPECT_CALL(mock_remote_journaler, construct());
 
   cls::journal::Client client;
@@ -305,6 +328,41 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorImageIdError) {
   ASSERT_TRUE(remote_journaler == nullptr);
 }
 
+TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, MirrorModeError) {
+  journal::MockJournaler mock_remote_journaler;
+  MockThreads mock_threads(m_threads);
+
+  InSequence seq;
+  expect_mirror_uuid_get(m_remote_io_ctx, "remote mirror uuid", 0);
+  MockGetMirrorImageIdRequest mock_get_mirror_image_id_request;
+  expect_get_mirror_image_id(mock_get_mirror_image_id_request,
+                             "remote image id", 0);
+
+  expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+                         -EINVAL);
+
+  std::string remote_mirror_uuid;
+  std::string remote_image_id;
+  journal::MockJournalerProxy *remote_journaler = nullptr;
+  cls::journal::ClientState client_state;
+  librbd::journal::MirrorPeerClientMeta client_meta;
+  C_SaferCond ctx;
+  auto req = MockPrepareRemoteImageRequest::create(&mock_threads,
+                                                   m_remote_io_ctx,
+                                                   "global image id",
+                                                   "local mirror uuid",
+                                                   "", {}, nullptr,
+                                                   &remote_mirror_uuid,
+                                                   &remote_image_id,
+                                                   &remote_journaler,
+                                                   &client_state, &client_meta,
+                                                   &ctx);
+  req->send();
+
+  ASSERT_EQ(-EINVAL, ctx.wait());
+  ASSERT_TRUE(remote_journaler == nullptr);
+}
+
 TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetClientError) {
   journal::MockJournaler mock_remote_journaler;
   MockThreads mock_threads(m_threads);
@@ -315,6 +373,9 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, GetClientError) {
   expect_get_mirror_image_id(mock_get_mirror_image_id_request,
                              "remote image id", 0);
 
+  expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+                         0);
+
   EXPECT_CALL(mock_remote_journaler, construct());
 
   cls::journal::Client client;
@@ -355,6 +416,9 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, RegisterClientError) {
   expect_get_mirror_image_id(mock_get_mirror_image_id_request,
                              "remote image id", 0);
 
+  expect_get_mirror_mode(m_remote_io_ctx, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
+                         0);
+
   EXPECT_CALL(mock_remote_journaler, construct());
 
   cls::journal::Client client;
index ebc2ca4256eceee0c368ff4f37f37cb8924eb6f9..aab1c3c13dc81f8a0172f0164f9528a61da3f64e 100644 (file)
@@ -98,7 +98,57 @@ void PrepareRemoteImageRequest<I>::handle_get_remote_image_id(int r) {
     return;
   }
 
-  get_client();
+  get_mirror_image();
+}
+
+template <typename I>
+void PrepareRemoteImageRequest<I>::get_mirror_image() {
+  dout(10) << dendl;
+
+  librados::ObjectReadOperation op;
+  librbd::cls_client::mirror_image_get_start(&op, *m_remote_image_id);
+
+  auto aio_comp = create_rados_callback<
+    PrepareRemoteImageRequest<I>,
+    &PrepareRemoteImageRequest<I>::handle_get_mirror_image>(this);
+  m_out_bl.clear();
+  int r = m_remote_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl);
+  ceph_assert(r == 0);
+  aio_comp->release();
+}
+
+template <typename I>
+void PrepareRemoteImageRequest<I>::handle_get_mirror_image(int r) {
+  dout(10) << "r=" << r << dendl;
+  cls::rbd::MirrorImage mirror_image;
+  if (r == 0) {
+    auto iter = m_out_bl.cbegin();
+    r = librbd::cls_client::mirror_image_get_finish(&iter, &mirror_image);
+  }
+
+  if (r == -ENOENT) {
+    dout(10) << "image " << m_global_image_id << " not mirrored" << dendl;
+    finish(r);
+    return;
+  } else if (r < 0) {
+    derr << "failed to retrieve mirror image details for image "
+         << m_global_image_id << ": " << cpp_strerror(r) << dendl;
+    finish(r);
+    return;
+  }
+
+  switch (mirror_image.mode) {
+  case cls::rbd::MIRROR_IMAGE_MODE_JOURNAL:
+    get_client();
+    break;
+  case cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT:
+    // TODO
+  default:
+    derr << "unsupported mirror image mode " << mirror_image.mode << " "
+         << "for image " << m_global_image_id << dendl;
+    finish(-EOPNOTSUPP);
+    break;
+  }
 }
 
 template <typename I>
index 8746430f31eabb3cb19bfae1ee3a5cb634ad3439..413b26c2e6ec28021cf06c4e5333899d0a6b4113 100644 (file)
@@ -95,13 +95,16 @@ private:
    * GET_REMOTE_IMAGE_ID
    *    |
    *    v
-   * GET_CLIENT
+   * GET_REMOTE_MIRROR_IMAGE
    *    |
-   *    v (skip if not needed)
-   * REGISTER_CLIENT
-   *    |
-   *    v
-   * <finish>
+   *    | (journal)
+   *    \-----------> GET_CLIENT
+   *                      |
+   *                      v (skip if not needed)
+   *                  REGISTER_CLIENT
+   *                      |
+   *                      v
+   *                  <finish>
 
    * @endverbatim
    */
@@ -129,6 +132,9 @@ private:
   void get_remote_image_id();
   void handle_get_remote_image_id(int r);
 
+  void get_mirror_image();
+  void handle_get_mirror_image(int r);
+
   void get_client();
   void handle_get_client(int r);