]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / rbd_mirror / image_replayer / test_mock_CreateImageRequest.cc
index df0c4b2eac6f89c93b1ecee3196dcbf1c59d4a09..8e13e8b37efff1775814c4afdbafdbe6fad49a98 100644 (file)
@@ -5,6 +5,7 @@
 #include "include/rbd/librbd.hpp"
 #include "librbd/ImageState.h"
 #include "librbd/Operations.h"
+#include "test/journal/mock/MockJournaler.h"
 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
 #include "test/librados_test_stub/MockTestMemRadosClient.h"
 #include "test/librbd/mock/MockImageCtx.h"
@@ -21,7 +22,7 @@ namespace librbd {
 namespace {
 
 struct MockTestImageCtx : public librbd::MockImageCtx {
-  MockTestImageCtx(librbd::ImageCtx &image_ctx)
+  explicit MockTestImageCtx(librbd::ImageCtx &image_ctx)
     : librbd::MockImageCtx(image_ctx) {
   }
 };
@@ -35,7 +36,8 @@ struct CreateRequest<librbd::MockTestImageCtx> {
   static CreateRequest *s_instance;
   Context *on_finish = nullptr;
 
-  static CreateRequest *create(IoCtx &ioctx, const std::string &imgname,
+  static CreateRequest *create(const ConfigProxy& config, IoCtx &ioctx,
+                               const std::string &imgname,
                                const std::string &imageid, uint64_t size,
                                const librbd::ImageOptions &image_options,
                                const std::string &non_primary_global_image_id,
@@ -43,7 +45,7 @@ struct CreateRequest<librbd::MockTestImageCtx> {
                                bool skip_mirror_enable,
                                MockContextWQ *op_work_queue,
                                Context *on_finish) {
-    assert(s_instance != nullptr);
+    ceph_assert(s_instance != nullptr);
     EXPECT_FALSE(non_primary_global_image_id.empty());
     EXPECT_FALSE(primary_mirror_uuid.empty());
     EXPECT_FALSE(skip_mirror_enable);
@@ -72,15 +74,19 @@ struct CloneRequest<librbd::MockTestImageCtx> {
   static CloneRequest *s_instance;
   Context *on_finish = nullptr;
 
-  static CloneRequest *create(librbd::MockTestImageCtx *p_imctx,
+  static CloneRequest *create(ConfigProxy& config, IoCtx &p_ioctx,
+                              const std::string &p_id,
+                              const std::string &p_snap_name,
+                              uint64_t p_snap_id,
                              IoCtx &c_ioctx, const std::string &c_name,
                              const std::string &c_id, ImageOptions c_options,
                              const std::string &non_primary_global_image_id,
                              const std::string &primary_mirror_uuid,
-                             MockContextWQ *op_work_queue, Context *on_finish) {
-    assert(s_instance != nullptr);
+                             MockContextWQ *op_work_queue,
+                              Context *on_finish) {
+    ceph_assert(s_instance != nullptr);
     s_instance->on_finish = on_finish;
-    s_instance->construct(p_imctx);
+    s_instance->construct();
     return s_instance;
   }
 
@@ -93,17 +99,39 @@ struct CloneRequest<librbd::MockTestImageCtx> {
   }
 
   MOCK_METHOD0(send, void());
-  MOCK_METHOD1(construct, void(librbd::MockTestImageCtx *p_imctx));
+  MOCK_METHOD0(construct, void());
 };
 
 CloneRequest<librbd::MockTestImageCtx>*
   CloneRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
 
 } // namespace image
+
+namespace journal {
+
+template <>
+struct TypeTraits<MockTestImageCtx> {
+  typedef ::journal::MockJournalerProxy Journaler;
+};
+
+} // namespace journal
 } // namespace librbd
 
 namespace rbd {
 namespace mirror {
+
+template <>
+struct Threads<librbd::MockTestImageCtx> {
+  Mutex &timer_lock;
+  SafeTimer *timer;
+  ContextWQ *work_queue;
+
+  Threads(Threads<librbd::ImageCtx> *threads)
+    : timer_lock(threads->timer_lock), timer(threads->timer),
+      work_queue(threads->work_queue) {
+  }
+};
+
 namespace image_replayer {
 
 template<>
@@ -113,14 +141,14 @@ struct CloseImageRequest<librbd::MockTestImageCtx> {
 
   static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx,
                                    Context *on_finish) {
-    assert(s_instance != nullptr);
+    ceph_assert(s_instance != nullptr);
     s_instance->construct(*image_ctx);
     s_instance->on_finish = on_finish;
     return s_instance;
   }
 
   CloseImageRequest() {
-    assert(s_instance == nullptr);
+    ceph_assert(s_instance == nullptr);
     s_instance = this;
   }
   ~CloseImageRequest() {
@@ -141,7 +169,7 @@ struct OpenImageRequest<librbd::MockTestImageCtx> {
                                   librbd::MockTestImageCtx **image_ctx,
                                   const std::string &image_id,
                                   bool read_only, Context *on_finish) {
-    assert(s_instance != nullptr);
+    ceph_assert(s_instance != nullptr);
     s_instance->image_ctx = image_ctx;
     s_instance->on_finish = on_finish;
     s_instance->construct(io_ctx, image_id);
@@ -149,7 +177,7 @@ struct OpenImageRequest<librbd::MockTestImageCtx> {
   }
 
   OpenImageRequest() {
-    assert(s_instance == nullptr);
+    ceph_assert(s_instance == nullptr);
     s_instance = this;
   }
   ~OpenImageRequest() {
@@ -192,6 +220,7 @@ MATCHER_P(IsSameIoCtx, io_ctx, "") {
 
 class TestMockImageReplayerCreateImageRequest : public TestMockFixture {
 public:
+  typedef Threads<librbd::MockTestImageCtx> MockThreads;
   typedef librbd::image::CreateRequest<librbd::MockTestImageCtx> MockCreateRequest;
   typedef librbd::image::CloneRequest<librbd::MockTestImageCtx> MockCloneRequest;
   typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest;
@@ -206,21 +235,17 @@ public:
     ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
   }
 
+  void snap_create(librbd::ImageCtx *image_ctx, const std::string &snap_name) {
+    ASSERT_EQ(0, image_ctx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
+                                                   snap_name.c_str()));
+    ASSERT_EQ(0, image_ctx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
+                                                    snap_name.c_str()));
+    ASSERT_EQ(0, image_ctx->state->refresh());
+  }
+
   int clone_image(librbd::ImageCtx *parent_image_ctx,
                   const std::string &snap_name, const std::string &clone_name) {
-    {
-      librbd::ImageCtx *ictx = new librbd::ImageCtx(parent_image_ctx->name,
-                                                   "", "", m_remote_io_ctx,
-                                                    false);
-      ictx->state->open(false);
-      EXPECT_EQ(0, ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
-                                                snap_name.c_str()));
-      EXPECT_EQ(0, ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
-                                                 snap_name.c_str()));
-      ictx->state->close();
-    }
-
-    EXPECT_EQ(0, parent_image_ctx->state->refresh());
+    snap_create(parent_image_ctx, snap_name);
 
     int order = 0;
     return librbd::clone(m_remote_io_ctx, parent_image_ctx->name.c_str(),
@@ -239,8 +264,10 @@ public:
   }
 
   void expect_ioctx_create(librados::IoCtx &io_ctx) {
+    librados::MockTestMemIoCtxImpl &io_ctx_impl = get_mock_io_ctx(io_ctx);
     EXPECT_CALL(*get_mock_io_ctx(io_ctx).get_mock_rados_client(), create_ioctx(_, _))
-      .WillOnce(Return(&get_mock_io_ctx(io_ctx)));
+      .WillOnce(DoAll(GetReference(&io_ctx_impl),
+                      Return(&get_mock_io_ctx(io_ctx))));
   }
 
   void expect_get_parent_global_image_id(librados::IoCtx &io_ctx,
@@ -249,7 +276,7 @@ public:
     mirror_image.global_image_id = global_id;
 
     bufferlist bl;
-    ::encode(mirror_image, bl);
+    encode(mirror_image, bl);
 
     EXPECT_CALL(get_mock_io_ctx(io_ctx),
                 exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_get"), _, _, _))
@@ -262,7 +289,7 @@ public:
   void expect_mirror_image_get_image_id(librados::IoCtx &io_ctx,
                                         const std::string &image_id, int r) {
     bufferlist bl;
-    ::encode(image_id, bl);
+    encode(image_id, bl);
 
     EXPECT_CALL(get_mock_io_ctx(io_ctx),
                 exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_get_image_id"), _, _, _))
@@ -283,18 +310,9 @@ public:
         }));
   }
 
-  void expect_snap_set(librbd::MockTestImageCtx &mock_image_ctx,
-                       const std::string &snap_name, int r) {
-    EXPECT_CALL(*mock_image_ctx.state, snap_set(_, StrEq(snap_name), _))
-      .WillOnce(WithArg<2>(Invoke([this, r](Context *on_finish) {
-          m_threads->work_queue->queue(on_finish, r);
-        })));
-  }
-
   void expect_clone_image(MockCloneRequest &mock_clone_request,
-                         librbd::MockTestImageCtx &mock_parent_imctx,
                           int r) {
-    EXPECT_CALL(mock_clone_request, construct(&mock_parent_imctx));
+    EXPECT_CALL(mock_clone_request, construct());
     EXPECT_CALL(mock_clone_request, send())
       .WillOnce(Invoke([this, &mock_clone_request, r]() {
             m_threads->work_queue->queue(mock_clone_request.on_finish, r);
@@ -310,13 +328,50 @@ public:
         }));
   }
 
-  MockCreateImageRequest *create_request(const std::string &global_image_id,
+  void expect_mirror_uuid_get(librados::IoCtx &io_ctx,
+                              const std::string &mirror_uuid, int r) {
+    bufferlist bl;
+    encode(mirror_uuid, bl);
+
+    EXPECT_CALL(get_mock_io_ctx(io_ctx),
+                exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_uuid_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,
+                                   librbd::journal::MirrorPeerState state,
+                                   int r) {
+    EXPECT_CALL(mock_journaler, construct());
+
+    librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
+    mirror_peer_client_meta.state = state;
+
+    librbd::journal::ClientData client_data{mirror_peer_client_meta};
+
+    cls::journal::Client client;
+    encode(client_data, client.data);
+
+    EXPECT_CALL(mock_journaler, get_client(StrEq(client_id), _, _))
+      .WillOnce(DoAll(WithArg<1>(Invoke([client](cls::journal::Client *out_client) {
+                                          *out_client = client;
+                                        })),
+                      WithArg<2>(Invoke([this, r](Context *on_finish) {
+                                          m_threads->work_queue->queue(on_finish, r);
+                                        }))));
+  }
+
+  MockCreateImageRequest *create_request(MockThreads* mock_threads,
+                                         const std::string &global_image_id,
                                          const std::string &remote_mirror_uuid,
                                          const std::string &local_image_name,
                                         const std::string &local_image_id,
                                          librbd::MockTestImageCtx &mock_remote_image_ctx,
                                          Context *on_finish) {
-    return new MockCreateImageRequest(m_local_io_ctx, m_threads->work_queue,
+    return new MockCreateImageRequest(mock_threads, m_local_io_ctx,
                                       global_image_id, remote_mirror_uuid,
                                       local_image_name, local_image_id,
                                       &mock_remote_image_ctx, on_finish);
@@ -333,8 +388,10 @@ TEST_F(TestMockImageReplayerCreateImageRequest, Create) {
   expect_create_image(mock_create_request, m_local_io_ctx, 0);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_image_ctx, &ctx);
   request->send();
   ASSERT_EQ(0, ctx.wait());
@@ -348,8 +405,10 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CreateError) {
   expect_create_image(mock_create_request, m_local_io_ctx, -EINVAL);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_image_ctx, &ctx);
   request->send();
   ASSERT_EQ(-EINVAL, ctx.wait());
@@ -360,6 +419,7 @@ TEST_F(TestMockImageReplayerCreateImageRequest, Clone) {
   librbd::ImageCtx *local_image_ctx;
   ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
   ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
+  snap_create(local_image_ctx, "snap");
 
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
@@ -369,37 +429,39 @@ TEST_F(TestMockImageReplayerCreateImageRequest, Clone) {
                &remote_clone_image_ctx));
 
   librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
   MockCloneRequest mock_clone_request;
   MockOpenImageRequest mock_open_image_request;
   MockCloseImageRequest mock_close_image_request;
+  journal::MockJournaler mock_remote_journaler;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+  expect_journaler_get_client(
+    mock_remote_journaler, "local parent uuid",
+    librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
   expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
   expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
 
   expect_open_image(mock_open_image_request, m_remote_io_ctx,
                     m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
-  expect_open_image(mock_open_image_request, m_local_io_ctx,
-                    "local parent id", mock_local_parent_image_ctx, 0);
-  expect_snap_set(mock_local_parent_image_ctx, "snap", 0);
-  expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0);
-  expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0);
+  expect_clone_image(mock_clone_request, 0);
   expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();
   ASSERT_EQ(0, ctx.wait());
 }
 
-TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetGlobalImageIdError) {
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneParentMirrorUuidGetError) {
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
 
@@ -408,23 +470,24 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetGlobalImageIdError) {
                &remote_clone_image_ctx));
 
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
-  MockCloneRequest mock_clone_request;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
-  expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", -ENOENT);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", -EPERM);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();
-  ASSERT_EQ(-ENOENT, ctx.wait());
+  ASSERT_EQ(-EPERM, ctx.wait());
 }
 
-TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetLocalParentImageIdError) {
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetRemoteParentClientStateError) {
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
 
@@ -433,24 +496,28 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetLocalParentImageIdError)
                &remote_clone_image_ctx));
 
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
-  MockCloneRequest mock_clone_request;
+  journal::MockJournaler mock_remote_journaler;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
-  expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
-  expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", -ENOENT);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+  expect_journaler_get_client(
+    mock_remote_journaler, "local parent uuid",
+    librbd::journal::MIRROR_PEER_STATE_REPLAYING, -EPERM);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();
-  ASSERT_EQ(-ENOENT, ctx.wait());
+  ASSERT_EQ(-EPERM, ctx.wait());
 }
 
-TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenRemoteParentError) {
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetRemoteParentClientStateSyncing) {
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
 
@@ -458,35 +525,29 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenRemoteParentError) {
   ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
                &remote_clone_image_ctx));
 
