From 56a7228a3f2cbdc71990b840a0d2ac6b5cbbb1c0 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 6 Jan 2020 20:15:13 -0500 Subject: [PATCH] rbd-mirror: retrieve remote image mirror mode during prepare The remote image's mirroring mode is needed to determine which style of mirroring the image should use. Signed-off-by: Jason Dillaman --- .../test_mock_PrepareRemoteImageRequest.cc | 64 +++++++++++++++++++ .../PrepareRemoteImageRequest.cc | 52 ++++++++++++++- .../PrepareRemoteImageRequest.h | 18 ++++-- 3 files changed, 127 insertions(+), 7 deletions(-) diff --git a/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc b/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc index 9814b9bfb53..ceeab552302 100644 --- a/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc +++ b/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc @@ -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; diff --git a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc index ebc2ca4256e..aab1c3c13dc 100644 --- a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc @@ -98,7 +98,57 @@ void PrepareRemoteImageRequest::handle_get_remote_image_id(int r) { return; } - get_client(); + get_mirror_image(); +} + +template +void PrepareRemoteImageRequest::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, + &PrepareRemoteImageRequest::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 +void PrepareRemoteImageRequest::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 diff --git a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h index 8746430f31e..413b26c2e6e 100644 --- a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h +++ b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h @@ -95,13 +95,16 @@ private: * GET_REMOTE_IMAGE_ID * | * v - * GET_CLIENT + * GET_REMOTE_MIRROR_IMAGE * | - * v (skip if not needed) - * REGISTER_CLIENT - * | - * v - * + * | (journal) + * \-----------> GET_CLIENT + * | + * v (skip if not needed) + * REGISTER_CLIENT + * | + * v + * * @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); -- 2.39.5