1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/rbd_mirror/test_mock_fixture.h"
5 #include "librbd/deep_copy/ImageCopyRequest.h"
6 #include "librbd/deep_copy/SnapshotCopyRequest.h"
7 #include "librbd/mirror/ImageStateUpdateRequest.h"
8 #include "librbd/mirror/snapshot/CreateNonPrimaryRequest.h"
9 #include "librbd/mirror/snapshot/GetImageStateRequest.h"
10 #include "librbd/mirror/snapshot/ImageMeta.h"
11 #include "librbd/mirror/snapshot/UnlinkPeerRequest.h"
12 #include "tools/rbd_mirror/InstanceWatcher.h"
13 #include "tools/rbd_mirror/Threads.h"
14 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
15 #include "tools/rbd_mirror/image_replayer/ReplayerListener.h"
16 #include "tools/rbd_mirror/image_replayer/Utils.h"
17 #include "tools/rbd_mirror/image_replayer/snapshot/ApplyImageStateRequest.h"
18 #include "tools/rbd_mirror/image_replayer/snapshot/Replayer.h"
19 #include "tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h"
20 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
21 #include "test/librbd/mock/MockImageCtx.h"
22 #include "test/librbd/mock/MockOperations.h"
23 #include "test/rbd_mirror/mock/MockContextWQ.h"
24 #include "test/rbd_mirror/mock/MockSafeTimer.h"
29 struct MockTestImageCtx
: public librbd::MockImageCtx
{
30 explicit MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
31 : librbd::MockImageCtx(image_ctx
) {
35 } // anonymous namespace
40 struct ImageCopyRequest
<MockTestImageCtx
> {
41 uint64_t src_snap_id_start
;
42 uint64_t src_snap_id_end
;
43 uint64_t dst_snap_id_start
;
44 librbd::deep_copy::ObjectNumber object_number
;
45 librbd::SnapSeqs snap_seqs
;
47 static ImageCopyRequest
* s_instance
;
48 static ImageCopyRequest
* create(MockTestImageCtx
*src_image_ctx
,
49 MockTestImageCtx
*dst_image_ctx
,
50 librados::snap_t src_snap_id_start
,
51 librados::snap_t src_snap_id_end
,
52 librados::snap_t dst_snap_id_start
,
54 const ObjectNumber
&object_number
,
55 const SnapSeqs
&snap_seqs
,
58 ceph_assert(s_instance
!= nullptr);
59 s_instance
->src_snap_id_start
= src_snap_id_start
;
60 s_instance
->src_snap_id_end
= src_snap_id_end
;
61 s_instance
->dst_snap_id_start
= dst_snap_id_start
;
62 s_instance
->object_number
= object_number
;
63 s_instance
->snap_seqs
= snap_seqs
;
64 s_instance
->on_finish
= on_finish
;
68 Context
* on_finish
= nullptr;
74 MOCK_METHOD0(send
, void());
78 struct SnapshotCopyRequest
<MockTestImageCtx
> {
79 librados::snap_t src_snap_id_start
;
80 librados::snap_t src_snap_id_end
;
81 librados::snap_t dst_snap_id_start
;
82 SnapSeqs
* snap_seqs
= nullptr;
84 static SnapshotCopyRequest
* s_instance
;
85 static SnapshotCopyRequest
* create(MockTestImageCtx
*src_image_ctx
,
86 MockTestImageCtx
*dst_image_ctx
,
87 librados::snap_t src_snap_id_start
,
88 librados::snap_t src_snap_id_end
,
89 librados::snap_t dst_snap_id_start
,
91 ::MockContextWQ
*work_queue
,
94 ceph_assert(s_instance
!= nullptr);
95 s_instance
->src_snap_id_start
= src_snap_id_start
;
96 s_instance
->src_snap_id_end
= src_snap_id_end
;
97 s_instance
->dst_snap_id_start
= dst_snap_id_start
;
98 s_instance
->snap_seqs
= snap_seqs
;
99 s_instance
->on_finish
= on_finish
;
103 Context
* on_finish
= nullptr;
105 SnapshotCopyRequest() {
109 MOCK_METHOD0(send
, void());
112 ImageCopyRequest
<MockTestImageCtx
>* ImageCopyRequest
<MockTestImageCtx
>::s_instance
= nullptr;
113 SnapshotCopyRequest
<MockTestImageCtx
>* SnapshotCopyRequest
<MockTestImageCtx
>::s_instance
= nullptr;
115 } // namespace deep_copy
120 struct ImageStateUpdateRequest
<MockTestImageCtx
> {
121 static ImageStateUpdateRequest
* s_instance
;
122 static ImageStateUpdateRequest
* create(
123 librados::IoCtx
& io_ctx
,
124 const std::string
& image_id
,
125 cls::rbd::MirrorImageState mirror_image_state
,
126 const cls::rbd::MirrorImage
& mirror_image
,
127 Context
* on_finish
) {
128 ceph_assert(s_instance
!= nullptr);
129 EXPECT_EQ(cls::rbd::MIRROR_IMAGE_STATE_ENABLED
,
131 EXPECT_EQ(cls::rbd::MirrorImage
{}, mirror_image
);
132 s_instance
->on_finish
= on_finish
;
136 Context
* on_finish
= nullptr;
137 ImageStateUpdateRequest() {
141 MOCK_METHOD0(send
, void());
144 ImageStateUpdateRequest
<MockTestImageCtx
>* ImageStateUpdateRequest
<MockTestImageCtx
>::s_instance
= nullptr;
149 struct CreateNonPrimaryRequest
<MockTestImageCtx
> {
150 bool demoted
= false;
151 std::string primary_mirror_uuid
;
152 uint64_t primary_snap_id
;
154 uint64_t* snap_id
= nullptr;
156 static CreateNonPrimaryRequest
* s_instance
;
157 static CreateNonPrimaryRequest
* create(MockTestImageCtx
*image_ctx
,
159 const std::string
&primary_mirror_uuid
,
160 uint64_t primary_snap_id
,
161 const SnapSeqs
& snap_seqs
,
162 const ImageState
&image_state
,
164 Context
*on_finish
) {
165 ceph_assert(s_instance
!= nullptr);
166 s_instance
->demoted
= demoted
;
167 s_instance
->primary_mirror_uuid
= primary_mirror_uuid
;
168 s_instance
->primary_snap_id
= primary_snap_id
;
169 s_instance
->snap_seqs
= snap_seqs
;
170 s_instance
->snap_id
= snap_id
;
171 s_instance
->on_finish
= on_finish
;
175 Context
* on_finish
= nullptr;
177 CreateNonPrimaryRequest() {
181 MOCK_METHOD0(send
, void());
185 struct GetImageStateRequest
<MockTestImageCtx
> {
186 uint64_t snap_id
= CEPH_NOSNAP
;
188 static GetImageStateRequest
* s_instance
;
189 static GetImageStateRequest
* create(MockTestImageCtx
*image_ctx
,
191 ImageState
*image_state
,
192 Context
*on_finish
) {
193 ceph_assert(s_instance
!= nullptr);
194 s_instance
->snap_id
= snap_id
;
195 s_instance
->on_finish
= on_finish
;
199 Context
* on_finish
= nullptr;
201 GetImageStateRequest() {
205 MOCK_METHOD0(send
, void());
209 struct ImageMeta
<MockTestImageCtx
> {
210 MOCK_METHOD1(load
, void(Context
*));
212 bool resync_requested
= false;
216 struct UnlinkPeerRequest
<MockTestImageCtx
> {
218 std::string mirror_peer_uuid
;
220 static UnlinkPeerRequest
* s_instance
;
221 static UnlinkPeerRequest
*create (MockTestImageCtx
*image_ctx
,
223 const std::string
&mirror_peer_uuid
,
224 Context
*on_finish
) {
225 ceph_assert(s_instance
!= nullptr);
226 s_instance
->snap_id
= snap_id
;
227 s_instance
->mirror_peer_uuid
= mirror_peer_uuid
;
228 s_instance
->on_finish
= on_finish
;
232 Context
* on_finish
= nullptr;
234 UnlinkPeerRequest() {
238 MOCK_METHOD0(send
, void());
241 CreateNonPrimaryRequest
<MockTestImageCtx
>* CreateNonPrimaryRequest
<MockTestImageCtx
>::s_instance
= nullptr;
242 GetImageStateRequest
<MockTestImageCtx
>* GetImageStateRequest
<MockTestImageCtx
>::s_instance
= nullptr;
243 UnlinkPeerRequest
<MockTestImageCtx
>* UnlinkPeerRequest
<MockTestImageCtx
>::s_instance
= nullptr;
245 } // namespace snapshot
246 } // namespace mirror
247 } // namespace librbd
253 struct InstanceWatcher
<librbd::MockTestImageCtx
> {
254 MOCK_METHOD1(cancel_sync_request
, void(const std::string
&));
255 MOCK_METHOD2(notify_sync_request
, void(const std::string
&,
257 MOCK_METHOD1(notify_sync_complete
, void(const std::string
&));
261 struct Threads
<librbd::MockTestImageCtx
> {
262 MockSafeTimer
*timer
;
263 ceph::mutex
&timer_lock
;
265 MockContextWQ
*work_queue
;
267 Threads(Threads
<librbd::ImageCtx
>* threads
)
268 : timer(new MockSafeTimer()),
269 timer_lock(threads
->timer_lock
),
270 work_queue(new MockContextWQ()) {
280 struct MockReplayerListener
: public image_replayer::ReplayerListener
{
281 MOCK_METHOD0(handle_notification
, void());
284 } // anonymous namespace
286 namespace image_replayer
{
289 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
290 static CloseImageRequest
* s_instance
;
291 librbd::MockTestImageCtx
**image_ctx
= nullptr;
292 Context
*on_finish
= nullptr;
294 static CloseImageRequest
* create(librbd::MockTestImageCtx
**image_ctx
,
295 Context
*on_finish
) {
296 ceph_assert(s_instance
!= nullptr);
297 s_instance
->image_ctx
= image_ctx
;
298 s_instance
->on_finish
= on_finish
;
302 CloseImageRequest() {
303 ceph_assert(s_instance
== nullptr);
307 ~CloseImageRequest() {
308 ceph_assert(s_instance
== this);
309 s_instance
= nullptr;
312 MOCK_METHOD0(send
, void());
315 CloseImageRequest
<librbd::MockTestImageCtx
>* CloseImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
320 struct ApplyImageStateRequest
<librbd::MockTestImageCtx
> {
321 Context
* on_finish
= nullptr;
323 static ApplyImageStateRequest
* s_instance
;
324 static ApplyImageStateRequest
* create(
325 const std::string
& local_mirror_uuid
,
326 const std::string
& remote_mirror_uuid
,
327 librbd::MockTestImageCtx
* local_image_ctx
,
328 librbd::MockTestImageCtx
* remote_image_ctx
,
329 const librbd::mirror::snapshot::ImageState
& image_state
,
330 Context
* on_finish
) {
331 ceph_assert(s_instance
!= nullptr);
332 s_instance
->on_finish
= on_finish
;
336 ApplyImageStateRequest() {
340 MOCK_METHOD0(send
, void());
344 struct StateBuilder
<librbd::MockTestImageCtx
> {
345 StateBuilder(librbd::MockTestImageCtx
& local_image_ctx
,
346 librbd::MockTestImageCtx
& remote_image_ctx
,
347 librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
>&
349 : local_image_ctx(&local_image_ctx
),
350 remote_image_ctx(&remote_image_ctx
),
351 local_image_meta(&local_image_meta
) {
354 librbd::MockTestImageCtx
* local_image_ctx
;
355 librbd::MockTestImageCtx
* remote_image_ctx
;
357 std::string remote_mirror_uuid
= "remote mirror uuid";
359 librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
>*
360 local_image_meta
= nullptr;
363 ApplyImageStateRequest
<librbd::MockTestImageCtx
>* ApplyImageStateRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
365 } // namespace snapshot
366 } // namespace image_replayer
367 } // namespace mirror
370 #include "tools/rbd_mirror/image_replayer/snapshot/Replayer.cc"
374 namespace image_replayer
{
378 using ::testing::DoAll
;
379 using ::testing::InSequence
;
380 using ::testing::Invoke
;
381 using ::testing::Return
;
382 using ::testing::ReturnArg
;
383 using ::testing::StrEq
;
384 using ::testing::WithArg
;
386 class TestMockImageReplayerSnapshotReplayer
: public TestMockFixture
{
388 typedef Replayer
<librbd::MockTestImageCtx
> MockReplayer
;
389 typedef ApplyImageStateRequest
<librbd::MockTestImageCtx
> MockApplyImageStateRequest
;
390 typedef StateBuilder
<librbd::MockTestImageCtx
> MockStateBuilder
;
391 typedef InstanceWatcher
<librbd::MockTestImageCtx
> MockInstanceWatcher
;
392 typedef Threads
<librbd::MockTestImageCtx
> MockThreads
;
393 typedef CloseImageRequest
<librbd::MockTestImageCtx
> MockCloseImageRequest
;
394 typedef librbd::deep_copy::ImageCopyRequest
<librbd::MockTestImageCtx
> MockImageCopyRequest
;
395 typedef librbd::deep_copy::SnapshotCopyRequest
<librbd::MockTestImageCtx
> MockSnapshotCopyRequest
;
396 typedef librbd::mirror::ImageStateUpdateRequest
<librbd::MockTestImageCtx
> MockImageStateUpdateRequest
;
397 typedef librbd::mirror::snapshot::CreateNonPrimaryRequest
<librbd::MockTestImageCtx
> MockCreateNonPrimaryRequest
;
398 typedef librbd::mirror::snapshot::GetImageStateRequest
<librbd::MockTestImageCtx
> MockGetImageStateRequest
;
399 typedef librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
> MockImageMeta
;
400 typedef librbd::mirror::snapshot::UnlinkPeerRequest
<librbd::MockTestImageCtx
> MockUnlinkPeerRequest
;
402 void SetUp() override
{
403 TestMockFixture::SetUp();
406 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
407 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
409 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
,
411 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
,
412 &m_remote_image_ctx
));
415 void expect_work_queue_repeatedly(MockThreads
&mock_threads
) {
416 EXPECT_CALL(*mock_threads
.work_queue
, queue(_
, _
))
417 .WillRepeatedly(Invoke([this](Context
*ctx
, int r
) {
418 m_threads
->work_queue
->queue(ctx
, r
);
422 void expect_add_event_after_repeatedly(MockThreads
&mock_threads
) {
423 EXPECT_CALL(*mock_threads
.timer
, add_event_after(_
, _
))
425 DoAll(Invoke([this](double seconds
, Context
*ctx
) {
426 m_threads
->timer
->add_event_after(seconds
, ctx
);
429 EXPECT_CALL(*mock_threads
.timer
, cancel_event(_
))
431 Invoke([this](Context
*ctx
) {
432 return m_threads
->timer
->cancel_event(ctx
);
436 void expect_register_update_watcher(librbd::MockTestImageCtx
& mock_image_ctx
,
437 librbd::UpdateWatchCtx
** update_watch_ctx
,
438 uint64_t watch_handle
, int r
) {
439 EXPECT_CALL(*mock_image_ctx
.state
, register_update_watcher(_
, _
))
440 .WillOnce(Invoke([update_watch_ctx
, watch_handle
, r
]
441 (librbd::UpdateWatchCtx
* ctx
, uint64_t* handle
) {
443 *update_watch_ctx
= ctx
;
444 *handle
= watch_handle
;
450 void expect_unregister_update_watcher(librbd::MockTestImageCtx
& mock_image_ctx
,
451 uint64_t watch_handle
, int r
) {
452 EXPECT_CALL(*mock_image_ctx
.state
, unregister_update_watcher(watch_handle
, _
))
453 .WillOnce(WithArg
<1>(Invoke([this, r
](Context
* ctx
) {
454 m_threads
->work_queue
->queue(ctx
, r
);
458 void expect_load_image_meta(MockImageMeta
& mock_image_meta
,
459 bool resync_requested
, int r
) {
460 EXPECT_CALL(mock_image_meta
, load(_
))
461 .WillOnce(Invoke([this, &mock_image_meta
, resync_requested
, r
](Context
* ctx
) {
462 mock_image_meta
.resync_requested
= resync_requested
;
463 m_threads
->work_queue
->queue(ctx
, r
);
467 void expect_is_refresh_required(librbd::MockTestImageCtx
& mock_image_ctx
,
469 EXPECT_CALL(*mock_image_ctx
.state
, is_refresh_required())
470 .WillOnce(Return(is_required
));
473 void expect_refresh(librbd::MockTestImageCtx
& mock_image_ctx
,
474 const std::map
<uint64_t, librbd::SnapInfo
>& snaps
,
476 EXPECT_CALL(*mock_image_ctx
.state
, refresh(_
))
477 .WillOnce(Invoke([this, &mock_image_ctx
, snaps
, r
](Context
* ctx
) {
478 mock_image_ctx
.snap_info
= snaps
;
479 m_threads
->work_queue
->queue(ctx
, r
);
483 void expect_notify_update(librbd::MockTestImageCtx
& mock_image_ctx
) {
484 EXPECT_CALL(mock_image_ctx
, notify_update(_
))
485 .WillOnce(Invoke([this](Context
* ctx
) {
486 m_threads
->work_queue
->queue(ctx
, 0);
490 void expect_prune_non_primary_snapshot(librbd::MockTestImageCtx
& mock_image_ctx
,
491 uint64_t snap_id
, int r
) {
492 EXPECT_CALL(mock_image_ctx
, get_snap_info(snap_id
))
493 .WillOnce(Invoke([&mock_image_ctx
](uint64_t snap_id
) -> librbd::SnapInfo
* {
494 auto it
= mock_image_ctx
.snap_info
.find(snap_id
);
495 if (it
== mock_image_ctx
.snap_info
.end()) {
500 EXPECT_CALL(*mock_image_ctx
.operations
, snap_remove(_
, _
, _
))
501 .WillOnce(WithArg
<2>(Invoke([this, r
](Context
* ctx
) {
502 m_threads
->work_queue
->queue(ctx
, r
);
506 void expect_snapshot_copy(MockSnapshotCopyRequest
& mock_snapshot_copy_request
,
507 uint64_t src_snap_id_start
,
508 uint64_t src_snap_id_end
,
509 uint64_t dst_snap_id_start
,
510 const librbd::SnapSeqs
& snap_seqs
, int r
) {
511 EXPECT_CALL(mock_snapshot_copy_request
, send())
512 .WillOnce(Invoke([this, &req
=mock_snapshot_copy_request
,
513 src_snap_id_start
, src_snap_id_end
, dst_snap_id_start
,
515 ASSERT_EQ(src_snap_id_start
, req
.src_snap_id_start
);
516 ASSERT_EQ(src_snap_id_end
, req
.src_snap_id_end
);
517 ASSERT_EQ(dst_snap_id_start
, req
.dst_snap_id_start
);
518 *req
.snap_seqs
= snap_seqs
;
519 m_threads
->work_queue
->queue(req
.on_finish
, r
);
523 void expect_get_image_state(MockGetImageStateRequest
& mock_get_image_state_request
,
524 uint64_t snap_id
, int r
) {
525 EXPECT_CALL(mock_get_image_state_request
, send())
526 .WillOnce(Invoke([this, &req
=mock_get_image_state_request
, snap_id
, r
]() {
527 ASSERT_EQ(snap_id
, req
.snap_id
);
528 m_threads
->work_queue
->queue(req
.on_finish
, r
);
532 void expect_create_non_primary_request(MockCreateNonPrimaryRequest
& mock_create_non_primary_request
,
534 const std::string
& primary_mirror_uuid
,
535 uint64_t primary_snap_id
,
536 const librbd::SnapSeqs
& snap_seqs
,
537 uint64_t snap_id
, int r
) {
538 EXPECT_CALL(mock_create_non_primary_request
, send())
539 .WillOnce(Invoke([this, &req
=mock_create_non_primary_request
, demoted
,
540 primary_mirror_uuid
, primary_snap_id
, snap_seqs
,
542 ASSERT_EQ(demoted
, req
.demoted
);
543 ASSERT_EQ(primary_mirror_uuid
, req
.primary_mirror_uuid
);
544 ASSERT_EQ(primary_snap_id
, req
.primary_snap_id
);
545 ASSERT_EQ(snap_seqs
, req
.snap_seqs
);
546 *req
.snap_id
= snap_id
;
547 m_threads
->work_queue
->queue(req
.on_finish
, r
);
551 void expect_update_mirror_image_state(MockImageStateUpdateRequest
& mock_image_state_update_request
,
553 EXPECT_CALL(mock_image_state_update_request
, send())
554 .WillOnce(Invoke([this, &req
=mock_image_state_update_request
, r
]() {
555 m_threads
->work_queue
->queue(req
.on_finish
, r
);
559 void expect_notify_sync_request(MockInstanceWatcher
& mock_instance_watcher
,
560 const std::string
& image_id
, int r
) {
561 EXPECT_CALL(mock_instance_watcher
, notify_sync_request(image_id
, _
))
562 .WillOnce(WithArg
<1>(Invoke([this, r
](Context
* ctx
) {
563 m_threads
->work_queue
->queue(ctx
, r
);
567 void expect_notify_sync_complete(MockInstanceWatcher
& mock_instance_watcher
,
568 const std::string
& image_id
) {
569 EXPECT_CALL(mock_instance_watcher
, notify_sync_complete(image_id
));
572 void expect_image_copy(MockImageCopyRequest
& mock_image_copy_request
,
573 uint64_t src_snap_id_start
, uint64_t src_snap_id_end
,
574 uint64_t dst_snap_id_start
,
575 const librbd::deep_copy::ObjectNumber
& object_number
,
576 const librbd::SnapSeqs
& snap_seqs
, int r
) {
577 EXPECT_CALL(mock_image_copy_request
, send())
578 .WillOnce(Invoke([this, &req
=mock_image_copy_request
, src_snap_id_start
,
579 src_snap_id_end
, dst_snap_id_start
, object_number
,
581 ASSERT_EQ(src_snap_id_start
, req
.src_snap_id_start
);
582 ASSERT_EQ(src_snap_id_end
, req
.src_snap_id_end
);
583 ASSERT_EQ(dst_snap_id_start
, req
.dst_snap_id_start
);
584 ASSERT_EQ(object_number
, req
.object_number
);
585 ASSERT_EQ(snap_seqs
, req
.snap_seqs
);
586 m_threads
->work_queue
->queue(req
.on_finish
, r
);
590 void expect_unlink_peer(MockUnlinkPeerRequest
& mock_unlink_peer_request
,
591 uint64_t snap_id
, const std::string
& mirror_peer_uuid
,
593 EXPECT_CALL(mock_unlink_peer_request
, send())
594 .WillOnce(Invoke([this, &req
=mock_unlink_peer_request
, snap_id
,
595 mirror_peer_uuid
, r
]() {
596 ASSERT_EQ(snap_id
, req
.snap_id
);
597 ASSERT_EQ(mirror_peer_uuid
, req
.mirror_peer_uuid
);
598 m_threads
->work_queue
->queue(req
.on_finish
, r
);
602 void expect_apply_image_state(
603 MockApplyImageStateRequest
& mock_request
, int r
) {
604 EXPECT_CALL(mock_request
, send())
605 .WillOnce(Invoke([this, &req
=mock_request
, r
]() {
606 m_threads
->work_queue
->queue(req
.on_finish
, r
);
610 void expect_mirror_image_snapshot_set_copy_progress(
611 librbd::MockTestImageCtx
& mock_test_image_ctx
, uint64_t snap_id
,
612 bool completed
, uint64_t last_copied_object
, int r
) {
615 encode(completed
, bl
);
616 encode(last_copied_object
, bl
);
618 EXPECT_CALL(get_mock_io_ctx(mock_test_image_ctx
.md_ctx
),
619 exec(mock_test_image_ctx
.header_oid
, _
, StrEq("rbd"),
620 StrEq("mirror_image_snapshot_set_copy_progress"),
621 ContentsEqual(bl
), _
, _
, _
))
622 .WillOnce(Return(r
));
625 void expect_send(MockCloseImageRequest
&mock_close_image_request
, int r
) {
626 EXPECT_CALL(mock_close_image_request
, send())
627 .WillOnce(Invoke([this, &mock_close_image_request
, r
]() {
628 *mock_close_image_request
.image_ctx
= nullptr;
629 m_threads
->work_queue
->queue(mock_close_image_request
.on_finish
, r
);
633 void expect_notification(MockThreads
& mock_threads
,
634 MockReplayerListener
& mock_replayer_listener
) {
635 EXPECT_CALL(mock_replayer_listener
, handle_notification())
636 .WillRepeatedly(Invoke([this]() {
637 std::unique_lock locker
{m_lock
};
643 int wait_for_notification(uint32_t count
) {
644 std::unique_lock locker
{m_lock
};
645 for (uint32_t idx
= 0; idx
< count
; ++idx
) {
646 while (m_notifications
== 0) {
647 if (m_cond
.wait_for(locker
, 10s
) == std::cv_status::timeout
) {
656 int init_entry_replayer(MockReplayer
& mock_replayer
,
657 MockThreads
& mock_threads
,
658 librbd::MockTestImageCtx
& mock_local_image_ctx
,
659 librbd::MockTestImageCtx
& mock_remote_image_ctx
,
660 MockReplayerListener
& mock_replayer_listener
,
661 MockImageMeta
& mock_image_meta
,
662 librbd::UpdateWatchCtx
** update_watch_ctx
) {
663 expect_register_update_watcher(mock_local_image_ctx
, update_watch_ctx
, 123,
665 expect_register_update_watcher(mock_remote_image_ctx
, update_watch_ctx
, 234,
667 expect_load_image_meta(mock_image_meta
, false, 0);
668 expect_is_refresh_required(mock_local_image_ctx
, false);
669 expect_is_refresh_required(mock_remote_image_ctx
, false);
671 C_SaferCond init_ctx
;
672 mock_replayer
.init(&init_ctx
);
673 int r
= init_ctx
.wait();
678 return wait_for_notification(2);
681 int shut_down_entry_replayer(MockReplayer
& mock_replayer
,
682 MockThreads
& mock_threads
,
683 librbd::MockTestImageCtx
& mock_local_image_ctx
,
684 librbd::MockTestImageCtx
& mock_remote_image_ctx
) {
685 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, 0);
686 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
688 C_SaferCond shutdown_ctx
;
689 mock_replayer
.shut_down(&shutdown_ctx
);
690 return shutdown_ctx
.wait();
693 librbd::ImageCtx
* m_local_image_ctx
= nullptr;
694 librbd::ImageCtx
* m_remote_image_ctx
= nullptr;
696 PoolMetaCache m_pool_meta_cache
{g_ceph_context
};
698 ceph::mutex m_lock
= ceph::make_mutex(
699 "TestMockImageReplayerSnapshotReplayer");
700 ceph::condition_variable m_cond
;
701 uint32_t m_notifications
= 0;
704 TEST_F(TestMockImageReplayerSnapshotReplayer
, InitShutDown
) {
705 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
706 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
708 MockThreads
mock_threads(m_threads
);
709 expect_work_queue_repeatedly(mock_threads
);
711 MockReplayerListener mock_replayer_listener
;
712 expect_notification(mock_threads
, mock_replayer_listener
);
716 MockInstanceWatcher mock_instance_watcher
;
717 MockImageMeta mock_image_meta
;
718 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
719 mock_remote_image_ctx
,
721 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
722 "local mirror uuid", &m_pool_meta_cache
,
723 &mock_state_builder
, &mock_replayer_listener
};
724 m_pool_meta_cache
.set_remote_pool_meta(
725 m_remote_io_ctx
.get_id(),
726 {"remote mirror uuid", "remote mirror peer uuid"});
728 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
729 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
730 mock_local_image_ctx
,
731 mock_remote_image_ctx
,
732 mock_replayer_listener
,
735 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
736 mock_local_image_ctx
,
737 mock_remote_image_ctx
));
740 TEST_F(TestMockImageReplayerSnapshotReplayer
, SyncSnapshot
) {
741 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
742 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
744 // it should sync two snapshots and skip two (user and mirror w/o matching
746 mock_remote_image_ctx
.snap_info
= {
747 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
748 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
749 "", CEPH_NOSNAP
, true, 0, {}},
751 {2U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
753 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
754 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {""},
755 "", CEPH_NOSNAP
, true, 0, {}},
757 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
758 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
759 "", CEPH_NOSNAP
, true, 0, {}},
762 MockThreads
mock_threads(m_threads
);
763 expect_work_queue_repeatedly(mock_threads
);
765 MockReplayerListener mock_replayer_listener
;
766 expect_notification(mock_threads
, mock_replayer_listener
);
770 MockInstanceWatcher mock_instance_watcher
;
771 MockImageMeta mock_image_meta
;
772 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
773 mock_remote_image_ctx
,
775 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
776 "local mirror uuid", &m_pool_meta_cache
,
777 &mock_state_builder
, &mock_replayer_listener
};
778 m_pool_meta_cache
.set_remote_pool_meta(
779 m_remote_io_ctx
.get_id(),
780 {"remote mirror uuid", "remote mirror peer uuid"});
782 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
785 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
787 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
791 expect_load_image_meta(mock_image_meta
, false, 0);
792 expect_is_refresh_required(mock_local_image_ctx
, false);
793 expect_is_refresh_required(mock_remote_image_ctx
, false);
794 MockSnapshotCopyRequest mock_snapshot_copy_request
;
795 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
797 MockGetImageStateRequest mock_get_image_state_request
;
798 expect_get_image_state(mock_get_image_state_request
, 1, 0);
799 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
800 expect_create_non_primary_request(mock_create_non_primary_request
,
801 false, "remote mirror uuid", 1,
802 {{1, CEPH_NOSNAP
}}, 11, 0);
803 MockImageStateUpdateRequest mock_image_state_update_request
;
804 expect_update_mirror_image_state(mock_image_state_update_request
, 0);
805 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
806 MockImageCopyRequest mock_image_copy_request
;
807 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
808 {{1, CEPH_NOSNAP
}}, 0);
809 MockApplyImageStateRequest mock_apply_state_request
;
810 expect_apply_image_state(mock_apply_state_request
, 0);
811 expect_mirror_image_snapshot_set_copy_progress(
812 mock_local_image_ctx
, 11, true, 0, 0);
813 expect_notify_update(mock_local_image_ctx
);
814 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
817 expect_load_image_meta(mock_image_meta
, false, 0);
818 expect_is_refresh_required(mock_local_image_ctx
, true);
820 mock_local_image_ctx
, {
821 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
822 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
823 1, true, 0, {{1, CEPH_NOSNAP
}}},
826 expect_is_refresh_required(mock_remote_image_ctx
, true);
828 mock_remote_image_ctx
, {
829 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
830 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
831 "", CEPH_NOSNAP
, true, 0, {}},
833 {2U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
835 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
836 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {""},
837 "", CEPH_NOSNAP
, true, 0, {}},
839 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
840 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
841 "", CEPH_NOSNAP
, true, 0, {}},
843 {5U, librbd::SnapInfo
{"snap5", cls::rbd::MirrorSnapshotNamespace
{
844 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
845 "", CEPH_NOSNAP
, true, 0, {}},
848 expect_snapshot_copy(mock_snapshot_copy_request
, 1, 4, 11,
849 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP
}}, 0);
850 expect_get_image_state(mock_get_image_state_request
, 4, 0);
851 expect_create_non_primary_request(mock_create_non_primary_request
,
852 false, "remote mirror uuid", 4,
853 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP
}}, 14,
855 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
856 expect_image_copy(mock_image_copy_request
, 1, 4, 11, {},
857 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP
}}, 0);
858 expect_apply_image_state(mock_apply_state_request
, 0);
859 expect_mirror_image_snapshot_set_copy_progress(
860 mock_local_image_ctx
, 14, true, 0, 0);
861 expect_notify_update(mock_local_image_ctx
);
862 MockUnlinkPeerRequest mock_unlink_peer_request
;
863 expect_unlink_peer(mock_unlink_peer_request
, 1, "remote mirror peer uuid",
865 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
867 // prune non-primary snap1
868 expect_load_image_meta(mock_image_meta
, false, 0);
869 expect_is_refresh_required(mock_local_image_ctx
, true);
871 mock_local_image_ctx
, {
872 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
873 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
876 {12U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
878 {14U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
879 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
883 expect_is_refresh_required(mock_remote_image_ctx
, true);
885 mock_remote_image_ctx
, {
886 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
887 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
888 "", CEPH_NOSNAP
, true, 0, {}},
890 {2U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
892 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
893 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {""},
894 "", CEPH_NOSNAP
, true, 0, {}},
896 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
897 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
898 "", CEPH_NOSNAP
, true, 0, {}},
901 expect_prune_non_primary_snapshot(mock_local_image_ctx
, 11, 0);
904 expect_load_image_meta(mock_image_meta
, false, 0);
905 expect_is_refresh_required(mock_local_image_ctx
, true);
907 mock_local_image_ctx
, {
908 {14U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
909 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
913 expect_is_refresh_required(mock_remote_image_ctx
, true);
915 mock_remote_image_ctx
, {
916 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
917 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
918 "", CEPH_NOSNAP
, true, 0, {}},
923 C_SaferCond init_ctx
;
924 mock_replayer
.init(&init_ctx
);
925 ASSERT_EQ(0, init_ctx
.wait());
927 // wait for sync to complete
928 ASSERT_EQ(0, wait_for_notification(4));
931 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
932 mock_local_image_ctx
,
933 mock_remote_image_ctx
));
936 TEST_F(TestMockImageReplayerSnapshotReplayer
, InterruptedSync
) {
937 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
938 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
940 MockThreads
mock_threads(m_threads
);
941 expect_work_queue_repeatedly(mock_threads
);
943 MockReplayerListener mock_replayer_listener
;
944 expect_notification(mock_threads
, mock_replayer_listener
);
948 MockInstanceWatcher mock_instance_watcher
;
949 MockImageMeta mock_image_meta
;
950 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
951 mock_remote_image_ctx
,
953 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
954 "local mirror uuid", &m_pool_meta_cache
,
955 &mock_state_builder
, &mock_replayer_listener
};
956 m_pool_meta_cache
.set_remote_pool_meta(
957 m_remote_io_ctx
.get_id(),
958 {"remote mirror uuid", "remote mirror peer uuid"});
960 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
961 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
962 mock_local_image_ctx
,
963 mock_remote_image_ctx
,
964 mock_replayer_listener
,
968 // inject a incomplete sync snapshot
969 mock_remote_image_ctx
.snap_info
= {
970 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
971 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
972 "", CEPH_NOSNAP
, true, 0, {}},
974 mock_local_image_ctx
.snap_info
= {
975 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
976 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
977 1, false, 123, {{1, CEPH_NOSNAP
}}},
981 expect_load_image_meta(mock_image_meta
, false, 0);
982 expect_is_refresh_required(mock_local_image_ctx
, false);
983 expect_is_refresh_required(mock_remote_image_ctx
, false);
984 MockGetImageStateRequest mock_get_image_state_request
;
985 expect_get_image_state(mock_get_image_state_request
, 11, 0);
986 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
987 MockImageCopyRequest mock_image_copy_request
;
988 expect_image_copy(mock_image_copy_request
, 0, 1, 0,
989 librbd::deep_copy::ObjectNumber
{123U},
990 {{1, CEPH_NOSNAP
}}, 0);
991 MockApplyImageStateRequest mock_apply_state_request
;
992 expect_apply_image_state(mock_apply_state_request
, 0);
993 expect_mirror_image_snapshot_set_copy_progress(
994 mock_local_image_ctx
, 11, true, 123, 0);
995 expect_notify_update(mock_local_image_ctx
);
996 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
999 expect_load_image_meta(mock_image_meta
, false, 0);
1000 expect_is_refresh_required(mock_local_image_ctx
, true);
1002 mock_local_image_ctx
, {
1003 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1004 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
1008 expect_is_refresh_required(mock_remote_image_ctx
, false);
1011 update_watch_ctx
->handle_notify();
1013 // wait for sync to complete
1014 ASSERT_EQ(0, wait_for_notification(2));
1016 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1017 mock_local_image_ctx
,
1018 mock_remote_image_ctx
));
1021 TEST_F(TestMockImageReplayerSnapshotReplayer
, RemoteImageDemoted
) {
1022 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1023 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1025 MockThreads
mock_threads(m_threads
);
1026 expect_work_queue_repeatedly(mock_threads
);
1028 MockReplayerListener mock_replayer_listener
;
1029 expect_notification(mock_threads
, mock_replayer_listener
);
1033 MockInstanceWatcher mock_instance_watcher
;
1034 MockImageMeta mock_image_meta
;
1035 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1036 mock_remote_image_ctx
,
1038 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1039 "local mirror uuid", &m_pool_meta_cache
,
1040 &mock_state_builder
, &mock_replayer_listener
};
1041 m_pool_meta_cache
.set_remote_pool_meta(
1042 m_remote_io_ctx
.get_id(),
1043 {"remote mirror uuid", "remote mirror peer uuid"});
1045 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1046 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1047 mock_local_image_ctx
,
1048 mock_remote_image_ctx
,
1049 mock_replayer_listener
,
1051 &update_watch_ctx
));
1053 // inject a demotion snapshot
1054 mock_remote_image_ctx
.snap_info
= {
1055 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1056 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
,
1057 {"remote mirror peer uuid"}, "", CEPH_NOSNAP
, true, 0, {}},
1061 expect_load_image_meta(mock_image_meta
, false, 0);
1062 expect_is_refresh_required(mock_local_image_ctx
, false);
1063 expect_is_refresh_required(mock_remote_image_ctx
, false);
1064 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1065 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1067 MockGetImageStateRequest mock_get_image_state_request
;
1068 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1069 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1070 expect_create_non_primary_request(mock_create_non_primary_request
,
1071 true, "remote mirror uuid", 1,
1072 {{1, CEPH_NOSNAP
}}, 11, 0);
1073 MockImageStateUpdateRequest mock_image_state_update_request
;
1074 expect_update_mirror_image_state(mock_image_state_update_request
, 0);
1075 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1076 MockImageCopyRequest mock_image_copy_request
;
1077 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
1078 {{1, CEPH_NOSNAP
}}, 0);
1079 MockApplyImageStateRequest mock_apply_state_request
;
1080 expect_apply_image_state(mock_apply_state_request
, 0);
1081 expect_mirror_image_snapshot_set_copy_progress(
1082 mock_local_image_ctx
, 11, true, 0, 0);
1083 expect_notify_update(mock_local_image_ctx
);
1084 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
1087 expect_load_image_meta(mock_image_meta
, false, 0);
1088 expect_is_refresh_required(mock_local_image_ctx
, true);
1090 mock_local_image_ctx
, {
1091 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1092 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
1096 expect_is_refresh_required(mock_remote_image_ctx
, false);
1099 update_watch_ctx
->handle_notify();
1101 // wait for sync to complete and expect replay complete
1102 ASSERT_EQ(0, wait_for_notification(2));
1103 ASSERT_FALSE(mock_replayer
.is_replaying());
1105 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1106 mock_local_image_ctx
,
1107 mock_remote_image_ctx
));
1110 TEST_F(TestMockImageReplayerSnapshotReplayer
, LocalImagePromoted
) {
1111 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1112 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1114 MockThreads
mock_threads(m_threads
);
1115 expect_work_queue_repeatedly(mock_threads
);
1117 MockReplayerListener mock_replayer_listener
;
1118 expect_notification(mock_threads
, mock_replayer_listener
);
1122 MockInstanceWatcher mock_instance_watcher
;
1123 MockImageMeta mock_image_meta
;
1124 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1125 mock_remote_image_ctx
,
1127 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1128 "local mirror uuid", &m_pool_meta_cache
,
1129 &mock_state_builder
, &mock_replayer_listener
};
1130 m_pool_meta_cache
.set_remote_pool_meta(
1131 m_remote_io_ctx
.get_id(),
1132 {"remote mirror uuid", "remote mirror peer uuid"});
1134 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1135 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1136 mock_local_image_ctx
,
1137 mock_remote_image_ctx
,
1138 mock_replayer_listener
,
1140 &update_watch_ctx
));
1142 // inject a promotion snapshot
1143 mock_local_image_ctx
.snap_info
= {
1144 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1145 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
,
1146 {"remote mirror peer uuid"}, "", CEPH_NOSNAP
, true, 0, {}},
1150 expect_load_image_meta(mock_image_meta
, false, 0);
1151 expect_is_refresh_required(mock_local_image_ctx
, false);
1152 expect_is_refresh_required(mock_remote_image_ctx
, false);
1155 update_watch_ctx
->handle_notify();
1157 // wait for sync to complete and expect replay complete
1158 ASSERT_EQ(0, wait_for_notification(1));
1159 ASSERT_FALSE(mock_replayer
.is_replaying());
1161 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1162 mock_local_image_ctx
,
1163 mock_remote_image_ctx
));
1166 TEST_F(TestMockImageReplayerSnapshotReplayer
, ResyncRequested
) {
1167 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1168 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1170 MockThreads
mock_threads(m_threads
);
1171 expect_work_queue_repeatedly(mock_threads
);
1173 MockReplayerListener mock_replayer_listener
;
1174 expect_notification(mock_threads
, mock_replayer_listener
);
1178 MockInstanceWatcher mock_instance_watcher
;
1179 MockImageMeta mock_image_meta
;
1180 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1181 mock_remote_image_ctx
,
1183 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1184 "local mirror uuid", &m_pool_meta_cache
,
1185 &mock_state_builder
, &mock_replayer_listener
};
1186 m_pool_meta_cache
.set_remote_pool_meta(
1187 m_remote_io_ctx
.get_id(),
1188 {"remote mirror uuid", "remote mirror peer uuid"});
1190 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1191 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1192 mock_local_image_ctx
,
1193 mock_remote_image_ctx
,
1194 mock_replayer_listener
,
1196 &update_watch_ctx
));
1199 expect_load_image_meta(mock_image_meta
, true, 0);
1202 update_watch_ctx
->handle_notify();
1204 // wait for sync to complete and expect replay complete
1205 ASSERT_EQ(0, wait_for_notification(1));
1206 ASSERT_FALSE(mock_replayer
.is_replaying());
1208 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1209 mock_local_image_ctx
,
1210 mock_remote_image_ctx
));
1213 TEST_F(TestMockImageReplayerSnapshotReplayer
, RegisterLocalUpdateWatcherError
) {
1214 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1215 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1217 MockThreads
mock_threads(m_threads
);
1218 expect_work_queue_repeatedly(mock_threads
);
1222 MockInstanceWatcher mock_instance_watcher
;
1223 MockImageMeta mock_image_meta
;
1224 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1225 mock_remote_image_ctx
,
1227 MockReplayerListener mock_replayer_listener
;
1228 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1229 "local mirror uuid", &m_pool_meta_cache
,
1230 &mock_state_builder
, &mock_replayer_listener
};
1231 m_pool_meta_cache
.set_remote_pool_meta(
1232 m_remote_io_ctx
.get_id(),
1233 {"remote mirror uuid", "remote mirror peer uuid"});
1236 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1237 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
1241 C_SaferCond init_ctx
;
1242 mock_replayer
.init(&init_ctx
);
1243 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
1246 TEST_F(TestMockImageReplayerSnapshotReplayer
, RegisterRemoteUpdateWatcherError
) {
1247 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1248 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1250 MockThreads
mock_threads(m_threads
);
1251 expect_work_queue_repeatedly(mock_threads
);
1255 MockInstanceWatcher mock_instance_watcher
;
1256 MockImageMeta mock_image_meta
;
1257 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1258 mock_remote_image_ctx
,
1260 MockReplayerListener mock_replayer_listener
;
1261 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1262 "local mirror uuid", &m_pool_meta_cache
,
1263 &mock_state_builder
, &mock_replayer_listener
};
1264 m_pool_meta_cache
.set_remote_pool_meta(
1265 m_remote_io_ctx
.get_id(),
1266 {"remote mirror uuid", "remote mirror peer uuid"});
1269 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1270 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
1272 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
1275 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
1278 C_SaferCond init_ctx
;
1279 mock_replayer
.init(&init_ctx
);
1280 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
1283 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnregisterRemoteUpdateWatcherError
) {
1284 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1285 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1287 MockThreads
mock_threads(m_threads
);
1288 expect_work_queue_repeatedly(mock_threads
);
1290 MockReplayerListener mock_replayer_listener
;
1291 expect_notification(mock_threads
, mock_replayer_listener
);
1295 MockInstanceWatcher mock_instance_watcher
;
1296 MockImageMeta mock_image_meta
;
1297 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1298 mock_remote_image_ctx
,
1300 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1301 "local mirror uuid", &m_pool_meta_cache
,
1302 &mock_state_builder
, &mock_replayer_listener
};
1303 m_pool_meta_cache
.set_remote_pool_meta(
1304 m_remote_io_ctx
.get_id(),
1305 {"remote mirror uuid", "remote mirror peer uuid"});
1307 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1308 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1309 mock_local_image_ctx
,
1310 mock_remote_image_ctx
,
1311 mock_replayer_listener
,
1313 &update_watch_ctx
));
1317 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, -EINVAL
);
1318 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
1320 C_SaferCond shutdown_ctx
;
1321 mock_replayer
.shut_down(&shutdown_ctx
);
1322 ASSERT_EQ(-EINVAL
, shutdown_ctx
.wait());
1325 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnregisterLocalUpdateWatcherError
) {
1326 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1327 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1329 MockThreads
mock_threads(m_threads
);
1330 expect_work_queue_repeatedly(mock_threads
);
1332 MockReplayerListener mock_replayer_listener
;
1333 expect_notification(mock_threads
, mock_replayer_listener
);
1337 MockInstanceWatcher mock_instance_watcher
;
1338 MockImageMeta mock_image_meta
;
1339 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1340 mock_remote_image_ctx
,
1342 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1343 "local mirror uuid", &m_pool_meta_cache
,
1344 &mock_state_builder
, &mock_replayer_listener
};
1345 m_pool_meta_cache
.set_remote_pool_meta(
1346 m_remote_io_ctx
.get_id(),
1347 {"remote mirror uuid", "remote mirror peer uuid"});
1349 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1350 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1351 mock_local_image_ctx
,
1352 mock_remote_image_ctx
,
1353 mock_replayer_listener
,
1355 &update_watch_ctx
));
1359 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, 0);
1360 expect_unregister_update_watcher(mock_local_image_ctx
, 123, -EINVAL
);
1362 C_SaferCond shutdown_ctx
;
1363 mock_replayer
.shut_down(&shutdown_ctx
);
1364 ASSERT_EQ(-EINVAL
, shutdown_ctx
.wait());
1367 TEST_F(TestMockImageReplayerSnapshotReplayer
, LoadImageMetaError
) {
1368 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1369 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1371 MockThreads
mock_threads(m_threads
);
1372 expect_work_queue_repeatedly(mock_threads
);
1374 MockReplayerListener mock_replayer_listener
;
1375 expect_notification(mock_threads
, mock_replayer_listener
);
1379 MockInstanceWatcher mock_instance_watcher
;
1380 MockImageMeta mock_image_meta
;
1381 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1382 mock_remote_image_ctx
,
1384 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1385 "local mirror uuid", &m_pool_meta_cache
,
1386 &mock_state_builder
, &mock_replayer_listener
};
1387 m_pool_meta_cache
.set_remote_pool_meta(
1388 m_remote_io_ctx
.get_id(),
1389 {"remote mirror uuid", "remote mirror peer uuid"});
1391 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1392 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1393 mock_local_image_ctx
,
1394 mock_remote_image_ctx
,
1395 mock_replayer_listener
,
1397 &update_watch_ctx
));
1400 expect_load_image_meta(mock_image_meta
, false, -EINVAL
);
1403 update_watch_ctx
->handle_notify();
1405 // wait for sync to complete and expect replay complete
1406 ASSERT_EQ(0, wait_for_notification(1));
1407 ASSERT_FALSE(mock_replayer
.is_replaying());
1408 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1410 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1411 mock_local_image_ctx
,
1412 mock_remote_image_ctx
));
1415 TEST_F(TestMockImageReplayerSnapshotReplayer
, RefreshLocalImageError
) {
1416 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1417 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1419 MockThreads
mock_threads(m_threads
);
1420 expect_work_queue_repeatedly(mock_threads
);
1422 MockReplayerListener mock_replayer_listener
;
1423 expect_notification(mock_threads
, mock_replayer_listener
);
1427 MockInstanceWatcher mock_instance_watcher
;
1428 MockImageMeta mock_image_meta
;
1429 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1430 mock_remote_image_ctx
,
1432 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1433 "local mirror uuid", &m_pool_meta_cache
,
1434 &mock_state_builder
, &mock_replayer_listener
};
1435 m_pool_meta_cache
.set_remote_pool_meta(
1436 m_remote_io_ctx
.get_id(),
1437 {"remote mirror uuid", "remote mirror peer uuid"});
1439 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1440 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1441 mock_local_image_ctx
,
1442 mock_remote_image_ctx
,
1443 mock_replayer_listener
,
1445 &update_watch_ctx
));
1448 expect_load_image_meta(mock_image_meta
, false, 0);
1449 expect_is_refresh_required(mock_local_image_ctx
, true);
1450 expect_refresh(mock_local_image_ctx
, {}, -EINVAL
);
1453 update_watch_ctx
->handle_notify();
1455 // wait for sync to complete and expect replay complete
1456 ASSERT_EQ(0, wait_for_notification(1));
1457 ASSERT_FALSE(mock_replayer
.is_replaying());
1458 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1460 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1461 mock_local_image_ctx
,
1462 mock_remote_image_ctx
));
1465 TEST_F(TestMockImageReplayerSnapshotReplayer
, RefreshRemoteImageError
) {
1466 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1467 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1469 MockThreads
mock_threads(m_threads
);
1470 expect_work_queue_repeatedly(mock_threads
);
1472 MockReplayerListener mock_replayer_listener
;
1473 expect_notification(mock_threads
, mock_replayer_listener
);
1477 MockInstanceWatcher mock_instance_watcher
;
1478 MockImageMeta mock_image_meta
;
1479 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1480 mock_remote_image_ctx
,
1482 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1483 "local mirror uuid", &m_pool_meta_cache
,
1484 &mock_state_builder
, &mock_replayer_listener
};
1485 m_pool_meta_cache
.set_remote_pool_meta(
1486 m_remote_io_ctx
.get_id(),
1487 {"remote mirror uuid", "remote mirror peer uuid"});
1489 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1490 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1491 mock_local_image_ctx
,
1492 mock_remote_image_ctx
,
1493 mock_replayer_listener
,
1495 &update_watch_ctx
));
1498 expect_load_image_meta(mock_image_meta
, false, 0);
1499 expect_is_refresh_required(mock_local_image_ctx
, false);
1500 expect_is_refresh_required(mock_remote_image_ctx
, true);
1501 expect_refresh(mock_remote_image_ctx
, {}, -EINVAL
);
1504 update_watch_ctx
->handle_notify();
1506 // wait for sync to complete and expect replay complete
1507 ASSERT_EQ(0, wait_for_notification(1));
1508 ASSERT_FALSE(mock_replayer
.is_replaying());
1509 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1511 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1512 mock_local_image_ctx
,
1513 mock_remote_image_ctx
));
1516 TEST_F(TestMockImageReplayerSnapshotReplayer
, CopySnapshotsError
) {
1517 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1518 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1520 MockThreads
mock_threads(m_threads
);
1521 expect_work_queue_repeatedly(mock_threads
);
1523 MockReplayerListener mock_replayer_listener
;
1524 expect_notification(mock_threads
, mock_replayer_listener
);
1528 MockInstanceWatcher mock_instance_watcher
;
1529 MockImageMeta mock_image_meta
;
1530 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1531 mock_remote_image_ctx
,
1533 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1534 "local mirror uuid", &m_pool_meta_cache
,
1535 &mock_state_builder
, &mock_replayer_listener
};
1536 m_pool_meta_cache
.set_remote_pool_meta(
1537 m_remote_io_ctx
.get_id(),
1538 {"remote mirror uuid", "remote mirror peer uuid"});
1540 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1541 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1542 mock_local_image_ctx
,
1543 mock_remote_image_ctx
,
1544 mock_replayer_listener
,
1546 &update_watch_ctx
));
1549 mock_remote_image_ctx
.snap_info
= {
1550 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1551 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1552 CEPH_NOSNAP
, true, 0, {}},
1556 expect_load_image_meta(mock_image_meta
, false, 0);
1557 expect_is_refresh_required(mock_local_image_ctx
, false);
1558 expect_is_refresh_required(mock_remote_image_ctx
, false);
1559 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1560 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1564 update_watch_ctx
->handle_notify();
1566 // wait for sync to complete and expect replay complete
1567 ASSERT_EQ(0, wait_for_notification(1));
1568 ASSERT_FALSE(mock_replayer
.is_replaying());
1569 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1571 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1572 mock_local_image_ctx
,
1573 mock_remote_image_ctx
));
1576 TEST_F(TestMockImageReplayerSnapshotReplayer
, GetImageStateError
) {
1577 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1578 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1580 MockThreads
mock_threads(m_threads
);
1581 expect_work_queue_repeatedly(mock_threads
);
1583 MockReplayerListener mock_replayer_listener
;
1584 expect_notification(mock_threads
, mock_replayer_listener
);
1588 MockInstanceWatcher mock_instance_watcher
;
1589 MockImageMeta mock_image_meta
;
1590 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1591 mock_remote_image_ctx
,
1593 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1594 "local mirror uuid", &m_pool_meta_cache
,
1595 &mock_state_builder
, &mock_replayer_listener
};
1596 m_pool_meta_cache
.set_remote_pool_meta(
1597 m_remote_io_ctx
.get_id(),
1598 {"remote mirror uuid", "remote mirror peer uuid"});
1600 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1601 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1602 mock_local_image_ctx
,
1603 mock_remote_image_ctx
,
1604 mock_replayer_listener
,
1606 &update_watch_ctx
));
1609 mock_remote_image_ctx
.snap_info
= {
1610 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1611 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1612 CEPH_NOSNAP
, true, 0, {}},
1616 expect_load_image_meta(mock_image_meta
, false, 0);
1617 expect_is_refresh_required(mock_local_image_ctx
, false);
1618 expect_is_refresh_required(mock_remote_image_ctx
, false);
1619 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1620 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1622 MockGetImageStateRequest mock_get_image_state_request
;
1623 expect_get_image_state(mock_get_image_state_request
, 1, -EINVAL
);
1626 update_watch_ctx
->handle_notify();
1628 // wait for sync to complete and expect replay complete
1629 ASSERT_EQ(0, wait_for_notification(1));
1630 ASSERT_FALSE(mock_replayer
.is_replaying());
1631 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1633 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1634 mock_local_image_ctx
,
1635 mock_remote_image_ctx
));
1638 TEST_F(TestMockImageReplayerSnapshotReplayer
, CreateNonPrimarySnapshotError
) {
1639 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1640 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1642 MockThreads
mock_threads(m_threads
);
1643 expect_work_queue_repeatedly(mock_threads
);
1645 MockReplayerListener mock_replayer_listener
;
1646 expect_notification(mock_threads
, mock_replayer_listener
);
1650 MockInstanceWatcher mock_instance_watcher
;
1651 MockImageMeta mock_image_meta
;
1652 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1653 mock_remote_image_ctx
,
1655 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1656 "local mirror uuid", &m_pool_meta_cache
,
1657 &mock_state_builder
, &mock_replayer_listener
};
1658 m_pool_meta_cache
.set_remote_pool_meta(
1659 m_remote_io_ctx
.get_id(),
1660 {"remote mirror uuid", "remote mirror peer uuid"});
1662 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1663 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1664 mock_local_image_ctx
,
1665 mock_remote_image_ctx
,
1666 mock_replayer_listener
,
1668 &update_watch_ctx
));
1671 mock_remote_image_ctx
.snap_info
= {
1672 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1673 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1674 CEPH_NOSNAP
, true, 0, {}},
1678 expect_load_image_meta(mock_image_meta
, false, 0);
1679 expect_is_refresh_required(mock_local_image_ctx
, false);
1680 expect_is_refresh_required(mock_remote_image_ctx
, false);
1681 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1682 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1684 MockGetImageStateRequest mock_get_image_state_request
;
1685 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1686 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1687 expect_create_non_primary_request(mock_create_non_primary_request
,
1688 false, "remote mirror uuid", 1,
1689 {{1, CEPH_NOSNAP
}}, 11, -EINVAL
);
1692 update_watch_ctx
->handle_notify();
1694 // wait for sync to complete and expect replay complete
1695 ASSERT_EQ(0, wait_for_notification(1));
1696 ASSERT_FALSE(mock_replayer
.is_replaying());
1697 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1699 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1700 mock_local_image_ctx
,
1701 mock_remote_image_ctx
));
1704 TEST_F(TestMockImageReplayerSnapshotReplayer
, UpdateMirrorImageStateError
) {
1705 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1706 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1708 MockThreads
mock_threads(m_threads
);
1709 expect_work_queue_repeatedly(mock_threads
);
1711 MockReplayerListener mock_replayer_listener
;
1712 expect_notification(mock_threads
, mock_replayer_listener
);
1716 MockInstanceWatcher mock_instance_watcher
;
1717 MockImageMeta mock_image_meta
;
1718 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1719 mock_remote_image_ctx
,
1721 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1722 "local mirror uuid", &m_pool_meta_cache
,
1723 &mock_state_builder
, &mock_replayer_listener
};
1724 m_pool_meta_cache
.set_remote_pool_meta(
1725 m_remote_io_ctx
.get_id(),
1726 {"remote mirror uuid", "remote mirror peer uuid"});
1728 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1729 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1730 mock_local_image_ctx
,
1731 mock_remote_image_ctx
,
1732 mock_replayer_listener
,
1734 &update_watch_ctx
));
1737 mock_remote_image_ctx
.snap_info
= {
1738 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1739 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1740 CEPH_NOSNAP
, true, 0, {}},
1744 expect_load_image_meta(mock_image_meta
, false, 0);
1745 expect_is_refresh_required(mock_local_image_ctx
, false);
1746 expect_is_refresh_required(mock_remote_image_ctx
, false);
1747 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1748 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1750 MockGetImageStateRequest mock_get_image_state_request
;
1751 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1752 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1753 expect_create_non_primary_request(mock_create_non_primary_request
,
1754 false, "remote mirror uuid", 1,
1755 {{1, CEPH_NOSNAP
}}, 11, 0);
1756 MockImageStateUpdateRequest mock_image_state_update_request
;
1757 expect_update_mirror_image_state(mock_image_state_update_request
, -EIO
);
1760 update_watch_ctx
->handle_notify();
1762 // wait for sync to complete and expect replay complete
1763 ASSERT_EQ(0, wait_for_notification(1));
1764 ASSERT_FALSE(mock_replayer
.is_replaying());
1765 ASSERT_EQ(-EIO
, mock_replayer
.get_error_code());
1767 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1768 mock_local_image_ctx
,
1769 mock_remote_image_ctx
));
1772 TEST_F(TestMockImageReplayerSnapshotReplayer
, RequestSyncError
) {
1773 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1774 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1776 MockThreads
mock_threads(m_threads
);
1777 expect_work_queue_repeatedly(mock_threads
);
1779 MockReplayerListener mock_replayer_listener
;
1780 expect_notification(mock_threads
, mock_replayer_listener
);
1784 MockInstanceWatcher mock_instance_watcher
;
1785 MockImageMeta mock_image_meta
;
1786 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1787 mock_remote_image_ctx
,
1789 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1790 "local mirror uuid", &m_pool_meta_cache
,
1791 &mock_state_builder
, &mock_replayer_listener
};
1792 m_pool_meta_cache
.set_remote_pool_meta(
1793 m_remote_io_ctx
.get_id(),
1794 {"remote mirror uuid", "remote mirror peer uuid"});
1796 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1797 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1798 mock_local_image_ctx
,
1799 mock_remote_image_ctx
,
1800 mock_replayer_listener
,
1802 &update_watch_ctx
));
1805 mock_remote_image_ctx
.snap_info
= {
1806 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1807 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1808 CEPH_NOSNAP
, true, 0, {}},
1812 expect_load_image_meta(mock_image_meta
, false, 0);
1813 expect_is_refresh_required(mock_local_image_ctx
, false);
1814 expect_is_refresh_required(mock_remote_image_ctx
, false);
1815 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1816 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1818 MockGetImageStateRequest mock_get_image_state_request
;
1819 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1820 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1821 expect_create_non_primary_request(mock_create_non_primary_request
,
1822 false, "remote mirror uuid", 1,
1823 {{1, CEPH_NOSNAP
}}, 11, 0);
1824 MockImageStateUpdateRequest mock_image_state_update_request
;
1825 expect_update_mirror_image_state(mock_image_state_update_request
, 0);
1826 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
,
1830 update_watch_ctx
->handle_notify();
1832 // wait for sync to complete and expect replay complete
1833 ASSERT_EQ(0, wait_for_notification(1));
1834 ASSERT_FALSE(mock_replayer
.is_replaying());
1835 ASSERT_EQ(-ECANCELED
, mock_replayer
.get_error_code());
1837 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1838 mock_local_image_ctx
,
1839 mock_remote_image_ctx
));
1842 TEST_F(TestMockImageReplayerSnapshotReplayer
, CopyImageError
) {
1843 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1844 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1846 MockThreads
mock_threads(m_threads
);
1847 expect_work_queue_repeatedly(mock_threads
);
1849 MockReplayerListener mock_replayer_listener
;
1850 expect_notification(mock_threads
, mock_replayer_listener
);
1854 MockInstanceWatcher mock_instance_watcher
;
1855 MockImageMeta mock_image_meta
;
1856 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1857 mock_remote_image_ctx
,
1859 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1860 "local mirror uuid", &m_pool_meta_cache
,
1861 &mock_state_builder
, &mock_replayer_listener
};
1862 m_pool_meta_cache
.set_remote_pool_meta(
1863 m_remote_io_ctx
.get_id(),
1864 {"remote mirror uuid", "remote mirror peer uuid"});
1866 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1867 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1868 mock_local_image_ctx
,
1869 mock_remote_image_ctx
,
1870 mock_replayer_listener
,
1872 &update_watch_ctx
));
1875 mock_remote_image_ctx
.snap_info
= {
1876 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1877 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1878 CEPH_NOSNAP
,true, 0, {}},
1882 expect_load_image_meta(mock_image_meta
, false, 0);
1883 expect_is_refresh_required(mock_local_image_ctx
, false);
1884 expect_is_refresh_required(mock_remote_image_ctx
, false);
1885 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1886 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1888 MockGetImageStateRequest mock_get_image_state_request
;
1889 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1890 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1891 expect_create_non_primary_request(mock_create_non_primary_request
,
1892 false, "remote mirror uuid", 1,
1893 {{1, CEPH_NOSNAP
}}, 11, 0);
1894 MockImageStateUpdateRequest mock_image_state_update_request
;
1895 expect_update_mirror_image_state(mock_image_state_update_request
, 0);
1896 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1897 MockImageCopyRequest mock_image_copy_request
;
1898 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
1899 {{1, CEPH_NOSNAP
}}, -EINVAL
);
1900 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
1903 update_watch_ctx
->handle_notify();
1905 // wait for sync to complete and expect replay complete
1906 ASSERT_EQ(0, wait_for_notification(1));
1907 ASSERT_FALSE(mock_replayer
.is_replaying());
1908 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1910 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1911 mock_local_image_ctx
,
1912 mock_remote_image_ctx
));
1915 TEST_F(TestMockImageReplayerSnapshotReplayer
, UpdateNonPrimarySnapshotError
) {
1916 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1917 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1919 MockThreads
mock_threads(m_threads
);
1920 expect_work_queue_repeatedly(mock_threads
);
1922 MockReplayerListener mock_replayer_listener
;
1923 expect_notification(mock_threads
, mock_replayer_listener
);
1927 MockInstanceWatcher mock_instance_watcher
;
1928 MockImageMeta mock_image_meta
;
1929 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1930 mock_remote_image_ctx
,
1932 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1933 "local mirror uuid", &m_pool_meta_cache
,
1934 &mock_state_builder
, &mock_replayer_listener
};
1935 m_pool_meta_cache
.set_remote_pool_meta(
1936 m_remote_io_ctx
.get_id(),
1937 {"remote mirror uuid", "remote mirror peer uuid"});
1939 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1940 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1941 mock_local_image_ctx
,
1942 mock_remote_image_ctx
,
1943 mock_replayer_listener
,
1945 &update_watch_ctx
));
1948 mock_remote_image_ctx
.snap_info
= {
1949 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1950 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1951 CEPH_NOSNAP
, true, 0, {}},
1955 expect_load_image_meta(mock_image_meta
, false, 0);
1956 expect_is_refresh_required(mock_local_image_ctx
, false);
1957 expect_is_refresh_required(mock_remote_image_ctx
, false);
1958 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1959 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1961 MockGetImageStateRequest mock_get_image_state_request
;
1962 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1963 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1964 expect_create_non_primary_request(mock_create_non_primary_request
,
1965 false, "remote mirror uuid", 1,
1966 {{1, CEPH_NOSNAP
}}, 11, 0);
1967 MockImageStateUpdateRequest mock_image_state_update_request
;
1968 expect_update_mirror_image_state(mock_image_state_update_request
, 0);
1969 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1970 MockImageCopyRequest mock_image_copy_request
;
1971 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
1972 {{1, CEPH_NOSNAP
}}, 0);
1973 MockApplyImageStateRequest mock_apply_state_request
;
1974 expect_apply_image_state(mock_apply_state_request
, 0);
1975 expect_mirror_image_snapshot_set_copy_progress(
1976 mock_local_image_ctx
, 11, true, 0, -EINVAL
);
1977 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
1980 update_watch_ctx
->handle_notify();
1982 // wait for sync to complete and expect replay complete
1983 ASSERT_EQ(0, wait_for_notification(1));
1984 ASSERT_FALSE(mock_replayer
.is_replaying());
1985 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1987 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1988 mock_local_image_ctx
,
1989 mock_remote_image_ctx
));
1992 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnlinkPeerError
) {
1993 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1994 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1996 MockThreads
mock_threads(m_threads
);
1997 expect_work_queue_repeatedly(mock_threads
);
1999 MockReplayerListener mock_replayer_listener
;
2000 expect_notification(mock_threads
, mock_replayer_listener
);
2004 MockInstanceWatcher mock_instance_watcher
;
2005 MockImageMeta mock_image_meta
;
2006 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2007 mock_remote_image_ctx
,
2009 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2010 "local mirror uuid", &m_pool_meta_cache
,
2011 &mock_state_builder
, &mock_replayer_listener
};
2012 m_pool_meta_cache
.set_remote_pool_meta(
2013 m_remote_io_ctx
.get_id(),
2014 {"remote mirror uuid", "remote mirror peer uuid"});
2016 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2017 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
2018 mock_local_image_ctx
,
2019 mock_remote_image_ctx
,
2020 mock_replayer_listener
,
2022 &update_watch_ctx
));
2025 mock_remote_image_ctx
.snap_info
= {
2026 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2027 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
2028 CEPH_NOSNAP
, true, 0, {}},
2030 {2U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2031 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2032 "", CEPH_NOSNAP
, true, 0, {}},
2034 mock_local_image_ctx
.snap_info
= {
2035 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2036 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
2041 expect_load_image_meta(mock_image_meta
, false, 0);
2042 expect_is_refresh_required(mock_local_image_ctx
, false);
2043 expect_is_refresh_required(mock_remote_image_ctx
, false);
2044 MockSnapshotCopyRequest mock_snapshot_copy_request
;
2045 expect_snapshot_copy(mock_snapshot_copy_request
, 1, 2, 11, {{2, CEPH_NOSNAP
}},
2047 MockGetImageStateRequest mock_get_image_state_request
;
2048 expect_get_image_state(mock_get_image_state_request
, 2, 0);
2049 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
2050 expect_create_non_primary_request(mock_create_non_primary_request
,
2051 false, "remote mirror uuid", 2,
2052 {{2, CEPH_NOSNAP
}}, 12, 0);
2053 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
2054 MockImageCopyRequest mock_image_copy_request
;
2055 expect_image_copy(mock_image_copy_request
, 1, 2, 11, {},
2056 {{2, CEPH_NOSNAP
}}, 0);
2057 MockApplyImageStateRequest mock_apply_state_request
;
2058 expect_apply_image_state(mock_apply_state_request
, 0);
2059 expect_mirror_image_snapshot_set_copy_progress(
2060 mock_local_image_ctx
, 12, true, 0, 0);
2061 expect_notify_update(mock_local_image_ctx
);
2062 MockUnlinkPeerRequest mock_unlink_peer_request
;
2063 expect_unlink_peer(mock_unlink_peer_request
, 1, "remote mirror peer uuid",
2065 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
2068 update_watch_ctx
->handle_notify();
2070 // wait for sync to complete and expect replay complete
2071 ASSERT_EQ(0, wait_for_notification(1));
2072 ASSERT_FALSE(mock_replayer
.is_replaying());
2073 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
2075 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2076 mock_local_image_ctx
,
2077 mock_remote_image_ctx
));
2080 TEST_F(TestMockImageReplayerSnapshotReplayer
, SplitBrain
) {
2081 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
2082 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2084 MockThreads
mock_threads(m_threads
);
2085 expect_work_queue_repeatedly(mock_threads
);
2087 MockReplayerListener mock_replayer_listener
;
2088 expect_notification(mock_threads
, mock_replayer_listener
);
2092 MockInstanceWatcher mock_instance_watcher
;
2093 MockImageMeta mock_image_meta
;
2094 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2095 mock_remote_image_ctx
,
2097 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2098 "local mirror uuid", &m_pool_meta_cache
,
2099 &mock_state_builder
, &mock_replayer_listener
};
2100 m_pool_meta_cache
.set_remote_pool_meta(
2101 m_remote_io_ctx
.get_id(),
2102 {"remote mirror uuid", "remote mirror peer uuid"});
2104 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2105 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
2106 mock_local_image_ctx
,
2107 mock_remote_image_ctx
,
2108 mock_replayer_listener
,
2110 &update_watch_ctx
));
2112 // inject a primary demote to local image
2113 mock_remote_image_ctx
.snap_info
= {
2114 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2115 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2116 "", CEPH_NOSNAP
, true, 0, {}},
2118 mock_local_image_ctx
.snap_info
= {
2119 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2120 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", CEPH_NOSNAP
,
2124 // detect split-brain
2125 expect_load_image_meta(mock_image_meta
, false, 0);
2126 expect_is_refresh_required(mock_local_image_ctx
, false);
2127 expect_is_refresh_required(mock_remote_image_ctx
, false);
2130 update_watch_ctx
->handle_notify();
2132 // wait for sync to complete and expect replay complete
2133 ASSERT_EQ(0, wait_for_notification(1));
2134 ASSERT_FALSE(mock_replayer
.is_replaying());
2135 ASSERT_EQ(-EEXIST
, mock_replayer
.get_error_code());
2136 ASSERT_EQ(std::string
{"split-brain"}, mock_replayer
.get_error_description());
2138 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2139 mock_local_image_ctx
,
2140 mock_remote_image_ctx
));
2143 TEST_F(TestMockImageReplayerSnapshotReplayer
, RemoteSnapshotMissingSplitBrain
) {
2144 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
2145 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2147 MockThreads
mock_threads(m_threads
);
2148 expect_work_queue_repeatedly(mock_threads
);
2150 MockReplayerListener mock_replayer_listener
;
2151 expect_notification(mock_threads
, mock_replayer_listener
);
2155 MockInstanceWatcher mock_instance_watcher
;
2156 MockImageMeta mock_image_meta
;
2157 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2158 mock_remote_image_ctx
,
2160 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2161 "local mirror uuid", &m_pool_meta_cache
,
2162 &mock_state_builder
, &mock_replayer_listener
};
2163 m_pool_meta_cache
.set_remote_pool_meta(
2164 m_remote_io_ctx
.get_id(),
2165 {"remote mirror uuid", "remote mirror peer uuid"});
2167 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2168 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
2169 mock_local_image_ctx
,
2170 mock_remote_image_ctx
,
2171 mock_replayer_listener
,
2173 &update_watch_ctx
));
2175 // inject a missing remote start snap (deleted)
2176 mock_local_image_ctx
.snap_info
= {
2177 {11U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2178 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {},
2179 "remote mirror uuid", 1, true, 0,
2180 {{1, CEPH_NOSNAP
}}},
2182 mock_remote_image_ctx
.snap_info
= {
2183 {2U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2184 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2185 "", CEPH_NOSNAP
, true, 0, {}},
2187 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2188 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2189 "", CEPH_NOSNAP
, true, 0, {}},
2192 // split-brain due to missing snapshot 1
2193 expect_load_image_meta(mock_image_meta
, false, 0);
2194 expect_is_refresh_required(mock_local_image_ctx
, false);
2195 expect_is_refresh_required(mock_remote_image_ctx
, false);
2198 update_watch_ctx
->handle_notify();
2200 // wait for sync to complete and expect replay complete
2201 ASSERT_EQ(0, wait_for_notification(1));
2202 ASSERT_FALSE(mock_replayer
.is_replaying());
2203 ASSERT_EQ(-EEXIST
, mock_replayer
.get_error_code());
2204 ASSERT_EQ(std::string
{"split-brain"}, mock_replayer
.get_error_description());
2206 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2207 mock_local_image_ctx
,
2208 mock_remote_image_ctx
));
2211 TEST_F(TestMockImageReplayerSnapshotReplayer
, RemoteFailover
) {
2212 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
2213 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2215 MockThreads
mock_threads(m_threads
);
2216 expect_work_queue_repeatedly(mock_threads
);
2218 MockReplayerListener mock_replayer_listener
;
2219 expect_notification(mock_threads
, mock_replayer_listener
);
2223 MockInstanceWatcher mock_instance_watcher
;
2224 MockImageMeta mock_image_meta
;
2225 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2226 mock_remote_image_ctx
,
2228 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2229 "local mirror uuid", &m_pool_meta_cache
,
2230 &mock_state_builder
, &mock_replayer_listener
};
2231 m_pool_meta_cache
.set_remote_pool_meta(
2232 m_remote_io_ctx
.get_id(),
2233 {"remote mirror uuid", "remote mirror peer uuid"});
2235 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2236 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
2237 mock_local_image_ctx
,
2238 mock_remote_image_ctx
,
2239 mock_replayer_listener
,
2241 &update_watch_ctx
));
2243 // inject a primary demote to local image
2244 mock_remote_image_ctx
.snap_info
= {
2245 {1U, librbd::SnapInfo
{"snap1", cls::rbd::UserSnapshotNamespace
{},
2247 {2U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2248 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED
,
2249 {"remote mirror peer uuid"}, "local mirror uuid", 12U, true, 0, {}},
2251 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2252 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2253 "", CEPH_NOSNAP
, true, 0, {}},
2255 mock_local_image_ctx
.snap_ids
= {
2256 {{cls::rbd::UserSnapshotNamespace
{}, "snap1"}, 11},
2257 {{cls::rbd::MirrorSnapshotNamespace
{}, "snap2"}, 12}};
2258 mock_local_image_ctx
.snap_info
= {
2259 {11U, librbd::SnapInfo
{"snap1", cls::rbd::UserSnapshotNamespace
{},
2261 {12U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2262 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", CEPH_NOSNAP
,
2266 // attach to promoted remote image
2267 expect_load_image_meta(mock_image_meta
, false, 0);
2268 expect_is_refresh_required(mock_local_image_ctx
, false);
2269 expect_is_refresh_required(mock_remote_image_ctx
, false);
2270 MockSnapshotCopyRequest mock_snapshot_copy_request
;
2271 expect_snapshot_copy(mock_snapshot_copy_request
, 2, 3, 12,
2272 {{2, 12}, {3, CEPH_NOSNAP
}}, 0);
2273 MockGetImageStateRequest mock_get_image_state_request
;
2274 expect_get_image_state(mock_get_image_state_request
, 3, 0);
2275 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
2276 expect_create_non_primary_request(mock_create_non_primary_request
,
2277 false, "remote mirror uuid", 3,
2278 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP
}}, 13,
2280 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
2281 MockImageCopyRequest mock_image_copy_request
;
2282 expect_image_copy(mock_image_copy_request
, 2, 3, 12, {},
2283 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP
}}, 0);
2284 MockApplyImageStateRequest mock_apply_state_request
;
2285 expect_apply_image_state(mock_apply_state_request
, 0);
2286 expect_mirror_image_snapshot_set_copy_progress(
2287 mock_local_image_ctx
, 13, true, 0, 0);
2288 expect_notify_update(mock_local_image_ctx
);
2289 MockUnlinkPeerRequest mock_unlink_peer_request
;
2290 expect_unlink_peer(mock_unlink_peer_request
, 2, "remote mirror peer uuid", 0);
2291 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
2294 expect_load_image_meta(mock_image_meta
, false, 0);
2295 expect_is_refresh_required(mock_local_image_ctx
, true);
2297 mock_local_image_ctx
, {
2298 {11U, librbd::SnapInfo
{"snap1", cls::rbd::UserSnapshotNamespace
{},
2300 {12U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2301 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", CEPH_NOSNAP
,
2304 {13U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2305 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {},
2306 "remote mirror uuid", 3, true, 0,
2307 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP
}}},
2310 expect_is_refresh_required(mock_remote_image_ctx
, true);
2312 mock_remote_image_ctx
, {
2313 {1U, librbd::SnapInfo
{"snap1", cls::rbd::UserSnapshotNamespace
{},
2315 {2U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2316 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED
,
2317 {"remote mirror peer uuid"}, "local mirror uuid", 12U, true, 0, {}},
2319 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2320 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {}, "", CEPH_NOSNAP
, true, 0,
2326 update_watch_ctx
->handle_notify();
2328 // wait for sync to complete and expect replay complete
2329 ASSERT_EQ(0, wait_for_notification(2));
2330 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2331 mock_local_image_ctx
,
2332 mock_remote_image_ctx
));
2335 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnlinkRemoteSnapshot
) {
2336 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
2337 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2339 // it should attempt to unlink from remote snap1 since we don't need it
2341 mock_local_image_ctx
.snap_info
= {
2342 {14U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
2343 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
2346 mock_remote_image_ctx
.snap_info
= {
2347 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2348 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2349 "", CEPH_NOSNAP
, true, 0, {}},
2351 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
2352 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2353 "", CEPH_NOSNAP
, true, 0, {}},
2356 MockThreads
mock_threads(m_threads
);
2357 expect_work_queue_repeatedly(mock_threads
);
2359 MockReplayerListener mock_replayer_listener
;
2360 expect_notification(mock_threads
, mock_replayer_listener
);
2364 MockInstanceWatcher mock_instance_watcher
;
2365 MockImageMeta mock_image_meta
;
2366 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2367 mock_remote_image_ctx
,
2369 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2370 "local mirror uuid", &m_pool_meta_cache
,
2371 &mock_state_builder
, &mock_replayer_listener
};
2372 m_pool_meta_cache
.set_remote_pool_meta(
2373 m_remote_io_ctx
.get_id(),
2374 {"remote mirror uuid", "remote mirror peer uuid"});
2376 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2379 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
2381 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
2385 expect_load_image_meta(mock_image_meta
, false, 0);
2386 expect_is_refresh_required(mock_local_image_ctx
, false);
2387 expect_is_refresh_required(mock_remote_image_ctx
, false);
2388 MockUnlinkPeerRequest mock_unlink_peer_request
;
2389 expect_unlink_peer(mock_unlink_peer_request
, 1, "remote mirror peer uuid",
2393 expect_load_image_meta(mock_image_meta
, false, 0);
2394 expect_is_refresh_required(mock_local_image_ctx
, false);
2395 expect_is_refresh_required(mock_remote_image_ctx
, true);
2397 mock_remote_image_ctx
, {
2398 {2U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
2400 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2401 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {""},
2402 "", CEPH_NOSNAP
, true, 0, {}},
2404 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
2405 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2406 "", CEPH_NOSNAP
, true, 0, {}},
2411 C_SaferCond init_ctx
;
2412 mock_replayer
.init(&init_ctx
);
2413 ASSERT_EQ(0, init_ctx
.wait());
2415 // wait for sync to complete
2416 ASSERT_EQ(0, wait_for_notification(3));
2419 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2420 mock_local_image_ctx
,
2421 mock_remote_image_ctx
));
2424 TEST_F(TestMockImageReplayerSnapshotReplayer
, SkipImageSync
) {
2425 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
2426 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2428 mock_remote_image_ctx
.snap_info
= {
2429 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2430 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2431 "", 0U, true, 0, {}},
2434 MockThreads
mock_threads(m_threads
);
2435 expect_work_queue_repeatedly(mock_threads
);
2437 MockReplayerListener mock_replayer_listener
;
2438 expect_notification(mock_threads
, mock_replayer_listener
);
2442 MockInstanceWatcher mock_instance_watcher
;
2443 MockImageMeta mock_image_meta
;
2444 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2445 mock_remote_image_ctx
,
2447 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2448 "local mirror uuid", &m_pool_meta_cache
,
2449 &mock_state_builder
, &mock_replayer_listener
};
2450 m_pool_meta_cache
.set_remote_pool_meta(
2451 m_remote_io_ctx
.get_id(),
2452 {"remote mirror uuid", "remote mirror peer uuid"});
2454 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2457 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
2459 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
2463 expect_load_image_meta(mock_image_meta
, false, 0);
2464 expect_is_refresh_required(mock_local_image_ctx
, false);
2465 expect_is_refresh_required(mock_remote_image_ctx
, false);
2466 MockSnapshotCopyRequest mock_snapshot_copy_request
;
2467 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
2469 MockGetImageStateRequest mock_get_image_state_request
;
2470 expect_get_image_state(mock_get_image_state_request
, 1, 0);
2471 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
2472 expect_create_non_primary_request(mock_create_non_primary_request
,
2473 false, "remote mirror uuid", 1,
2474 {{1, CEPH_NOSNAP
}}, 11, 0);
2475 MockImageStateUpdateRequest mock_image_state_update_request
;
2476 expect_update_mirror_image_state(mock_image_state_update_request
, 0);
2477 MockApplyImageStateRequest mock_apply_state_request
;
2478 expect_apply_image_state(mock_apply_state_request
, 0);
2479 expect_mirror_image_snapshot_set_copy_progress(
2480 mock_local_image_ctx
, 11, true, 0, 0);
2481 expect_notify_update(mock_local_image_ctx
);
2484 expect_load_image_meta(mock_image_meta
, false, 0);
2485 expect_is_refresh_required(mock_local_image_ctx
, true);
2487 mock_local_image_ctx
, {
2488 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2489 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
2490 1, true, 0, {{1, CEPH_NOSNAP
}}},
2493 expect_is_refresh_required(mock_remote_image_ctx
, false);
2496 C_SaferCond init_ctx
;
2497 mock_replayer
.init(&init_ctx
);
2498 ASSERT_EQ(0, init_ctx
.wait());
2500 // wait for sync to complete
2501 ASSERT_EQ(0, wait_for_notification(3));
2504 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2505 mock_local_image_ctx
,
2506 mock_remote_image_ctx
));
2509 TEST_F(TestMockImageReplayerSnapshotReplayer
, ImageNameUpdated
) {
2510 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
2511 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2513 MockThreads
mock_threads(m_threads
);
2514 expect_work_queue_repeatedly(mock_threads
);
2516 MockReplayerListener mock_replayer_listener
;
2517 expect_notification(mock_threads
, mock_replayer_listener
);
2521 MockInstanceWatcher mock_instance_watcher
;
2522 MockImageMeta mock_image_meta
;
2523 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2524 mock_remote_image_ctx
,
2526 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2527 "local mirror uuid", &m_pool_meta_cache
,
2528 &mock_state_builder
, &mock_replayer_listener
};
2529 m_pool_meta_cache
.set_remote_pool_meta(
2530 m_remote_io_ctx
.get_id(),
2531 {"remote mirror uuid", "remote mirror peer uuid"});
2533 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2534 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
2535 mock_local_image_ctx
,
2536 mock_remote_image_ctx
,
2537 mock_replayer_listener
,
2539 &update_watch_ctx
));
2541 // change the name of the image
2542 mock_local_image_ctx
.name
= "NEW NAME";
2545 expect_load_image_meta(mock_image_meta
, true, 0);
2548 update_watch_ctx
->handle_notify();
2550 // wait for sync to complete and expect replay complete
2551 ASSERT_EQ(0, wait_for_notification(2));
2552 auto image_spec
= image_replayer::util::compute_image_spec(m_local_io_ctx
,
2554 ASSERT_EQ(image_spec
, mock_replayer
.get_image_spec());
2555 ASSERT_FALSE(mock_replayer
.is_replaying());
2558 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2559 mock_local_image_ctx
,
2560 mock_remote_image_ctx
));
2563 } // namespace snapshot
2564 } // namespace image_replayer
2565 } // namespace mirror