-  librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
-  MockCloneRequest mock_clone_request;
-  MockOpenImageRequest mock_open_image_request;
+  journal::MockJournaler mock_remote_journaler;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
-  expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
-  expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
-
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    m_remote_image_ctx->id, mock_remote_parent_image_ctx, -ENOENT);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+  expect_journaler_get_client(
+    mock_remote_journaler, "local parent uuid",
+    librbd::journal::MIRROR_PEER_STATE_SYNCING, 0);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();
   ASSERT_EQ(-ENOENT, ctx.wait());
 }
 
-TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenLocalParentError) {
-  librbd::RBD rbd;
-  librbd::ImageCtx *local_image_ctx;
-  ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
-  ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
-
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetGlobalImageIdError) {
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
 
@@ -494,40 +555,30 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenLocalParentError) {
   ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
                &remote_clone_image_ctx));
 
-  librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
-  MockCloneRequest mock_clone_request;
-  MockOpenImageRequest mock_open_image_request;
-  MockCloseImageRequest mock_close_image_request;
+  journal::MockJournaler mock_remote_journaler;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
-  expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
-  expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
-
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
-  expect_open_image(mock_open_image_request, m_local_io_ctx,
-                    "local parent id", mock_local_parent_image_ctx, -ENOENT);
-  expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+  expect_journaler_get_client(
+    mock_remote_journaler, "local parent uuid",
+    librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
+  expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", -ENOENT);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();
   ASSERT_EQ(-ENOENT, ctx.wait());
 }
 
