diff options
author | oliveiradan <doliveirabrz@gmail.com> | 2017-05-09 05:28:07 +0200 |
---|---|---|
committer | oliveiradan <doliveirabrz@gmail.com> | 2017-05-12 20:55:54 +0200 |
commit | c582dc76313cc3fe52f4a9263d18d17bbe91c52a (patch) | |
tree | 3312512ab0b06a133ed17368a2b3994234eab899 /src/test | |
parent | common/ceph_context: config diff get option refactored (diff) | |
parent | Merge pull request #14984 from dmick/wip-osd-dup (diff) | |
download | ceph-c582dc76313cc3fe52f4a9263d18d17bbe91c52a.tar.xz ceph-c582dc76313cc3fe52f4a9263d18d17bbe91c52a.zip |
Merge remote-tracking branch 'upstream/master' into SebastienHan_config_diff_get_fr
Diffstat (limited to 'src/test')
-rwxr-xr-x | src/test/encoding/generate-corpus-objects.sh | 58 | ||||
-rw-r--r-- | src/test/librbd/journal/test_mock_PromoteRequest.cc | 125 | ||||
-rw-r--r-- | src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc | 4 | ||||
-rw-r--r-- | src/test/librbd/test_librbd.cc | 1 | ||||
-rw-r--r-- | src/test/objectstore/Allocator_test.cc | 16 | ||||
-rwxr-xr-x | src/test/osd/osd-dup.sh | 3 | ||||
-rw-r--r-- | src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc | 234 |
7 files changed, 393 insertions, 48 deletions
diff --git a/src/test/encoding/generate-corpus-objects.sh b/src/test/encoding/generate-corpus-objects.sh new file mode 100755 index 00000000000..6f84181ecf4 --- /dev/null +++ b/src/test/encoding/generate-corpus-objects.sh @@ -0,0 +1,58 @@ +#!/bin/bash -ex + +BDIR=`pwd` + +p=$1 +echo path $p +test ! -d $p +mkdir $p +strings bin/ceph-osd | grep "^$p/%s__%d.%x" + +v=`git describe | cut -c 2-` +echo version $v + +echo 'binaries look ok, vstarting' +echo + +MON=3 MDS=3 OSD=5 MDS=3 MGR=2 RGW=1 ../src/vstart.sh -x -n -l --bluestore -e + +export PATH=bin:$PATH + +# do some work to generate a hopefully braod set of object instances + +echo 'starting some background work' +../qa/workunits/rados/test.sh & +../qa/workunits/rbd/test_librbd.sh & +../qa/workunits/libcephfs/test.sh & +../qa/workunits/rgw/run-s3tests.sh & +ceph-syn --syn makedirs 3 3 3 & + +echo 'waiting a bit' + +sleep 10 +echo 'triggering some recovery' + +kill -9 `cat out/osd.0.pid` +sleep 10 +ceph osd out 0 +sleep 10 +init-ceph start osd.0 +ceph osd in 0 + +sleep 5 +echo 'triggering mds work' +bin/ceph mds fail 0 + +echo 'waiting for worker to join (and ignoring errors)' +wait || true + +echo 'importing' +../src/test/encoding/import.sh $p $v ../ceph-object-corpus/archive + +for d in ../ceph-object-corpus/archive/$v/objects/* +do + echo prune $d + ../ceph-object-corpus/bin/prune.sh $d 25 +done + +echo 'done' diff --git a/src/test/librbd/journal/test_mock_PromoteRequest.cc b/src/test/librbd/journal/test_mock_PromoteRequest.cc index 805e76aaed4..209249955b1 100644 --- a/src/test/librbd/journal/test_mock_PromoteRequest.cc +++ b/src/test/librbd/journal/test_mock_PromoteRequest.cc @@ -24,6 +24,7 @@ namespace journal { template <> struct TypeTraits<MockTestImageCtx> { typedef ::journal::MockJournalerProxy Journaler; + typedef ::journal::MockFutureProxy Future; }; template <> @@ -63,7 +64,9 @@ namespace librbd { namespace journal { using ::testing::_; +using ::testing::A; using ::testing::InSequence; +using ::testing::Return; using ::testing::WithArg; class TestMockJournalPromoteRequest : public TestMockFixture { @@ -95,6 +98,35 @@ public: .WillOnce(WithArg<3>(CompleteContext(r, static_cast<ContextWQ*>(NULL)))); } + void expect_append_journaler(::journal::MockJournaler &mock_journaler) { + EXPECT_CALL(mock_journaler, append(_, _)) + .WillOnce(Return(::journal::MockFutureProxy())); + } + + void expect_future_flush(::journal::MockFuture &mock_future, int r) { + EXPECT_CALL(mock_future, flush(_)) + .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL))); + } + + void expect_future_committed(::journal::MockJournaler &mock_journaler) { + EXPECT_CALL(mock_journaler, committed(A<const ::journal::MockFutureProxy &>())); + } + + void expect_flush_commit_position(::journal::MockJournaler &mock_journaler, + int r) { + EXPECT_CALL(mock_journaler, flush_commit_position(_)) + .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL))); + } + + void expect_start_append(::journal::MockJournaler &mock_journaler) { + EXPECT_CALL(mock_journaler, start_append(_, _, _)); + } + + void expect_stop_append(::journal::MockJournaler &mock_journaler, int r) { + EXPECT_CALL(mock_journaler, stop_append(_)) + .WillOnce(CompleteContext(r, static_cast<ContextWQ*>(NULL))); + } + void expect_shut_down_journaler(::journal::MockJournaler &mock_journaler, int r) { EXPECT_CALL(mock_journaler, shut_down(_)) @@ -120,6 +152,15 @@ TEST_F(TestMockJournalPromoteRequest, SuccessOrderly) { expect_open_journaler(mock_image_ctx, mock_open_request, 0); expect_allocate_tag(mock_journaler, {Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0); + + ::journal::MockFuture mock_future; + expect_start_append(mock_journaler); + expect_append_journaler(mock_journaler); + expect_future_flush(mock_future, 0); + expect_future_committed(mock_journaler); + expect_flush_commit_position(mock_journaler, 0); + expect_stop_append(mock_journaler, 0); + expect_shut_down_journaler(mock_journaler, 0); C_SaferCond ctx; @@ -145,6 +186,15 @@ TEST_F(TestMockJournalPromoteRequest, SuccessForced) { expect_open_journaler(mock_image_ctx, mock_open_request, 0); expect_allocate_tag(mock_journaler, {Journal<>::LOCAL_MIRROR_UUID, true, 567, 0}, 0); + + ::journal::MockFuture mock_future; + expect_start_append(mock_journaler); + expect_append_journaler(mock_journaler); + expect_future_flush(mock_future, 0); + expect_future_committed(mock_journaler); + expect_flush_commit_position(mock_journaler, 0); + expect_stop_append(mock_journaler, 0); + expect_shut_down_journaler(mock_journaler, 0); C_SaferCond ctx; @@ -201,6 +251,72 @@ TEST_F(TestMockJournalPromoteRequest, AllocateTagError) { ASSERT_EQ(-EBADMSG, ctx.wait()); } +TEST_F(TestMockJournalPromoteRequest, AppendEventError) { + REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + ::journal::MockJournaler mock_journaler; + MockOpenRequest mock_open_request; + + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + expect_construct_journaler(mock_journaler); + expect_open_journaler(mock_image_ctx, mock_open_request, 0); + expect_allocate_tag(mock_journaler, + {Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0); + + ::journal::MockFuture mock_future; + expect_start_append(mock_journaler); + expect_append_journaler(mock_journaler); + expect_future_flush(mock_future, -EPERM); + expect_stop_append(mock_journaler, 0); + + expect_shut_down_journaler(mock_journaler, 0); + + C_SaferCond ctx; + auto req = MockPromoteRequest::create(&mock_image_ctx, false, &ctx); + req->send(); + ASSERT_EQ(-EPERM, ctx.wait()); +} + +TEST_F(TestMockJournalPromoteRequest, CommitEventError) { + REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); + + librbd::ImageCtx *ictx; + ASSERT_EQ(0, open_image(m_image_name, &ictx)); + + MockTestImageCtx mock_image_ctx(*ictx); + ::journal::MockJournaler mock_journaler; + MockOpenRequest mock_open_request; + + expect_op_work_queue(mock_image_ctx); + + InSequence seq; + expect_construct_journaler(mock_journaler); + expect_open_journaler(mock_image_ctx, mock_open_request, 0); + expect_allocate_tag(mock_journaler, + {Journal<>::ORPHAN_MIRROR_UUID, true, 567, 1}, 0); + + ::journal::MockFuture mock_future; + expect_start_append(mock_journaler); + expect_append_journaler(mock_journaler); + expect_future_flush(mock_future, 0); + expect_future_committed(mock_journaler); + expect_flush_commit_position(mock_journaler, -EINVAL); + expect_stop_append(mock_journaler, 0); + + expect_shut_down_journaler(mock_journaler, 0); + + C_SaferCond ctx; + auto req = MockPromoteRequest::create(&mock_image_ctx, false, &ctx); + req->send(); + ASSERT_EQ(-EINVAL, ctx.wait()); +} + TEST_F(TestMockJournalPromoteRequest, ShutDownError) { REQUIRE_FEATURE(RBD_FEATURE_JOURNALING); @@ -218,6 +334,15 @@ TEST_F(TestMockJournalPromoteRequest, ShutDownError) { expect_open_journaler(mock_image_ctx, mock_open_request, 0); expect_allocate_tag(mock_journaler, {Journal<>::LOCAL_MIRROR_UUID, true, 567, 0}, 0); + + ::journal::MockFuture mock_future; + expect_start_append(mock_journaler); + expect_append_journaler(mock_journaler); + expect_future_flush(mock_future, 0); + expect_future_committed(mock_journaler); + expect_flush_commit_position(mock_journaler, 0); + expect_stop_append(mock_journaler, 0); + expect_shut_down_journaler(mock_journaler, -EINVAL); C_SaferCond ctx; diff --git a/src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc b/src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc index 1f8b4addf05..1341864720e 100644 --- a/src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc +++ b/src/test/librbd/operation/test_mock_SnapshotRollbackRequest.cc @@ -70,10 +70,6 @@ struct AsyncRequest<MockOperationImageCtx> : public AsyncRequest<MockImageCtx> { #include "librbd/operation/Request.cc" #include "librbd/operation/SnapshotRollbackRequest.cc" -template class librbd::AsyncRequest<librbd::MockImageCtx>; -template class librbd::AsyncObjectThrottle<librbd::MockImageCtx>; -template class librbd::operation::Request<librbd::MockImageCtx>; - namespace librbd { namespace operation { diff --git a/src/test/librbd/test_librbd.cc b/src/test/librbd/test_librbd.cc index edda51c77b4..f16fbcca2a9 100644 --- a/src/test/librbd/test_librbd.cc +++ b/src/test/librbd/test_librbd.cc @@ -84,6 +84,7 @@ static int get_features(bool *old_format, uint64_t *features) cout << "using new format!" << std::endl; } else { *old_format = true; + *features = 0; cout << "using old format" << std::endl; } diff --git a/src/test/objectstore/Allocator_test.cc b/src/test/objectstore/Allocator_test.cc index 3a408265962..65f8e47bd08 100644 --- a/src/test/objectstore/Allocator_test.cc +++ b/src/test/objectstore/Allocator_test.cc @@ -200,6 +200,22 @@ TEST_P(AllocTest, test_alloc_failure) } } +TEST_P(AllocTest, test_alloc_big) +{ + int64_t block_size = 4096; + int64_t blocks = 104857600; + int64_t mas = 4096; + init_alloc(blocks*block_size, block_size); + alloc->init_add_free(2*block_size, (blocks-2)*block_size); + for (int64_t big = mas; big < 1048576*128; big*=2) { + cout << big << std::endl; + EXPECT_EQ(alloc->reserve(big), 0); + AllocExtentVector extents; + EXPECT_EQ(big, + alloc->allocate(big, mas, 0, &extents)); + } +} + TEST_P(AllocTest, test_alloc_hint_bmap) { if (GetParam() == std::string("stupid")) { diff --git a/src/test/osd/osd-dup.sh b/src/test/osd/osd-dup.sh index 264d27ddfdb..f82a85b9080 100755 --- a/src/test/osd/osd-dup.sh +++ b/src/test/osd/osd-dup.sh @@ -12,6 +12,9 @@ function run() { CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none " CEPH_ARGS+="--mon-host=$CEPH_MON " CEPH_ARGS+="--enable-experimental-unrecoverable-data-corrupting-features bluestore " + # avoid running out of fds in rados bench + CEPH_ARGS+="--filestore_wbthrottle_xfs_ios_hard_limit=900 " + CEPH_ARGS+="--filestore_wbthrottle_btrfs_ios_hard_limit=900 " local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')} for func in $funcs ; do setup $dir || return 1 diff --git a/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc b/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc index b31ab74fb58..a7c7b27b7a4 100644 --- a/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc +++ b/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc @@ -3,7 +3,6 @@ #include "test/rbd_mirror/test_mock_fixture.h" #include "librbd/journal/TypeTraits.h" -#include "tools/rbd_mirror/ImageSync.h" #include "tools/rbd_mirror/ImageSyncThrottler.h" #include "tools/rbd_mirror/Threads.h" #include "tools/rbd_mirror/image_replayer/BootstrapRequest.h" @@ -45,40 +44,6 @@ namespace mirror { class ProgressContext; template<> -struct ImageSync<librbd::MockTestImageCtx> { - static ImageSync* s_instance; - Context *on_finish = nullptr; - - static ImageSync* create(librbd::MockTestImageCtx *local_image_ctx, - librbd::MockTestImageCtx *remote_image_ctx, - SafeTimer *timer, Mutex *timer_lock, - const std::string &mirror_uuid, - ::journal::MockJournaler *journaler, - librbd::journal::MirrorPeerClientMeta *client_meta, - ContextWQ *work_queue, Context *on_finish, - ProgressContext *progress_ctx = nullptr) { - assert(s_instance != nullptr); - return s_instance; - } - - ImageSync() { - assert(s_instance == nullptr); - s_instance = this; - } - - void put() { - } - - void get() { - } - - MOCK_METHOD0(send, void()); - MOCK_METHOD0(cancel, void()); -}; - -ImageSync<librbd::MockTestImageCtx>* ImageSync<librbd::MockTestImageCtx>::s_instance = nullptr; - -template<> struct ImageSyncThrottler<librbd::MockTestImageCtx> { MOCK_METHOD10(start_sync, void(librbd::MockTestImageCtx *local_image_ctx, librbd::MockTestImageCtx *remote_image_ctx, @@ -124,6 +89,7 @@ struct CloseImageRequest<librbd::MockTestImageCtx> { template<> struct CreateImageRequest<librbd::MockTestImageCtx> { static CreateImageRequest* s_instance; + std::string *local_image_id = nullptr; Context *on_finish = nullptr; static CreateImageRequest* create(librados::IoCtx &local_io_ctx, @@ -135,7 +101,7 @@ struct CreateImageRequest<librbd::MockTestImageCtx> { std::string *local_image_id, Context *on_finish) { assert(s_instance != nullptr); - *local_image_id = "local image id"; + s_instance->local_image_id = local_image_id; s_instance->on_finish = on_finish; return s_instance; } @@ -278,6 +244,7 @@ public: typedef ImageSyncThrottlerRef<librbd::MockTestImageCtx> MockImageSyncThrottler; typedef BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest; typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest; + typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest; typedef IsPrimaryRequest<librbd::MockTestImageCtx> MockIsPrimaryRequest; typedef OpenImageRequest<librbd::MockTestImageCtx> MockOpenImageRequest; typedef OpenLocalImageRequest<librbd::MockTestImageCtx> MockOpenLocalImageRequest; @@ -321,6 +288,18 @@ public: })))); } + void expect_journaler_register_client(::journal::MockJournaler &mock_journaler, + const librbd::journal::ClientData &client_data, + int r) { + bufferlist bl; + ::encode(client_data, bl); + + EXPECT_CALL(mock_journaler, register_client(ContentsEqual(bl), _)) + .WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) { + m_threads->work_queue->queue(on_finish, r); + }))); + } + void expect_journaler_update_client(::journal::MockJournaler &mock_journaler, const librbd::journal::ClientData &client_data, int r) { @@ -346,12 +325,12 @@ public: void expect_open_local_image(MockOpenLocalImageRequest &mock_open_local_image_request, librados::IoCtx &io_ctx, const std::string &image_id, - librbd::MockTestImageCtx &mock_image_ctx, int r) { + librbd::MockTestImageCtx *mock_image_ctx, int r) { EXPECT_CALL(mock_open_local_image_request, construct(IsSameIoCtx(&io_ctx), image_id)); EXPECT_CALL(mock_open_local_image_request, send()) - .WillOnce(Invoke([this, &mock_open_local_image_request, &mock_image_ctx, r]() { - *mock_open_local_image_request.image_ctx = &mock_image_ctx; + .WillOnce(Invoke([this, &mock_open_local_image_request, mock_image_ctx, r]() { + *mock_open_local_image_request.image_ctx = mock_image_ctx; m_threads->work_queue->queue(mock_open_local_image_request.on_finish, r); })); @@ -393,6 +372,25 @@ public: Return(r))); } + void expect_create_image(MockCreateImageRequest &mock_create_image_request, + const std::string &image_id, int r) { + EXPECT_CALL(mock_create_image_request, send()) + .WillOnce(Invoke([this, &mock_create_image_request, image_id, r]() { + *mock_create_image_request.local_image_id = image_id; + m_threads->work_queue->queue(mock_create_image_request.on_finish, r); + })); + } + + void expect_image_sync(MockImageSyncThrottler image_sync_throttler, + int r) { + EXPECT_CALL(*image_sync_throttler, start_sync(_, _, _, _, + StrEq("local mirror uuid"), + _, _, _, _, _)) + .WillOnce(WithArg<8>(Invoke([this, r](Context *on_finish) { + m_threads->work_queue->queue(on_finish, r); + }))); + } + bufferlist encode_tag_data(const librbd::journal::TagData &tag_data) { bufferlist bl; ::encode(tag_data, bl); @@ -524,7 +522,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, RemoteDemotePromote) { mock_local_image_ctx.journal = &mock_journal; MockOpenLocalImageRequest mock_open_local_image_request; expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, - mock_local_image_ctx.id, mock_local_image_ctx, 0); + mock_local_image_ctx.id, &mock_local_image_ctx, 0); expect_is_resync_requested(mock_journal, false, 0); // remote demotion / promotion event @@ -599,7 +597,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, MultipleRemoteDemotePromotes) { mock_local_image_ctx.journal = &mock_journal; MockOpenLocalImageRequest mock_open_local_image_request; expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, - mock_local_image_ctx.id, mock_local_image_ctx, 0); + mock_local_image_ctx.id, &mock_local_image_ctx, 0); expect_is_resync_requested(mock_journal, false, 0); // remote demotion / promotion event @@ -684,7 +682,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, LocalDemoteRemotePromote) { mock_local_image_ctx.journal = &mock_journal; MockOpenLocalImageRequest mock_open_local_image_request; expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, - mock_local_image_ctx.id, mock_local_image_ctx, 0); + mock_local_image_ctx.id, &mock_local_image_ctx, 0); expect_is_resync_requested(mock_journal, false, 0); // remote demotion / promotion event @@ -757,7 +755,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, SplitBrainForcePromote) { mock_local_image_ctx.journal = &mock_journal; MockOpenLocalImageRequest mock_open_local_image_request; expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, - mock_local_image_ctx.id, mock_local_image_ctx, 0); + mock_local_image_ctx.id, &mock_local_image_ctx, 0); expect_is_resync_requested(mock_journal, false, 0); // remote demotion / promotion event @@ -830,7 +828,7 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) { mock_local_image_ctx.journal = &mock_journal; MockOpenLocalImageRequest mock_open_local_image_request; expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, - mock_local_image_ctx.id, mock_local_image_ctx, 0); + mock_local_image_ctx.id, &mock_local_image_ctx, 0); // resync is requested expect_is_resync_requested(mock_journal, true, 0); @@ -852,6 +850,154 @@ TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) { ASSERT_TRUE(m_do_resync); } +TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemote) { + create_local_image(); + + InSequence seq; + + // lookup remote image tag class + cls::journal::Client client; + librbd::journal::ClientData client_data{ + librbd::journal::ImageClientMeta{123}}; + ::encode(client_data, client.data); + ::journal::MockJournaler mock_journaler; + expect_journaler_get_client(mock_journaler, + librbd::Journal<>::IMAGE_CLIENT_ID, + client, 0); + + // lookup local peer in remote journal + client = {}; + expect_journaler_get_client(mock_journaler, "local mirror uuid", + client, -ENOENT); + + // register missing client in remote journal + librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta; + client_data.client_meta = mirror_peer_client_meta; + expect_journaler_register_client(mock_journaler, client_data, 0); + + // open the remote image + librbd::MockJournal mock_journal; + librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + MockOpenImageRequest mock_open_image_request; + expect_open_image(mock_open_image_request, m_remote_io_ctx, + mock_remote_image_ctx.id, mock_remote_image_ctx, 0); + MockIsPrimaryRequest mock_is_primary_request; + expect_is_primary(mock_is_primary_request, true, 0); + + // create the local image + librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); + mock_local_image_ctx.journal = &mock_journal; + + MockCreateImageRequest mock_create_image_request; + expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0); + + // open the local image + MockOpenLocalImageRequest mock_open_local_image_request; + expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, + mock_local_image_ctx.id, &mock_local_image_ctx, 0); + expect_is_resync_requested(mock_journal, false, 0); + + // update client state back to syncing + mirror_peer_client_meta = {mock_local_image_ctx.id}; + mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING; + client_data.client_meta = mirror_peer_client_meta; + client.data.clear(); + ::encode(client_data, client.data); + expect_journaler_update_client(mock_journaler, client_data, 0); + + // sync the remote image to the local image + MockImageSyncThrottler mock_image_sync_throttler( + new ImageSyncThrottler<librbd::MockTestImageCtx>()); + expect_image_sync(mock_image_sync_throttler, 0); + + MockCloseImageRequest mock_close_image_request; + expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0); + + C_SaferCond ctx; + MockBootstrapRequest *request = create_request( + mock_image_sync_throttler, mock_journaler, "", + mock_remote_image_ctx.id, "global image id", "local mirror uuid", + "remote mirror uuid", &ctx); + request->send(); + ASSERT_EQ(0, ctx.wait()); +} + +TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) { + create_local_image(); + + InSequence seq; + + // lookup remote image tag class + cls::journal::Client client; + librbd::journal::ClientData client_data{ + librbd::journal::ImageClientMeta{123}}; + ::encode(client_data, client.data); + ::journal::MockJournaler mock_journaler; + expect_journaler_get_client(mock_journaler, + librbd::Journal<>::IMAGE_CLIENT_ID, + client, 0); + + // lookup local peer in remote journal + librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{ + "missing image id"}; + mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING; + client_data.client_meta = mirror_peer_client_meta; + client.data.clear(); + ::encode(client_data, client.data); + expect_journaler_get_client(mock_journaler, "local mirror uuid", + client, 0); + + // open the remote image + librbd::MockJournal mock_journal; + librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx); + MockOpenImageRequest mock_open_image_request; + expect_open_image(mock_open_image_request, m_remote_io_ctx, + mock_remote_image_ctx.id, mock_remote_image_ctx, 0); + MockIsPrimaryRequest mock_is_primary_request; + expect_is_primary(mock_is_primary_request, true, 0); + + // open the missing local image + MockOpenLocalImageRequest mock_open_local_image_request; + expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, + "missing image id", nullptr, -ENOENT); + + // create the missing local image + librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx); + mock_local_image_ctx.journal = &mock_journal; + + MockCreateImageRequest mock_create_image_request; + expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0); + + // open the local image + expect_open_local_image(mock_open_local_image_request, m_local_io_ctx, + mock_local_image_ctx.id, &mock_local_image_ctx, 0); + expect_is_resync_requested(mock_journal, false, 0); + + // update client state back to syncing + mirror_peer_client_meta = {mock_local_image_ctx.id}; + mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING; + client_data.client_meta = mirror_peer_client_meta; + client.data.clear(); + ::encode(client_data, client.data); + expect_journaler_update_client(mock_journaler, client_data, 0); + + // sync the remote image to the local image + MockImageSyncThrottler mock_image_sync_throttler( + new ImageSyncThrottler<librbd::MockTestImageCtx>()); + expect_image_sync(mock_image_sync_throttler, 0); + + MockCloseImageRequest mock_close_image_request; + expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0); + + C_SaferCond ctx; + MockBootstrapRequest *request = create_request( + mock_image_sync_throttler, mock_journaler, "", + mock_remote_image_ctx.id, "global image id", "local mirror uuid", + "remote mirror uuid", &ctx); + request->send(); + ASSERT_EQ(0, ctx.wait()); +} + } // namespace image_replayer } // namespace mirror } // namespace rbd |