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/snapshot/CreateNonPrimaryRequest.h"
8 #include "librbd/mirror/snapshot/GetImageStateRequest.h"
9 #include "librbd/mirror/snapshot/ImageMeta.h"
10 #include "librbd/mirror/snapshot/UnlinkPeerRequest.h"
11 #include "tools/rbd_mirror/InstanceWatcher.h"
12 #include "tools/rbd_mirror/Threads.h"
13 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
14 #include "tools/rbd_mirror/image_replayer/ReplayerListener.h"
15 #include "tools/rbd_mirror/image_replayer/Utils.h"
16 #include "tools/rbd_mirror/image_replayer/snapshot/ApplyImageStateRequest.h"
17 #include "tools/rbd_mirror/image_replayer/snapshot/Replayer.h"
18 #include "tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h"
19 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
20 #include "test/librbd/mock/MockImageCtx.h"
21 #include "test/rbd_mirror/mock/MockContextWQ.h"
22 #include "test/rbd_mirror/mock/MockSafeTimer.h"
27 struct MockTestImageCtx
: public librbd::MockImageCtx
{
28 explicit MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
29 : librbd::MockImageCtx(image_ctx
) {
33 } // anonymous namespace
38 struct ImageCopyRequest
<MockTestImageCtx
> {
39 uint64_t src_snap_id_start
;
40 uint64_t src_snap_id_end
;
41 uint64_t dst_snap_id_start
;
42 librbd::deep_copy::ObjectNumber object_number
;
43 librbd::SnapSeqs snap_seqs
;
45 static ImageCopyRequest
* s_instance
;
46 static ImageCopyRequest
* create(MockTestImageCtx
*src_image_ctx
,
47 MockTestImageCtx
*dst_image_ctx
,
48 librados::snap_t src_snap_id_start
,
49 librados::snap_t src_snap_id_end
,
50 librados::snap_t dst_snap_id_start
,
52 const ObjectNumber
&object_number
,
53 const SnapSeqs
&snap_seqs
,
54 ProgressContext
*prog_ctx
,
56 ceph_assert(s_instance
!= nullptr);
57 s_instance
->src_snap_id_start
= src_snap_id_start
;
58 s_instance
->src_snap_id_end
= src_snap_id_end
;
59 s_instance
->dst_snap_id_start
= dst_snap_id_start
;
60 s_instance
->object_number
= object_number
;
61 s_instance
->snap_seqs
= snap_seqs
;
62 s_instance
->on_finish
= on_finish
;
66 Context
* on_finish
= nullptr;
72 MOCK_METHOD0(send
, void());
76 struct SnapshotCopyRequest
<MockTestImageCtx
> {
77 librados::snap_t src_snap_id_start
;
78 librados::snap_t src_snap_id_end
;
79 librados::snap_t dst_snap_id_start
;
80 SnapSeqs
* snap_seqs
= nullptr;
82 static SnapshotCopyRequest
* s_instance
;
83 static SnapshotCopyRequest
* create(MockTestImageCtx
*src_image_ctx
,
84 MockTestImageCtx
*dst_image_ctx
,
85 librados::snap_t src_snap_id_start
,
86 librados::snap_t src_snap_id_end
,
87 librados::snap_t dst_snap_id_start
,
89 ::MockContextWQ
*work_queue
,
92 ceph_assert(s_instance
!= nullptr);
93 s_instance
->src_snap_id_start
= src_snap_id_start
;
94 s_instance
->src_snap_id_end
= src_snap_id_end
;
95 s_instance
->dst_snap_id_start
= dst_snap_id_start
;
96 s_instance
->snap_seqs
= snap_seqs
;
97 s_instance
->on_finish
= on_finish
;
101 Context
* on_finish
= nullptr;
103 SnapshotCopyRequest() {
107 MOCK_METHOD0(send
, void());
110 ImageCopyRequest
<MockTestImageCtx
>* ImageCopyRequest
<MockTestImageCtx
>::s_instance
= nullptr;
111 SnapshotCopyRequest
<MockTestImageCtx
>* SnapshotCopyRequest
<MockTestImageCtx
>::s_instance
= nullptr;
113 } // namespace deep_copy
119 struct CreateNonPrimaryRequest
<MockTestImageCtx
> {
120 bool demoted
= false;
121 std::string primary_mirror_uuid
;
122 uint64_t primary_snap_id
;
124 uint64_t* snap_id
= nullptr;
126 static CreateNonPrimaryRequest
* s_instance
;
127 static CreateNonPrimaryRequest
* create(MockTestImageCtx
*image_ctx
,
129 const std::string
&primary_mirror_uuid
,
130 uint64_t primary_snap_id
,
131 const SnapSeqs
& snap_seqs
,
132 const ImageState
&image_state
,
134 Context
*on_finish
) {
135 ceph_assert(s_instance
!= nullptr);
136 s_instance
->demoted
= demoted
;
137 s_instance
->primary_mirror_uuid
= primary_mirror_uuid
;
138 s_instance
->primary_snap_id
= primary_snap_id
;
139 s_instance
->snap_seqs
= snap_seqs
;
140 s_instance
->snap_id
= snap_id
;
141 s_instance
->on_finish
= on_finish
;
145 Context
* on_finish
= nullptr;
147 CreateNonPrimaryRequest() {
151 MOCK_METHOD0(send
, void());
155 struct GetImageStateRequest
<MockTestImageCtx
> {
156 uint64_t snap_id
= CEPH_NOSNAP
;
158 static GetImageStateRequest
* s_instance
;
159 static GetImageStateRequest
* create(MockTestImageCtx
*image_ctx
,
161 ImageState
*image_state
,
162 Context
*on_finish
) {
163 ceph_assert(s_instance
!= nullptr);
164 s_instance
->snap_id
= snap_id
;
165 s_instance
->on_finish
= on_finish
;
169 Context
* on_finish
= nullptr;
171 GetImageStateRequest() {
175 MOCK_METHOD0(send
, void());
179 struct ImageMeta
<MockTestImageCtx
> {
180 MOCK_METHOD1(load
, void(Context
*));
182 bool resync_requested
= false;
186 struct UnlinkPeerRequest
<MockTestImageCtx
> {
188 std::string mirror_peer_uuid
;
190 static UnlinkPeerRequest
* s_instance
;
191 static UnlinkPeerRequest
*create (MockTestImageCtx
*image_ctx
,
193 const std::string
&mirror_peer_uuid
,
194 Context
*on_finish
) {
195 ceph_assert(s_instance
!= nullptr);
196 s_instance
->snap_id
= snap_id
;
197 s_instance
->mirror_peer_uuid
= mirror_peer_uuid
;
198 s_instance
->on_finish
= on_finish
;
202 Context
* on_finish
= nullptr;
204 UnlinkPeerRequest() {
208 MOCK_METHOD0(send
, void());
211 CreateNonPrimaryRequest
<MockTestImageCtx
>* CreateNonPrimaryRequest
<MockTestImageCtx
>::s_instance
= nullptr;
212 GetImageStateRequest
<MockTestImageCtx
>* GetImageStateRequest
<MockTestImageCtx
>::s_instance
= nullptr;
213 UnlinkPeerRequest
<MockTestImageCtx
>* UnlinkPeerRequest
<MockTestImageCtx
>::s_instance
= nullptr;
215 } // namespace snapshot
216 } // namespace mirror
217 } // namespace librbd
223 struct InstanceWatcher
<librbd::MockTestImageCtx
> {
224 MOCK_METHOD1(cancel_sync_request
, void(const std::string
&));
225 MOCK_METHOD2(notify_sync_request
, void(const std::string
&,
227 MOCK_METHOD1(notify_sync_complete
, void(const std::string
&));
231 struct Threads
<librbd::MockTestImageCtx
> {
232 MockSafeTimer
*timer
;
233 ceph::mutex
&timer_lock
;
235 MockContextWQ
*work_queue
;
237 Threads(Threads
<librbd::ImageCtx
>* threads
)
238 : timer(new MockSafeTimer()),
239 timer_lock(threads
->timer_lock
),
240 work_queue(new MockContextWQ()) {
250 struct MockReplayerListener
: public image_replayer::ReplayerListener
{
251 MOCK_METHOD0(handle_notification
, void());
254 } // anonymous namespace
256 namespace image_replayer
{
259 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
260 static CloseImageRequest
* s_instance
;
261 librbd::MockTestImageCtx
**image_ctx
= nullptr;
262 Context
*on_finish
= nullptr;
264 static CloseImageRequest
* create(librbd::MockTestImageCtx
**image_ctx
,
265 Context
*on_finish
) {
266 ceph_assert(s_instance
!= nullptr);
267 s_instance
->image_ctx
= image_ctx
;
268 s_instance
->on_finish
= on_finish
;
272 CloseImageRequest() {
273 ceph_assert(s_instance
== nullptr);
277 ~CloseImageRequest() {
278 ceph_assert(s_instance
== this);
279 s_instance
= nullptr;
282 MOCK_METHOD0(send
, void());
285 CloseImageRequest
<librbd::MockTestImageCtx
>* CloseImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
290 struct ApplyImageStateRequest
<librbd::MockTestImageCtx
> {
291 Context
* on_finish
= nullptr;
293 static ApplyImageStateRequest
* s_instance
;
294 static ApplyImageStateRequest
* create(
295 const std::string
& local_mirror_uuid
,
296 const std::string
& remote_mirror_uuid
,
297 librbd::MockTestImageCtx
* local_image_ctx
,
298 librbd::MockTestImageCtx
* remote_image_ctx
,
299 const librbd::mirror::snapshot::ImageState
& image_state
,
300 Context
* on_finish
) {
301 ceph_assert(s_instance
!= nullptr);
302 s_instance
->on_finish
= on_finish
;
306 ApplyImageStateRequest() {
310 MOCK_METHOD0(send
, void());
314 struct StateBuilder
<librbd::MockTestImageCtx
> {
315 StateBuilder(librbd::MockTestImageCtx
& local_image_ctx
,
316 librbd::MockTestImageCtx
& remote_image_ctx
,
317 librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
>&
319 : local_image_ctx(&local_image_ctx
),
320 remote_image_ctx(&remote_image_ctx
),
321 local_image_meta(&local_image_meta
) {
324 librbd::MockTestImageCtx
* local_image_ctx
;
325 librbd::MockTestImageCtx
* remote_image_ctx
;
327 std::string remote_mirror_uuid
= "remote mirror uuid";
329 librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
>*
330 local_image_meta
= nullptr;
333 ApplyImageStateRequest
<librbd::MockTestImageCtx
>* ApplyImageStateRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
335 } // namespace snapshot
336 } // namespace image_replayer
337 } // namespace mirror
340 #include "tools/rbd_mirror/image_replayer/snapshot/Replayer.cc"
344 namespace image_replayer
{
348 using ::testing::DoAll
;
349 using ::testing::InSequence
;
350 using ::testing::Invoke
;
351 using ::testing::Return
;
352 using ::testing::ReturnArg
;
353 using ::testing::StrEq
;
354 using ::testing::WithArg
;
356 class TestMockImageReplayerSnapshotReplayer
: public TestMockFixture
{
358 typedef Replayer
<librbd::MockTestImageCtx
> MockReplayer
;
359 typedef ApplyImageStateRequest
<librbd::MockTestImageCtx
> MockApplyImageStateRequest
;
360 typedef StateBuilder
<librbd::MockTestImageCtx
> MockStateBuilder
;
361 typedef InstanceWatcher
<librbd::MockTestImageCtx
> MockInstanceWatcher
;
362 typedef Threads
<librbd::MockTestImageCtx
> MockThreads
;
363 typedef CloseImageRequest
<librbd::MockTestImageCtx
> MockCloseImageRequest
;
364 typedef librbd::deep_copy::ImageCopyRequest
<librbd::MockTestImageCtx
> MockImageCopyRequest
;
365 typedef librbd::deep_copy::SnapshotCopyRequest
<librbd::MockTestImageCtx
> MockSnapshotCopyRequest
;
366 typedef librbd::mirror::snapshot::CreateNonPrimaryRequest
<librbd::MockTestImageCtx
> MockCreateNonPrimaryRequest
;
367 typedef librbd::mirror::snapshot::GetImageStateRequest
<librbd::MockTestImageCtx
> MockGetImageStateRequest
;
368 typedef librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
> MockImageMeta
;
369 typedef librbd::mirror::snapshot::UnlinkPeerRequest
<librbd::MockTestImageCtx
> MockUnlinkPeerRequest
;
371 void SetUp() override
{
372 TestMockFixture::SetUp();
375 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
376 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
378 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
,
380 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
,
381 &m_remote_image_ctx
));
384 void expect_work_queue_repeatedly(MockThreads
&mock_threads
) {
385 EXPECT_CALL(*mock_threads
.work_queue
, queue(_
, _
))
386 .WillRepeatedly(Invoke([this](Context
*ctx
, int r
) {
387 m_threads
->work_queue
->queue(ctx
, r
);
391 void expect_add_event_after_repeatedly(MockThreads
&mock_threads
) {
392 EXPECT_CALL(*mock_threads
.timer
, add_event_after(_
, _
))
394 DoAll(Invoke([this](double seconds
, Context
*ctx
) {
395 m_threads
->timer
->add_event_after(seconds
, ctx
);
398 EXPECT_CALL(*mock_threads
.timer
, cancel_event(_
))
400 Invoke([this](Context
*ctx
) {
401 return m_threads
->timer
->cancel_event(ctx
);
405 void expect_register_update_watcher(librbd::MockTestImageCtx
& mock_image_ctx
,
406 librbd::UpdateWatchCtx
** update_watch_ctx
,
407 uint64_t watch_handle
, int r
) {
408 EXPECT_CALL(*mock_image_ctx
.state
, register_update_watcher(_
, _
))
409 .WillOnce(Invoke([update_watch_ctx
, watch_handle
, r
]
410 (librbd::UpdateWatchCtx
* ctx
, uint64_t* handle
) {
412 *update_watch_ctx
= ctx
;
413 *handle
= watch_handle
;
419 void expect_unregister_update_watcher(librbd::MockTestImageCtx
& mock_image_ctx
,
420 uint64_t watch_handle
, int r
) {
421 EXPECT_CALL(*mock_image_ctx
.state
, unregister_update_watcher(watch_handle
, _
))
422 .WillOnce(WithArg
<1>(Invoke([this, r
](Context
* ctx
) {
423 m_threads
->work_queue
->queue(ctx
, r
);
427 void expect_load_image_meta(MockImageMeta
& mock_image_meta
,
428 bool resync_requested
, int r
) {
429 EXPECT_CALL(mock_image_meta
, load(_
))
430 .WillOnce(Invoke([this, &mock_image_meta
, resync_requested
, r
](Context
* ctx
) {
431 mock_image_meta
.resync_requested
= resync_requested
;
432 m_threads
->work_queue
->queue(ctx
, r
);
436 void expect_is_refresh_required(librbd::MockTestImageCtx
& mock_image_ctx
,
438 EXPECT_CALL(*mock_image_ctx
.state
, is_refresh_required())
439 .WillOnce(Return(is_required
));
442 void expect_refresh(librbd::MockTestImageCtx
& mock_image_ctx
,
443 const std::map
<uint64_t, librbd::SnapInfo
>& snaps
,
445 EXPECT_CALL(*mock_image_ctx
.state
, refresh(_
))
446 .WillOnce(Invoke([this, &mock_image_ctx
, snaps
, r
](Context
* ctx
) {
447 mock_image_ctx
.snap_info
= snaps
;
448 m_threads
->work_queue
->queue(ctx
, r
);
452 void expect_notify_update(librbd::MockTestImageCtx
& mock_image_ctx
) {
453 EXPECT_CALL(mock_image_ctx
, notify_update(_
))
454 .WillOnce(Invoke([this](Context
* ctx
) {
455 m_threads
->work_queue
->queue(ctx
, 0);
459 void expect_snapshot_copy(MockSnapshotCopyRequest
& mock_snapshot_copy_request
,
460 uint64_t src_snap_id_start
,
461 uint64_t src_snap_id_end
,
462 uint64_t dst_snap_id_start
,
463 const librbd::SnapSeqs
& snap_seqs
, int r
) {
464 EXPECT_CALL(mock_snapshot_copy_request
, send())
465 .WillOnce(Invoke([this, &req
=mock_snapshot_copy_request
,
466 src_snap_id_start
, src_snap_id_end
, dst_snap_id_start
,
468 ASSERT_EQ(src_snap_id_start
, req
.src_snap_id_start
);
469 ASSERT_EQ(src_snap_id_end
, req
.src_snap_id_end
);
470 ASSERT_EQ(dst_snap_id_start
, req
.dst_snap_id_start
);
471 *req
.snap_seqs
= snap_seqs
;
472 m_threads
->work_queue
->queue(req
.on_finish
, r
);
476 void expect_get_image_state(MockGetImageStateRequest
& mock_get_image_state_request
,
477 uint64_t snap_id
, int r
) {
478 EXPECT_CALL(mock_get_image_state_request
, send())
479 .WillOnce(Invoke([this, &req
=mock_get_image_state_request
, snap_id
, r
]() {
480 ASSERT_EQ(snap_id
, req
.snap_id
);
481 m_threads
->work_queue
->queue(req
.on_finish
, r
);
485 void expect_create_non_primary_request(MockCreateNonPrimaryRequest
& mock_create_non_primary_request
,
487 const std::string
& primary_mirror_uuid
,
488 uint64_t primary_snap_id
,
489 const librbd::SnapSeqs
& snap_seqs
,
490 uint64_t snap_id
, int r
) {
491 EXPECT_CALL(mock_create_non_primary_request
, send())
492 .WillOnce(Invoke([this, &req
=mock_create_non_primary_request
, demoted
,
493 primary_mirror_uuid
, primary_snap_id
, snap_seqs
,
495 ASSERT_EQ(demoted
, req
.demoted
);
496 ASSERT_EQ(primary_mirror_uuid
, req
.primary_mirror_uuid
);
497 ASSERT_EQ(primary_snap_id
, req
.primary_snap_id
);
498 ASSERT_EQ(snap_seqs
, req
.snap_seqs
);
499 *req
.snap_id
= snap_id
;
500 m_threads
->work_queue
->queue(req
.on_finish
, r
);
504 void expect_notify_sync_request(MockInstanceWatcher
& mock_instance_watcher
,
505 const std::string
& image_id
, int r
) {
506 EXPECT_CALL(mock_instance_watcher
, notify_sync_request(image_id
, _
))
507 .WillOnce(WithArg
<1>(Invoke([this, r
](Context
* ctx
) {
508 m_threads
->work_queue
->queue(ctx
, r
);
512 void expect_notify_sync_complete(MockInstanceWatcher
& mock_instance_watcher
,
513 const std::string
& image_id
) {
514 EXPECT_CALL(mock_instance_watcher
, notify_sync_complete(image_id
));
517 void expect_image_copy(MockImageCopyRequest
& mock_image_copy_request
,
518 uint64_t src_snap_id_start
, uint64_t src_snap_id_end
,
519 uint64_t dst_snap_id_start
,
520 const librbd::deep_copy::ObjectNumber
& object_number
,
521 const librbd::SnapSeqs
& snap_seqs
, int r
) {
522 EXPECT_CALL(mock_image_copy_request
, send())
523 .WillOnce(Invoke([this, &req
=mock_image_copy_request
, src_snap_id_start
,
524 src_snap_id_end
, dst_snap_id_start
, object_number
,
526 ASSERT_EQ(src_snap_id_start
, req
.src_snap_id_start
);
527 ASSERT_EQ(src_snap_id_end
, req
.src_snap_id_end
);
528 ASSERT_EQ(dst_snap_id_start
, req
.dst_snap_id_start
);
529 ASSERT_EQ(object_number
, req
.object_number
);
530 ASSERT_EQ(snap_seqs
, req
.snap_seqs
);
531 m_threads
->work_queue
->queue(req
.on_finish
, r
);
535 void expect_unlink_peer(MockUnlinkPeerRequest
& mock_unlink_peer_request
,
536 uint64_t snap_id
, const std::string
& mirror_peer_uuid
,
538 EXPECT_CALL(mock_unlink_peer_request
, send())
539 .WillOnce(Invoke([this, &req
=mock_unlink_peer_request
, snap_id
,
540 mirror_peer_uuid
, r
]() {
541 ASSERT_EQ(snap_id
, req
.snap_id
);
542 ASSERT_EQ(mirror_peer_uuid
, req
.mirror_peer_uuid
);
543 m_threads
->work_queue
->queue(req
.on_finish
, r
);
547 void expect_apply_image_state(
548 MockApplyImageStateRequest
& mock_request
, int r
) {
549 EXPECT_CALL(mock_request
, send())
550 .WillOnce(Invoke([this, &req
=mock_request
, r
]() {
551 m_threads
->work_queue
->queue(req
.on_finish
, r
);
555 void expect_mirror_image_snapshot_set_copy_progress(
556 librbd::MockTestImageCtx
& mock_test_image_ctx
, uint64_t snap_id
,
557 bool completed
, uint64_t last_copied_object
, int r
) {
560 encode(completed
, bl
);
561 encode(last_copied_object
, bl
);
563 EXPECT_CALL(get_mock_io_ctx(mock_test_image_ctx
.md_ctx
),
564 exec(mock_test_image_ctx
.header_oid
, _
, StrEq("rbd"),
565 StrEq("mirror_image_snapshot_set_copy_progress"),
566 ContentsEqual(bl
), _
, _
))
567 .WillOnce(Return(r
));
570 void expect_send(MockCloseImageRequest
&mock_close_image_request
, int r
) {
571 EXPECT_CALL(mock_close_image_request
, send())
572 .WillOnce(Invoke([this, &mock_close_image_request
, r
]() {
573 *mock_close_image_request
.image_ctx
= nullptr;
574 m_threads
->work_queue
->queue(mock_close_image_request
.on_finish
, r
);
578 void expect_notification(MockThreads
& mock_threads
,
579 MockReplayerListener
& mock_replayer_listener
) {
580 EXPECT_CALL(mock_replayer_listener
, handle_notification())
581 .WillRepeatedly(Invoke([this]() {
582 std::unique_lock locker
{m_lock
};
588 int wait_for_notification(uint32_t count
) {
589 std::unique_lock locker
{m_lock
};
590 for (uint32_t idx
= 0; idx
< count
; ++idx
) {
591 while (m_notifications
== 0) {
592 if (m_cond
.wait_for(locker
, 10s
) == std::cv_status::timeout
) {
601 int init_entry_replayer(MockReplayer
& mock_replayer
,
602 MockThreads
& mock_threads
,
603 librbd::MockTestImageCtx
& mock_local_image_ctx
,
604 librbd::MockTestImageCtx
& mock_remote_image_ctx
,
605 MockReplayerListener
& mock_replayer_listener
,
606 MockImageMeta
& mock_image_meta
,
607 librbd::UpdateWatchCtx
** update_watch_ctx
) {
608 expect_register_update_watcher(mock_local_image_ctx
, update_watch_ctx
, 123,
610 expect_register_update_watcher(mock_remote_image_ctx
, update_watch_ctx
, 234,
612 expect_load_image_meta(mock_image_meta
, false, 0);
613 expect_is_refresh_required(mock_local_image_ctx
, false);
614 expect_is_refresh_required(mock_remote_image_ctx
, false);
616 C_SaferCond init_ctx
;
617 mock_replayer
.init(&init_ctx
);
618 int r
= init_ctx
.wait();
623 return wait_for_notification(2);
626 int shut_down_entry_replayer(MockReplayer
& mock_replayer
,
627 MockThreads
& mock_threads
,
628 librbd::MockTestImageCtx
& mock_local_image_ctx
,
629 librbd::MockTestImageCtx
& mock_remote_image_ctx
) {
630 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, 0);
631 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
633 C_SaferCond shutdown_ctx
;
634 mock_replayer
.shut_down(&shutdown_ctx
);
635 return shutdown_ctx
.wait();
638 librbd::ImageCtx
* m_local_image_ctx
= nullptr;
639 librbd::ImageCtx
* m_remote_image_ctx
= nullptr;
641 PoolMetaCache m_pool_meta_cache
{g_ceph_context
};
643 ceph::mutex m_lock
= ceph::make_mutex(
644 "TestMockImageReplayerSnapshotReplayer");
645 ceph::condition_variable m_cond
;
646 uint32_t m_notifications
= 0;
649 TEST_F(TestMockImageReplayerSnapshotReplayer
, InitShutDown
) {
650 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
651 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
653 MockThreads
mock_threads(m_threads
);
654 expect_work_queue_repeatedly(mock_threads
);
656 MockReplayerListener mock_replayer_listener
;
657 expect_notification(mock_threads
, mock_replayer_listener
);
661 MockInstanceWatcher mock_instance_watcher
;
662 MockImageMeta mock_image_meta
;
663 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
664 mock_remote_image_ctx
,
666 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
667 "local mirror uuid", &m_pool_meta_cache
,
668 &mock_state_builder
, &mock_replayer_listener
};
669 m_pool_meta_cache
.set_remote_pool_meta(
670 m_remote_io_ctx
.get_id(),
671 {"remote mirror uuid", "remote mirror peer uuid"});
673 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
674 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
675 mock_local_image_ctx
,
676 mock_remote_image_ctx
,
677 mock_replayer_listener
,
680 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
681 mock_local_image_ctx
,
682 mock_remote_image_ctx
));
685 TEST_F(TestMockImageReplayerSnapshotReplayer
, SyncSnapshot
) {
686 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
687 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
689 // it should sync two snapshots and skip two (user and mirror w/o matching
691 mock_remote_image_ctx
.snap_info
= {
692 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
693 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
694 "", 0U, true, 0, {}},
696 {2U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
698 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
699 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {""},
700 "", 0U, true, 0, {}},
702 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
703 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
704 "", 0U, true, 0, {}},
707 MockThreads
mock_threads(m_threads
);
708 expect_work_queue_repeatedly(mock_threads
);
710 MockReplayerListener mock_replayer_listener
;
711 expect_notification(mock_threads
, mock_replayer_listener
);
715 MockInstanceWatcher mock_instance_watcher
;
716 MockImageMeta mock_image_meta
;
717 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
718 mock_remote_image_ctx
,
720 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
721 "local mirror uuid", &m_pool_meta_cache
,
722 &mock_state_builder
, &mock_replayer_listener
};
723 m_pool_meta_cache
.set_remote_pool_meta(
724 m_remote_io_ctx
.get_id(),
725 {"remote mirror uuid", "remote mirror peer uuid"});
727 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
730 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
732 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
736 expect_load_image_meta(mock_image_meta
, false, 0);
737 expect_is_refresh_required(mock_local_image_ctx
, false);
738 expect_is_refresh_required(mock_remote_image_ctx
, false);
739 MockSnapshotCopyRequest mock_snapshot_copy_request
;
740 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
742 MockGetImageStateRequest mock_get_image_state_request
;
743 expect_get_image_state(mock_get_image_state_request
, 1, 0);
744 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
745 expect_create_non_primary_request(mock_create_non_primary_request
,
746 false, "remote mirror uuid", 1,
747 {{1, CEPH_NOSNAP
}}, 11, 0);
748 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
749 MockImageCopyRequest mock_image_copy_request
;
750 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
751 {{1, CEPH_NOSNAP
}}, 0);
752 MockApplyImageStateRequest mock_apply_state_request
;
753 expect_apply_image_state(mock_apply_state_request
, 0);
754 expect_mirror_image_snapshot_set_copy_progress(
755 mock_local_image_ctx
, 11, true, 0, 0);
756 expect_notify_update(mock_local_image_ctx
);
757 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
760 expect_load_image_meta(mock_image_meta
, false, 0);
761 expect_is_refresh_required(mock_local_image_ctx
, true);
763 mock_local_image_ctx
, {
764 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
765 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
769 expect_is_refresh_required(mock_remote_image_ctx
, false);
770 expect_snapshot_copy(mock_snapshot_copy_request
, 1, 4, 11,
771 {{1, 11}, {4, CEPH_NOSNAP
}}, 0);
772 expect_get_image_state(mock_get_image_state_request
, 4, 0);
773 expect_create_non_primary_request(mock_create_non_primary_request
,
774 false, "remote mirror uuid", 4,
775 {{1, 11}, {4, CEPH_NOSNAP
}}, 14, 0);
776 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
777 expect_image_copy(mock_image_copy_request
, 1, 4, 11, {},
778 {{1, 11}, {4, CEPH_NOSNAP
}}, 0);
779 expect_apply_image_state(mock_apply_state_request
, 0);
780 expect_mirror_image_snapshot_set_copy_progress(
781 mock_local_image_ctx
, 14, true, 0, 0);
782 expect_notify_update(mock_local_image_ctx
);
783 MockUnlinkPeerRequest mock_unlink_peer_request
;
784 expect_unlink_peer(mock_unlink_peer_request
, 1, "remote mirror peer uuid",
786 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
789 expect_load_image_meta(mock_image_meta
, false, 0);
790 expect_is_refresh_required(mock_local_image_ctx
, true);
792 mock_local_image_ctx
, {
793 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
794 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
797 {14U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
798 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
802 expect_is_refresh_required(mock_remote_image_ctx
, false);
805 C_SaferCond init_ctx
;
806 mock_replayer
.init(&init_ctx
);
807 ASSERT_EQ(0, init_ctx
.wait());
809 // wait for sync to complete
810 ASSERT_EQ(0, wait_for_notification(4));
813 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
814 mock_local_image_ctx
,
815 mock_remote_image_ctx
));
818 TEST_F(TestMockImageReplayerSnapshotReplayer
, InterruptedSync
) {
819 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
820 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
822 MockThreads
mock_threads(m_threads
);
823 expect_work_queue_repeatedly(mock_threads
);
825 MockReplayerListener mock_replayer_listener
;
826 expect_notification(mock_threads
, mock_replayer_listener
);
830 MockInstanceWatcher mock_instance_watcher
;
831 MockImageMeta mock_image_meta
;
832 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
833 mock_remote_image_ctx
,
835 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
836 "local mirror uuid", &m_pool_meta_cache
,
837 &mock_state_builder
, &mock_replayer_listener
};
838 m_pool_meta_cache
.set_remote_pool_meta(
839 m_remote_io_ctx
.get_id(),
840 {"remote mirror uuid", "remote mirror peer uuid"});
842 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
843 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
844 mock_local_image_ctx
,
845 mock_remote_image_ctx
,
846 mock_replayer_listener
,
850 // inject a incomplete sync snapshot
851 mock_remote_image_ctx
.snap_info
= {
852 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
853 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
854 "", 0U, true, 0, {}},
856 mock_local_image_ctx
.snap_info
= {
857 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
858 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
859 1, false, 123, {{1, CEPH_NOSNAP
}}},
863 expect_load_image_meta(mock_image_meta
, false, 0);
864 expect_is_refresh_required(mock_local_image_ctx
, false);
865 expect_is_refresh_required(mock_remote_image_ctx
, false);
866 MockGetImageStateRequest mock_get_image_state_request
;
867 expect_get_image_state(mock_get_image_state_request
, 11, 0);
868 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
869 MockImageCopyRequest mock_image_copy_request
;
870 expect_image_copy(mock_image_copy_request
, 0, 1, 0,
871 librbd::deep_copy::ObjectNumber
{123U},
872 {{1, CEPH_NOSNAP
}}, 0);
873 MockApplyImageStateRequest mock_apply_state_request
;
874 expect_apply_image_state(mock_apply_state_request
, 0);
875 expect_mirror_image_snapshot_set_copy_progress(
876 mock_local_image_ctx
, 11, true, 123, 0);
877 expect_notify_update(mock_local_image_ctx
);
880 expect_load_image_meta(mock_image_meta
, false, 0);
881 expect_is_refresh_required(mock_local_image_ctx
, true);
883 mock_local_image_ctx
, {
884 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
885 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
889 expect_is_refresh_required(mock_remote_image_ctx
, false);
892 update_watch_ctx
->handle_notify();
894 // wait for sync to complete
895 ASSERT_EQ(0, wait_for_notification(2));
897 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
898 mock_local_image_ctx
,
899 mock_remote_image_ctx
));
902 TEST_F(TestMockImageReplayerSnapshotReplayer
, RemoteImageDemoted
) {
903 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
904 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
906 MockThreads
mock_threads(m_threads
);
907 expect_work_queue_repeatedly(mock_threads
);
909 MockReplayerListener mock_replayer_listener
;
910 expect_notification(mock_threads
, mock_replayer_listener
);
914 MockInstanceWatcher mock_instance_watcher
;
915 MockImageMeta mock_image_meta
;
916 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
917 mock_remote_image_ctx
,
919 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
920 "local mirror uuid", &m_pool_meta_cache
,
921 &mock_state_builder
, &mock_replayer_listener
};
922 m_pool_meta_cache
.set_remote_pool_meta(
923 m_remote_io_ctx
.get_id(),
924 {"remote mirror uuid", "remote mirror peer uuid"});
926 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
927 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
928 mock_local_image_ctx
,
929 mock_remote_image_ctx
,
930 mock_replayer_listener
,
934 // inject a demotion snapshot
935 mock_remote_image_ctx
.snap_info
= {
936 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
937 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
,
938 {"remote mirror peer uuid"}, "", 0U, true, 0, {}},
942 expect_load_image_meta(mock_image_meta
, false, 0);
943 expect_is_refresh_required(mock_local_image_ctx
, false);
944 expect_is_refresh_required(mock_remote_image_ctx
, false);
945 MockSnapshotCopyRequest mock_snapshot_copy_request
;
946 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
948 MockGetImageStateRequest mock_get_image_state_request
;
949 expect_get_image_state(mock_get_image_state_request
, 1, 0);
950 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
951 expect_create_non_primary_request(mock_create_non_primary_request
,
952 true, "remote mirror uuid", 1,
953 {{1, CEPH_NOSNAP
}}, 11, 0);
954 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
955 MockImageCopyRequest mock_image_copy_request
;
956 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
957 {{1, CEPH_NOSNAP
}}, 0);
958 MockApplyImageStateRequest mock_apply_state_request
;
959 expect_apply_image_state(mock_apply_state_request
, 0);
960 expect_mirror_image_snapshot_set_copy_progress(
961 mock_local_image_ctx
, 11, true, 0, 0);
962 expect_notify_update(mock_local_image_ctx
);
965 expect_load_image_meta(mock_image_meta
, false, 0);
966 expect_is_refresh_required(mock_local_image_ctx
, true);
968 mock_local_image_ctx
, {
969 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
970 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
974 expect_is_refresh_required(mock_remote_image_ctx
, false);
977 update_watch_ctx
->handle_notify();
979 // wait for sync to complete and expect replay complete
980 ASSERT_EQ(0, wait_for_notification(2));
981 ASSERT_FALSE(mock_replayer
.is_replaying());
983 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
984 mock_local_image_ctx
,
985 mock_remote_image_ctx
));
988 TEST_F(TestMockImageReplayerSnapshotReplayer
, LocalImagePromoted
) {
989 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
990 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
992 MockThreads
mock_threads(m_threads
);
993 expect_work_queue_repeatedly(mock_threads
);
995 MockReplayerListener mock_replayer_listener
;
996 expect_notification(mock_threads
, mock_replayer_listener
);
1000 MockInstanceWatcher mock_instance_watcher
;
1001 MockImageMeta mock_image_meta
;
1002 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1003 mock_remote_image_ctx
,
1005 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1006 "local mirror uuid", &m_pool_meta_cache
,
1007 &mock_state_builder
, &mock_replayer_listener
};
1008 m_pool_meta_cache
.set_remote_pool_meta(
1009 m_remote_io_ctx
.get_id(),
1010 {"remote mirror uuid", "remote mirror peer uuid"});
1012 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1013 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1014 mock_local_image_ctx
,
1015 mock_remote_image_ctx
,
1016 mock_replayer_listener
,
1018 &update_watch_ctx
));
1020 // inject a promotion snapshot
1021 mock_local_image_ctx
.snap_info
= {
1022 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1023 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
,
1024 {"remote mirror peer uuid"}, "", 0U, true, 0, {}},
1028 expect_load_image_meta(mock_image_meta
, false, 0);
1029 expect_is_refresh_required(mock_local_image_ctx
, false);
1030 expect_is_refresh_required(mock_remote_image_ctx
, false);
1033 update_watch_ctx
->handle_notify();
1035 // wait for sync to complete and expect replay complete
1036 ASSERT_EQ(0, wait_for_notification(1));
1037 ASSERT_FALSE(mock_replayer
.is_replaying());
1039 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1040 mock_local_image_ctx
,
1041 mock_remote_image_ctx
));
1044 TEST_F(TestMockImageReplayerSnapshotReplayer
, ResyncRequested
) {
1045 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1046 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1048 MockThreads
mock_threads(m_threads
);
1049 expect_work_queue_repeatedly(mock_threads
);
1051 MockReplayerListener mock_replayer_listener
;
1052 expect_notification(mock_threads
, mock_replayer_listener
);
1056 MockInstanceWatcher mock_instance_watcher
;
1057 MockImageMeta mock_image_meta
;
1058 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1059 mock_remote_image_ctx
,
1061 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1062 "local mirror uuid", &m_pool_meta_cache
,
1063 &mock_state_builder
, &mock_replayer_listener
};
1064 m_pool_meta_cache
.set_remote_pool_meta(
1065 m_remote_io_ctx
.get_id(),
1066 {"remote mirror uuid", "remote mirror peer uuid"});
1068 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1069 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1070 mock_local_image_ctx
,
1071 mock_remote_image_ctx
,
1072 mock_replayer_listener
,
1074 &update_watch_ctx
));
1077 expect_load_image_meta(mock_image_meta
, true, 0);
1080 update_watch_ctx
->handle_notify();
1082 // wait for sync to complete and expect replay complete
1083 ASSERT_EQ(0, wait_for_notification(1));
1084 ASSERT_FALSE(mock_replayer
.is_replaying());
1086 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1087 mock_local_image_ctx
,
1088 mock_remote_image_ctx
));
1091 TEST_F(TestMockImageReplayerSnapshotReplayer
, RegisterLocalUpdateWatcherError
) {
1092 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1093 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1095 MockThreads
mock_threads(m_threads
);
1096 expect_work_queue_repeatedly(mock_threads
);
1100 MockInstanceWatcher mock_instance_watcher
;
1101 MockImageMeta mock_image_meta
;
1102 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1103 mock_remote_image_ctx
,
1105 MockReplayerListener mock_replayer_listener
;
1106 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1107 "local mirror uuid", &m_pool_meta_cache
,
1108 &mock_state_builder
, &mock_replayer_listener
};
1109 m_pool_meta_cache
.set_remote_pool_meta(
1110 m_remote_io_ctx
.get_id(),
1111 {"remote mirror uuid", "remote mirror peer uuid"});
1114 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1115 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
1119 C_SaferCond init_ctx
;
1120 mock_replayer
.init(&init_ctx
);
1121 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
1124 TEST_F(TestMockImageReplayerSnapshotReplayer
, RegisterRemoteUpdateWatcherError
) {
1125 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1126 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1128 MockThreads
mock_threads(m_threads
);
1129 expect_work_queue_repeatedly(mock_threads
);
1133 MockInstanceWatcher mock_instance_watcher
;
1134 MockImageMeta mock_image_meta
;
1135 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1136 mock_remote_image_ctx
,
1138 MockReplayerListener mock_replayer_listener
;
1139 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1140 "local mirror uuid", &m_pool_meta_cache
,
1141 &mock_state_builder
, &mock_replayer_listener
};
1142 m_pool_meta_cache
.set_remote_pool_meta(
1143 m_remote_io_ctx
.get_id(),
1144 {"remote mirror uuid", "remote mirror peer uuid"});
1147 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1148 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
1150 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
1153 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
1156 C_SaferCond init_ctx
;
1157 mock_replayer
.init(&init_ctx
);
1158 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
1161 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnregisterRemoteUpdateWatcherError
) {
1162 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1163 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1165 MockThreads
mock_threads(m_threads
);
1166 expect_work_queue_repeatedly(mock_threads
);
1168 MockReplayerListener mock_replayer_listener
;
1169 expect_notification(mock_threads
, mock_replayer_listener
);
1173 MockInstanceWatcher mock_instance_watcher
;
1174 MockImageMeta mock_image_meta
;
1175 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1176 mock_remote_image_ctx
,
1178 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1179 "local mirror uuid", &m_pool_meta_cache
,
1180 &mock_state_builder
, &mock_replayer_listener
};
1181 m_pool_meta_cache
.set_remote_pool_meta(
1182 m_remote_io_ctx
.get_id(),
1183 {"remote mirror uuid", "remote mirror peer uuid"});
1185 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1186 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1187 mock_local_image_ctx
,
1188 mock_remote_image_ctx
,
1189 mock_replayer_listener
,
1191 &update_watch_ctx
));
1195 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, -EINVAL
);
1196 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
1198 C_SaferCond shutdown_ctx
;
1199 mock_replayer
.shut_down(&shutdown_ctx
);
1200 ASSERT_EQ(-EINVAL
, shutdown_ctx
.wait());
1203 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnregisterLocalUpdateWatcherError
) {
1204 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1205 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1207 MockThreads
mock_threads(m_threads
);
1208 expect_work_queue_repeatedly(mock_threads
);
1210 MockReplayerListener mock_replayer_listener
;
1211 expect_notification(mock_threads
, mock_replayer_listener
);
1215 MockInstanceWatcher mock_instance_watcher
;
1216 MockImageMeta mock_image_meta
;
1217 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1218 mock_remote_image_ctx
,
1220 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1221 "local mirror uuid", &m_pool_meta_cache
,
1222 &mock_state_builder
, &mock_replayer_listener
};
1223 m_pool_meta_cache
.set_remote_pool_meta(
1224 m_remote_io_ctx
.get_id(),
1225 {"remote mirror uuid", "remote mirror peer uuid"});
1227 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1228 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1229 mock_local_image_ctx
,
1230 mock_remote_image_ctx
,
1231 mock_replayer_listener
,
1233 &update_watch_ctx
));
1237 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, 0);
1238 expect_unregister_update_watcher(mock_local_image_ctx
, 123, -EINVAL
);
1240 C_SaferCond shutdown_ctx
;
1241 mock_replayer
.shut_down(&shutdown_ctx
);
1242 ASSERT_EQ(-EINVAL
, shutdown_ctx
.wait());
1245 TEST_F(TestMockImageReplayerSnapshotReplayer
, LoadImageMetaError
) {
1246 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1247 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1249 MockThreads
mock_threads(m_threads
);
1250 expect_work_queue_repeatedly(mock_threads
);
1252 MockReplayerListener mock_replayer_listener
;
1253 expect_notification(mock_threads
, mock_replayer_listener
);
1257 MockInstanceWatcher mock_instance_watcher
;
1258 MockImageMeta mock_image_meta
;
1259 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1260 mock_remote_image_ctx
,
1262 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1263 "local mirror uuid", &m_pool_meta_cache
,
1264 &mock_state_builder
, &mock_replayer_listener
};
1265 m_pool_meta_cache
.set_remote_pool_meta(
1266 m_remote_io_ctx
.get_id(),
1267 {"remote mirror uuid", "remote mirror peer uuid"});
1269 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1270 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1271 mock_local_image_ctx
,
1272 mock_remote_image_ctx
,
1273 mock_replayer_listener
,
1275 &update_watch_ctx
));
1278 expect_load_image_meta(mock_image_meta
, false, -EINVAL
);
1281 update_watch_ctx
->handle_notify();
1283 // wait for sync to complete and expect replay complete
1284 ASSERT_EQ(0, wait_for_notification(1));
1285 ASSERT_FALSE(mock_replayer
.is_replaying());
1286 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1288 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1289 mock_local_image_ctx
,
1290 mock_remote_image_ctx
));
1293 TEST_F(TestMockImageReplayerSnapshotReplayer
, RefreshLocalImageError
) {
1294 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1295 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1297 MockThreads
mock_threads(m_threads
);
1298 expect_work_queue_repeatedly(mock_threads
);
1300 MockReplayerListener mock_replayer_listener
;
1301 expect_notification(mock_threads
, mock_replayer_listener
);
1305 MockInstanceWatcher mock_instance_watcher
;
1306 MockImageMeta mock_image_meta
;
1307 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1308 mock_remote_image_ctx
,
1310 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1311 "local mirror uuid", &m_pool_meta_cache
,
1312 &mock_state_builder
, &mock_replayer_listener
};
1313 m_pool_meta_cache
.set_remote_pool_meta(
1314 m_remote_io_ctx
.get_id(),
1315 {"remote mirror uuid", "remote mirror peer uuid"});
1317 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1318 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1319 mock_local_image_ctx
,
1320 mock_remote_image_ctx
,
1321 mock_replayer_listener
,
1323 &update_watch_ctx
));
1326 expect_load_image_meta(mock_image_meta
, false, 0);
1327 expect_is_refresh_required(mock_local_image_ctx
, true);
1328 expect_refresh(mock_local_image_ctx
, {}, -EINVAL
);
1331 update_watch_ctx
->handle_notify();
1333 // wait for sync to complete and expect replay complete
1334 ASSERT_EQ(0, wait_for_notification(1));
1335 ASSERT_FALSE(mock_replayer
.is_replaying());
1336 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1338 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1339 mock_local_image_ctx
,
1340 mock_remote_image_ctx
));
1343 TEST_F(TestMockImageReplayerSnapshotReplayer
, RefreshRemoteImageError
) {
1344 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1345 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1347 MockThreads
mock_threads(m_threads
);
1348 expect_work_queue_repeatedly(mock_threads
);
1350 MockReplayerListener mock_replayer_listener
;
1351 expect_notification(mock_threads
, mock_replayer_listener
);
1355 MockInstanceWatcher mock_instance_watcher
;
1356 MockImageMeta mock_image_meta
;
1357 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1358 mock_remote_image_ctx
,
1360 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1361 "local mirror uuid", &m_pool_meta_cache
,
1362 &mock_state_builder
, &mock_replayer_listener
};
1363 m_pool_meta_cache
.set_remote_pool_meta(
1364 m_remote_io_ctx
.get_id(),
1365 {"remote mirror uuid", "remote mirror peer uuid"});
1367 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1368 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1369 mock_local_image_ctx
,
1370 mock_remote_image_ctx
,
1371 mock_replayer_listener
,
1373 &update_watch_ctx
));
1376 expect_load_image_meta(mock_image_meta
, false, 0);
1377 expect_is_refresh_required(mock_local_image_ctx
, false);
1378 expect_is_refresh_required(mock_remote_image_ctx
, true);
1379 expect_refresh(mock_remote_image_ctx
, {}, -EINVAL
);
1382 update_watch_ctx
->handle_notify();
1384 // wait for sync to complete and expect replay complete
1385 ASSERT_EQ(0, wait_for_notification(1));
1386 ASSERT_FALSE(mock_replayer
.is_replaying());
1387 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1389 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1390 mock_local_image_ctx
,
1391 mock_remote_image_ctx
));
1394 TEST_F(TestMockImageReplayerSnapshotReplayer
, CopySnapshotsError
) {
1395 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1396 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1398 MockThreads
mock_threads(m_threads
);
1399 expect_work_queue_repeatedly(mock_threads
);
1401 MockReplayerListener mock_replayer_listener
;
1402 expect_notification(mock_threads
, mock_replayer_listener
);
1406 MockInstanceWatcher mock_instance_watcher
;
1407 MockImageMeta mock_image_meta
;
1408 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1409 mock_remote_image_ctx
,
1411 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1412 "local mirror uuid", &m_pool_meta_cache
,
1413 &mock_state_builder
, &mock_replayer_listener
};
1414 m_pool_meta_cache
.set_remote_pool_meta(
1415 m_remote_io_ctx
.get_id(),
1416 {"remote mirror uuid", "remote mirror peer uuid"});
1418 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1419 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1420 mock_local_image_ctx
,
1421 mock_remote_image_ctx
,
1422 mock_replayer_listener
,
1424 &update_watch_ctx
));
1427 mock_remote_image_ctx
.snap_info
= {
1428 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1429 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1434 expect_load_image_meta(mock_image_meta
, false, 0);
1435 expect_is_refresh_required(mock_local_image_ctx
, false);
1436 expect_is_refresh_required(mock_remote_image_ctx
, false);
1437 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1438 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1442 update_watch_ctx
->handle_notify();
1444 // wait for sync to complete and expect replay complete
1445 ASSERT_EQ(0, wait_for_notification(1));
1446 ASSERT_FALSE(mock_replayer
.is_replaying());
1447 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1449 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1450 mock_local_image_ctx
,
1451 mock_remote_image_ctx
));
1454 TEST_F(TestMockImageReplayerSnapshotReplayer
, GetImageStateError
) {
1455 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1456 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1458 MockThreads
mock_threads(m_threads
);
1459 expect_work_queue_repeatedly(mock_threads
);
1461 MockReplayerListener mock_replayer_listener
;
1462 expect_notification(mock_threads
, mock_replayer_listener
);
1466 MockInstanceWatcher mock_instance_watcher
;
1467 MockImageMeta mock_image_meta
;
1468 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1469 mock_remote_image_ctx
,
1471 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1472 "local mirror uuid", &m_pool_meta_cache
,
1473 &mock_state_builder
, &mock_replayer_listener
};
1474 m_pool_meta_cache
.set_remote_pool_meta(
1475 m_remote_io_ctx
.get_id(),
1476 {"remote mirror uuid", "remote mirror peer uuid"});
1478 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1479 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1480 mock_local_image_ctx
,
1481 mock_remote_image_ctx
,
1482 mock_replayer_listener
,
1484 &update_watch_ctx
));
1487 mock_remote_image_ctx
.snap_info
= {
1488 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1489 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1494 expect_load_image_meta(mock_image_meta
, false, 0);
1495 expect_is_refresh_required(mock_local_image_ctx
, false);
1496 expect_is_refresh_required(mock_remote_image_ctx
, false);
1497 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1498 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1500 MockGetImageStateRequest mock_get_image_state_request
;
1501 expect_get_image_state(mock_get_image_state_request
, 1, -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
, CreateNonPrimarySnapshotError
) {
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"}, "",
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
}},
1562 MockGetImageStateRequest mock_get_image_state_request
;
1563 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1564 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1565 expect_create_non_primary_request(mock_create_non_primary_request
,
1566 false, "remote mirror uuid", 1,
1567 {{1, CEPH_NOSNAP
}}, 11, -EINVAL
);
1570 update_watch_ctx
->handle_notify();
1572 // wait for sync to complete and expect replay complete
1573 ASSERT_EQ(0, wait_for_notification(1));
1574 ASSERT_FALSE(mock_replayer
.is_replaying());
1575 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1577 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1578 mock_local_image_ctx
,
1579 mock_remote_image_ctx
));
1582 TEST_F(TestMockImageReplayerSnapshotReplayer
, RequestSyncError
) {
1583 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1584 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1586 MockThreads
mock_threads(m_threads
);
1587 expect_work_queue_repeatedly(mock_threads
);
1589 MockReplayerListener mock_replayer_listener
;
1590 expect_notification(mock_threads
, mock_replayer_listener
);
1594 MockInstanceWatcher mock_instance_watcher
;
1595 MockImageMeta mock_image_meta
;
1596 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1597 mock_remote_image_ctx
,
1599 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1600 "local mirror uuid", &m_pool_meta_cache
,
1601 &mock_state_builder
, &mock_replayer_listener
};
1602 m_pool_meta_cache
.set_remote_pool_meta(
1603 m_remote_io_ctx
.get_id(),
1604 {"remote mirror uuid", "remote mirror peer uuid"});
1606 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1607 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1608 mock_local_image_ctx
,
1609 mock_remote_image_ctx
,
1610 mock_replayer_listener
,
1612 &update_watch_ctx
));
1615 mock_remote_image_ctx
.snap_info
= {
1616 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1617 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1622 expect_load_image_meta(mock_image_meta
, false, 0);
1623 expect_is_refresh_required(mock_local_image_ctx
, false);
1624 expect_is_refresh_required(mock_remote_image_ctx
, false);
1625 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1626 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1628 MockGetImageStateRequest mock_get_image_state_request
;
1629 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1630 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1631 expect_create_non_primary_request(mock_create_non_primary_request
,
1632 false, "remote mirror uuid", 1,
1633 {{1, CEPH_NOSNAP
}}, 11, 0);
1634 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
,
1638 update_watch_ctx
->handle_notify();
1640 // wait for sync to complete and expect replay complete
1641 ASSERT_EQ(0, wait_for_notification(1));
1642 ASSERT_FALSE(mock_replayer
.is_replaying());
1643 ASSERT_EQ(-ECANCELED
, mock_replayer
.get_error_code());
1645 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1646 mock_local_image_ctx
,
1647 mock_remote_image_ctx
));
1651 TEST_F(TestMockImageReplayerSnapshotReplayer
, CopyImageError
) {
1652 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1653 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1655 MockThreads
mock_threads(m_threads
);
1656 expect_work_queue_repeatedly(mock_threads
);
1658 MockReplayerListener mock_replayer_listener
;
1659 expect_notification(mock_threads
, mock_replayer_listener
);
1663 MockInstanceWatcher mock_instance_watcher
;
1664 MockImageMeta mock_image_meta
;
1665 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1666 mock_remote_image_ctx
,
1668 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1669 "local mirror uuid", &m_pool_meta_cache
,
1670 &mock_state_builder
, &mock_replayer_listener
};
1671 m_pool_meta_cache
.set_remote_pool_meta(
1672 m_remote_io_ctx
.get_id(),
1673 {"remote mirror uuid", "remote mirror peer uuid"});
1675 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1676 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1677 mock_local_image_ctx
,
1678 mock_remote_image_ctx
,
1679 mock_replayer_listener
,
1681 &update_watch_ctx
));
1684 mock_remote_image_ctx
.snap_info
= {
1685 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1686 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1691 expect_load_image_meta(mock_image_meta
, false, 0);
1692 expect_is_refresh_required(mock_local_image_ctx
, false);
1693 expect_is_refresh_required(mock_remote_image_ctx
, false);
1694 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1695 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1697 MockGetImageStateRequest mock_get_image_state_request
;
1698 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1699 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1700 expect_create_non_primary_request(mock_create_non_primary_request
,
1701 false, "remote mirror uuid", 1,
1702 {{1, CEPH_NOSNAP
}}, 11, 0);
1703 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1704 MockImageCopyRequest mock_image_copy_request
;
1705 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
1706 {{1, CEPH_NOSNAP
}}, -EINVAL
);
1709 update_watch_ctx
->handle_notify();
1711 // wait for sync to complete and expect replay complete
1712 ASSERT_EQ(0, wait_for_notification(1));
1713 ASSERT_FALSE(mock_replayer
.is_replaying());
1714 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1716 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1717 mock_local_image_ctx
,
1718 mock_remote_image_ctx
));
1721 TEST_F(TestMockImageReplayerSnapshotReplayer
, UpdateNonPrimarySnapshotError
) {
1722 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1723 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1725 MockThreads
mock_threads(m_threads
);
1726 expect_work_queue_repeatedly(mock_threads
);
1728 MockReplayerListener mock_replayer_listener
;
1729 expect_notification(mock_threads
, mock_replayer_listener
);
1733 MockInstanceWatcher mock_instance_watcher
;
1734 MockImageMeta mock_image_meta
;
1735 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1736 mock_remote_image_ctx
,
1738 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1739 "local mirror uuid", &m_pool_meta_cache
,
1740 &mock_state_builder
, &mock_replayer_listener
};
1741 m_pool_meta_cache
.set_remote_pool_meta(
1742 m_remote_io_ctx
.get_id(),
1743 {"remote mirror uuid", "remote mirror peer uuid"});
1745 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1746 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1747 mock_local_image_ctx
,
1748 mock_remote_image_ctx
,
1749 mock_replayer_listener
,
1751 &update_watch_ctx
));
1754 mock_remote_image_ctx
.snap_info
= {
1755 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1756 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1761 expect_load_image_meta(mock_image_meta
, false, 0);
1762 expect_is_refresh_required(mock_local_image_ctx
, false);
1763 expect_is_refresh_required(mock_remote_image_ctx
, false);
1764 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1765 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1767 MockGetImageStateRequest mock_get_image_state_request
;
1768 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1769 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1770 expect_create_non_primary_request(mock_create_non_primary_request
,
1771 false, "remote mirror uuid", 1,
1772 {{1, CEPH_NOSNAP
}}, 11, 0);
1773 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1774 MockImageCopyRequest mock_image_copy_request
;
1775 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
1776 {{1, CEPH_NOSNAP
}}, 0);
1777 MockApplyImageStateRequest mock_apply_state_request
;
1778 expect_apply_image_state(mock_apply_state_request
, 0);
1779 expect_mirror_image_snapshot_set_copy_progress(
1780 mock_local_image_ctx
, 11, true, 0, -EINVAL
);
1783 update_watch_ctx
->handle_notify();
1785 // wait for sync to complete and expect replay complete
1786 ASSERT_EQ(0, wait_for_notification(1));
1787 ASSERT_FALSE(mock_replayer
.is_replaying());
1788 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1790 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1791 mock_local_image_ctx
,
1792 mock_remote_image_ctx
));
1795 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnlinkPeerError
) {
1796 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1797 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1799 MockThreads
mock_threads(m_threads
);
1800 expect_work_queue_repeatedly(mock_threads
);
1802 MockReplayerListener mock_replayer_listener
;
1803 expect_notification(mock_threads
, mock_replayer_listener
);
1807 MockInstanceWatcher mock_instance_watcher
;
1808 MockImageMeta mock_image_meta
;
1809 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1810 mock_remote_image_ctx
,
1812 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1813 "local mirror uuid", &m_pool_meta_cache
,
1814 &mock_state_builder
, &mock_replayer_listener
};
1815 m_pool_meta_cache
.set_remote_pool_meta(
1816 m_remote_io_ctx
.get_id(),
1817 {"remote mirror uuid", "remote mirror peer uuid"});
1819 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1820 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1821 mock_local_image_ctx
,
1822 mock_remote_image_ctx
,
1823 mock_replayer_listener
,
1825 &update_watch_ctx
));
1828 mock_remote_image_ctx
.snap_info
= {
1829 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1830 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1833 {2U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
1834 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
1835 "", 0U, true, 0, {}},
1837 mock_local_image_ctx
.snap_info
= {
1838 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1839 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
1844 expect_load_image_meta(mock_image_meta
, false, 0);
1845 expect_is_refresh_required(mock_local_image_ctx
, false);
1846 expect_is_refresh_required(mock_remote_image_ctx
, false);
1847 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1848 expect_snapshot_copy(mock_snapshot_copy_request
, 1, 2, 11, {{2, CEPH_NOSNAP
}},
1850 MockGetImageStateRequest mock_get_image_state_request
;
1851 expect_get_image_state(mock_get_image_state_request
, 2, 0);
1852 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1853 expect_create_non_primary_request(mock_create_non_primary_request
,
1854 false, "remote mirror uuid", 2,
1855 {{2, CEPH_NOSNAP
}}, 12, 0);
1856 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1857 MockImageCopyRequest mock_image_copy_request
;
1858 expect_image_copy(mock_image_copy_request
, 1, 2, 11, {},
1859 {{2, CEPH_NOSNAP
}}, 0);
1860 MockApplyImageStateRequest mock_apply_state_request
;
1861 expect_apply_image_state(mock_apply_state_request
, 0);
1862 expect_mirror_image_snapshot_set_copy_progress(
1863 mock_local_image_ctx
, 12, true, 0, 0);
1864 expect_notify_update(mock_local_image_ctx
);
1865 MockUnlinkPeerRequest mock_unlink_peer_request
;
1866 expect_unlink_peer(mock_unlink_peer_request
, 1, "remote mirror peer uuid",
1868 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
1871 update_watch_ctx
->handle_notify();
1873 // wait for sync to complete and expect replay complete
1874 ASSERT_EQ(0, wait_for_notification(1));
1875 ASSERT_FALSE(mock_replayer
.is_replaying());
1876 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1878 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1879 mock_local_image_ctx
,
1880 mock_remote_image_ctx
));
1883 TEST_F(TestMockImageReplayerSnapshotReplayer
, SplitBrain
) {
1884 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1885 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1887 MockThreads
mock_threads(m_threads
);
1888 expect_work_queue_repeatedly(mock_threads
);
1890 MockReplayerListener mock_replayer_listener
;
1891 expect_notification(mock_threads
, mock_replayer_listener
);
1895 MockInstanceWatcher mock_instance_watcher
;
1896 MockImageMeta mock_image_meta
;
1897 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1898 mock_remote_image_ctx
,
1900 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1901 "local mirror uuid", &m_pool_meta_cache
,
1902 &mock_state_builder
, &mock_replayer_listener
};
1903 m_pool_meta_cache
.set_remote_pool_meta(
1904 m_remote_io_ctx
.get_id(),
1905 {"remote mirror uuid", "remote mirror peer uuid"});
1907 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1908 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1909 mock_local_image_ctx
,
1910 mock_remote_image_ctx
,
1911 mock_replayer_listener
,
1913 &update_watch_ctx
));
1915 // inject a primary demote to local image
1916 mock_remote_image_ctx
.snap_info
= {
1917 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1918 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
1919 "", 0U, true, 0, {}},
1921 mock_local_image_ctx
.snap_info
= {
1922 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1923 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", 0U, true, 0,
1927 // detect split-brain
1928 expect_load_image_meta(mock_image_meta
, false, 0);
1929 expect_is_refresh_required(mock_local_image_ctx
, false);
1930 expect_is_refresh_required(mock_remote_image_ctx
, false);
1933 update_watch_ctx
->handle_notify();
1935 // wait for sync to complete and expect replay complete
1936 ASSERT_EQ(0, wait_for_notification(1));
1937 ASSERT_FALSE(mock_replayer
.is_replaying());
1938 ASSERT_EQ(-EEXIST
, mock_replayer
.get_error_code());
1939 ASSERT_EQ(std::string
{"split-brain"}, mock_replayer
.get_error_description());
1941 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1942 mock_local_image_ctx
,
1943 mock_remote_image_ctx
));
1946 } // namespace snapshot
1947 } // namespace image_replayer
1948 } // namespace mirror