-TEST_F(TestMockImageReplayerCreateImageRequest, CloneSnapSetError) {
-  librbd::RBD rbd;
-  librbd::ImageCtx *local_image_ctx;
-  ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
-  ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
-
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetLocalParentImageIdError) {
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
 
@@ -535,42 +586,31 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneSnapSetError) {
   ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
                &remote_clone_image_ctx));
 
-  librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
-  MockCloneRequest mock_clone_request;
-  MockOpenImageRequest mock_open_image_request;
-  MockCloseImageRequest mock_close_image_request;
+  journal::MockJournaler mock_remote_journaler;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+  expect_journaler_get_client(
+    mock_remote_journaler, "local parent uuid",
+    librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
   expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
-  expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
-
-  expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
-  expect_open_image(mock_open_image_request, m_local_io_ctx,
-                    "local parent id", mock_local_parent_image_ctx, 0);
-  expect_snap_set(mock_local_parent_image_ctx, "snap", -ENOENT);
-  expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0);
-  expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
+  expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", -ENOENT);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();
   ASSERT_EQ(-ENOENT, ctx.wait());
 }
 
-TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) {
-  librbd::RBD rbd;
-  librbd::ImageCtx *local_image_ctx;
-  ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
-  ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
-
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenRemoteParentError) {
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
 
@@ -579,41 +619,41 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) {
                &remote_clone_image_ctx));
 
   librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
