From 28e051afee54a6c129f5cf2bcc0639043f5aa6f0 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 27 Jan 2020 14:47:30 -0500 Subject: [PATCH] rbd-mirror: prepare remote image now handles the snapshot mode Signed-off-by: Jason Dillaman --- .../test_mock_PrepareRemoteImageRequest.cc | 83 ++++++++++++++++++- .../PrepareRemoteImageRequest.cc | 24 +++++- .../PrepareRemoteImageRequest.h | 19 +++-- .../image_replayer/snapshot/StateBuilder.cc | 7 ++ .../image_replayer/snapshot/StateBuilder.h | 3 + 5 files changed, 127 insertions(+), 9 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 180a6f823c7..04ee88205db 100644 --- a/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc +++ b/src/test/rbd_mirror/image_replayer/test_mock_PrepareRemoteImageRequest.cc @@ -10,6 +10,7 @@ #include "tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h" #include "tools/rbd_mirror/image_replayer/StateBuilder.h" #include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h" +#include "tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h" #include "test/journal/mock/MockJournaler.h" #include "test/librados_test_stub/MockTestMemIoCtxImpl.h" #include "test/librbd/mock/MockImageCtx.h" @@ -137,6 +138,9 @@ struct StateBuilder : public image_replayer::StateBuilder { static StateBuilder* s_instance; + cls::rbd::MirrorImageMode mirror_image_mode = + cls::rbd::MIRROR_IMAGE_MODE_JOURNAL; + ::journal::MockJournalerProxy* remote_journaler = nullptr; cls::journal::ClientState remote_client_state; librbd::journal::MirrorPeerClientMeta remote_client_meta; @@ -154,6 +158,32 @@ struct StateBuilder StateBuilder* StateBuilder::s_instance = nullptr; } // namespace journal + +namespace snapshot { + +template<> +struct StateBuilder + : public image_replayer::StateBuilder { + static StateBuilder* s_instance; + + cls::rbd::MirrorImageMode mirror_image_mode = + cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT; + + std::string remote_mirror_peer_uuid; + + static StateBuilder* create(const std::string&) { + ceph_assert(s_instance != nullptr); + return s_instance; + } + + StateBuilder() { + s_instance = this; + } +}; + +StateBuilder* StateBuilder::s_instance = nullptr; + +} // namespace snapshot } // namespace image_replayer } // namespace mirror } // namespace rbd @@ -180,6 +210,7 @@ public: typedef GetMirrorImageIdRequest MockGetMirrorImageIdRequest; typedef StateBuilder MockStateBuilder; typedef journal::StateBuilder MockJournalStateBuilder; + typedef snapshot::StateBuilder MockSnapshotStateBuilder; typedef librbd::mirror::GetInfoRequest MockGetMirrorInfoRequest; void expect_get_mirror_image_mode(MockStateBuilder& mock_state_builder, @@ -239,7 +270,7 @@ public: } }; -TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) { +TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessJournal) { ::journal::MockJournaler mock_remote_journaler; MockThreads mock_threads(m_threads); @@ -284,6 +315,10 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) { ASSERT_EQ(0, ctx.wait()); ASSERT_TRUE(mock_state_builder != nullptr); + ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_JOURNAL, + mock_journal_state_builder.mirror_image_mode); + ASSERT_EQ(std::string("remote mirror uuid"), + mock_journal_state_builder.remote_mirror_uuid); ASSERT_EQ(std::string("remote image id"), mock_journal_state_builder.remote_image_id); ASSERT_EQ(librbd::mirror::PROMOTION_STATE_PRIMARY, @@ -293,6 +328,52 @@ TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, Success) { mock_journal_state_builder.remote_client_state); } +TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessSnapshot) { + ::journal::MockJournaler mock_remote_journaler; + MockThreads mock_threads(m_threads); + + InSequence seq; + MockGetMirrorImageIdRequest mock_get_mirror_image_id_request; + expect_get_mirror_image_id(mock_get_mirror_image_id_request, + "remote image id", 0); + + MockGetMirrorInfoRequest mock_get_mirror_info_request; + expect_get_mirror_info(mock_get_mirror_info_request, + {cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, + "global image id", + cls::rbd::MIRROR_IMAGE_STATE_ENABLED}, + librbd::mirror::PROMOTION_STATE_PRIMARY, + "remote mirror uuid", 0); + + MockSnapshotStateBuilder mock_snapshot_state_builder; + MockStateBuilder* mock_state_builder = nullptr; + C_SaferCond ctx; + auto req = MockPrepareRemoteImageRequest::create(&mock_threads, + m_local_io_ctx, + m_remote_io_ctx, + "global image id", + "local mirror uuid", + {"remote mirror uuid", + "remote mirror peer uuid"}, + nullptr, + &mock_state_builder, + &ctx); + req->send(); + + ASSERT_EQ(0, ctx.wait()); + ASSERT_TRUE(mock_state_builder != nullptr); + ASSERT_EQ(cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT, + mock_snapshot_state_builder.mirror_image_mode); + ASSERT_EQ(std::string("remote mirror uuid"), + mock_snapshot_state_builder.remote_mirror_uuid); + ASSERT_EQ(std::string("remote mirror peer uuid"), + mock_snapshot_state_builder.remote_mirror_peer_uuid); + ASSERT_EQ(std::string("remote image id"), + mock_snapshot_state_builder.remote_image_id); + ASSERT_EQ(librbd::mirror::PROMOTION_STATE_PRIMARY, + mock_snapshot_state_builder.remote_promotion_state); +} + TEST_F(TestMockImageReplayerPrepareRemoteImageRequest, SuccessNotRegistered) { ::journal::MockJournaler mock_remote_journaler; MockThreads mock_threads(m_threads); diff --git a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc index 652c22d7122..b3d4ec4e18a 100644 --- a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc +++ b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.cc @@ -16,6 +16,7 @@ #include "tools/rbd_mirror/image_replayer/GetMirrorImageIdRequest.h" #include "tools/rbd_mirror/image_replayer/Utils.h" #include "tools/rbd_mirror/image_replayer/journal/StateBuilder.h" +#include "tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h" #define dout_context g_ceph_context #define dout_subsys ceph_subsys_rbd_mirror @@ -121,7 +122,9 @@ void PrepareRemoteImageRequest::handle_get_mirror_info(int r) { get_client(); break; case cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT: - // TODO + finalize_snapshot_state_builder(); + finish(0); + break; default: derr << "unsupported mirror image mode " << m_mirror_image.mode << " " << "for image " << m_global_image_id << dendl; @@ -236,6 +239,25 @@ void PrepareRemoteImageRequest::finalize_journal_state_builder( state_builder->remote_client_meta = client_meta; } +template +void PrepareRemoteImageRequest::finalize_snapshot_state_builder() { + snapshot::StateBuilder* state_builder = nullptr; + if (*m_state_builder != nullptr) { + // already verified that it's a matching builder in + // 'handle_get_mirror_info' + state_builder = dynamic_cast*>(*m_state_builder); + ceph_assert(state_builder != nullptr); + } else { + state_builder = snapshot::StateBuilder::create(m_global_image_id); + *m_state_builder = state_builder; + } + + state_builder->remote_mirror_uuid = m_remote_pool_meta.mirror_uuid; + state_builder->remote_mirror_peer_uuid = m_remote_pool_meta.mirror_peer_uuid; + state_builder->remote_image_id = m_remote_image_id; + state_builder->remote_promotion_state = m_promotion_state; +} + template void PrepareRemoteImageRequest::finish(int r) { dout(10) << "r=" << r << dendl; diff --git a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h index 397436bc747..b546cdc80ff 100644 --- a/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h +++ b/src/tools/rbd_mirror/image_replayer/PrepareRemoteImageRequest.h @@ -92,13 +92,16 @@ private: * | * | (journal) * \-----------> GET_CLIENT - * | - * v (skip if not needed) - * REGISTER_CLIENT - * | - * v - * - + * | | + * | v (skip if not needed) + * | REGISTER_CLIENT + * | | + * | | + * |/----------------/ + * | + * v + * + * * @endverbatim */ @@ -136,6 +139,8 @@ private: void finalize_journal_state_builder(cls::journal::ClientState client_state, const MirrorPeerClientMeta& client_meta); + void finalize_snapshot_state_builder(); + void finish(int r); }; diff --git a/src/tools/rbd_mirror/image_replayer/snapshot/StateBuilder.cc b/src/tools/rbd_mirror/image_replayer/snapshot/StateBuilder.cc index 471a8a7a638..604b62f9c74 100644 --- a/src/tools/rbd_mirror/image_replayer/snapshot/StateBuilder.cc +++ b/src/tools/rbd_mirror/image_replayer/snapshot/StateBuilder.cc @@ -41,6 +41,13 @@ bool StateBuilder::is_disconnected() const { return false; } +template +bool StateBuilder::is_linked() const { + // the remote has to have us registered as a peer + return (image_replayer::StateBuilder::is_linked() && + !remote_mirror_peer_uuid.empty()); +} + template cls::rbd::MirrorImageMode StateBuilder::get_mirror_image_mode() const { return cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT; diff --git a/src/tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h b/src/tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h index 49e2f66d853..7444ceb344d 100644 --- a/src/tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h +++ b/src/tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h @@ -31,6 +31,7 @@ public: void close(Context* on_finish) override; bool is_disconnected() const override; + bool is_linked() const override; cls::rbd::MirrorImageMode get_mirror_image_mode() const override; @@ -57,6 +58,8 @@ public: SyncPointHandler* sync_point_handler = nullptr; + std::string remote_mirror_peer_uuid; + }; } // namespace snapshot -- 2.39.5