-  MockCloneRequest mock_clone_request;
   MockOpenImageRequest mock_open_image_request;
-  MockCloseImageRequest mock_close_image_request;
+  journal::MockJournaler mock_remote_journaler;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+  expect_journaler_get_client(
+    mock_remote_journaler, "local parent uuid",
+    librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
   expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
   expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
 
   expect_open_image(mock_open_image_request, m_remote_io_ctx,
-                    m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
-  expect_open_image(mock_open_image_request, m_local_io_ctx,
-                    "local parent id", mock_local_parent_image_ctx, 0);
-  expect_snap_set(mock_local_parent_image_ctx, "snap", 0);
-  expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, -EINVAL);
-  expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0);
-  expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
+                    m_remote_image_ctx->id, mock_remote_parent_image_ctx,
+                    -ENOENT);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
+  ASSERT_EQ(-ENOENT, ctx.wait());
 }
 
-TEST_F(TestMockImageReplayerCreateImageRequest, CloneLocalParentCloseError) {
+TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) {
   librbd::RBD rbd;
   librbd::ImageCtx *local_image_ctx;
   ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
   ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
+  snap_create(local_image_ctx, "snap");
 
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
@@ -623,34 +663,36 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneLocalParentCloseError) {
                &remote_clone_image_ctx));
 
   librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
   MockCloneRequest mock_clone_request;
   MockOpenImageRequest mock_open_image_request;
   MockCloseImageRequest mock_close_image_request;
+  journal::MockJournaler mock_remote_journaler;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+  expect_journaler_get_client(
+    mock_remote_journaler, "local parent uuid",
+    librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
   expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
   expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
 
   expect_open_image(mock_open_image_request, m_remote_io_ctx,
                     m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
-  expect_open_image(mock_open_image_request, m_local_io_ctx,
-                    "local parent id", mock_local_parent_image_ctx, 0);
-  expect_snap_set(mock_local_parent_image_ctx, "snap", 0);
-  expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0);
-  expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, -EINVAL);
+  expect_clone_image(mock_clone_request, -EINVAL);
   expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();
-  ASSERT_EQ(0, ctx.wait());
+  ASSERT_EQ(-EINVAL, ctx.wait());
 }
 
 TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) {
@@ -658,6 +700,7 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) {
   librbd::ImageCtx *local_image_ctx;
   ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
   ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
+  snap_create(local_image_ctx, "snap");
 
   std::string clone_image_name = get_temp_image_name();
   ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
@@ -667,30 +710,33 @@ TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) {
                &remote_clone_image_ctx));
 
   librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
-  librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
   librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
   MockCloneRequest mock_clone_request;
   MockOpenImageRequest mock_open_image_request;
   MockCloseImageRequest mock_close_image_request;
+  journal::MockJournaler mock_remote_journaler;
 
   InSequence seq;
   expect_ioctx_create(m_remote_io_ctx);
   expect_ioctx_create(m_local_io_ctx);
+  expect_mirror_uuid_get(m_local_io_ctx, "local parent uuid", 0);
+  expect_journaler_get_client(
+    mock_remote_journaler, "local parent uuid",
+    librbd::journal::MIRROR_PEER_STATE_REPLAYING, 0);
   expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
   expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
 
   expect_open_image(mock_open_image_request, m_remote_io_ctx,
                     m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
-  expect_open_image(mock_open_image_request, m_local_io_ctx,
-                    "local parent id", mock_local_parent_image_ctx, 0);
-  expect_snap_set(mock_local_parent_image_ctx, "snap", 0);
-  expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0);
-  expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0);
-  expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, -EINVAL);
+  expect_clone_image(mock_clone_request, 0);
+  expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx,
+                     -EINVAL);
 
   C_SaferCond ctx;
-  MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
-                                                   "image name", "101241a7c4c9",
+  MockThreads mock_threads(m_threads);
+  MockCreateImageRequest *request = create_request(&mock_threads, "global uuid",
+                                                   "remote uuid", "image name",
+                                                   "101241a7c4c9",
                                                    mock_remote_clone_image_ctx,
                                                    &ctx);
   request->send();