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/librbd/mock/MockOperations.h"
22 #include "test/rbd_mirror/mock/MockContextWQ.h"
23 #include "test/rbd_mirror/mock/MockSafeTimer.h"
28 struct MockTestImageCtx
: public librbd::MockImageCtx
{
29 explicit MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
30 : librbd::MockImageCtx(image_ctx
) {
34 } // anonymous namespace
39 struct ImageCopyRequest
<MockTestImageCtx
> {
40 uint64_t src_snap_id_start
;
41 uint64_t src_snap_id_end
;
42 uint64_t dst_snap_id_start
;
43 librbd::deep_copy::ObjectNumber object_number
;
44 librbd::SnapSeqs snap_seqs
;
46 static ImageCopyRequest
* s_instance
;
47 static ImageCopyRequest
* create(MockTestImageCtx
*src_image_ctx
,
48 MockTestImageCtx
*dst_image_ctx
,
49 librados::snap_t src_snap_id_start
,
50 librados::snap_t src_snap_id_end
,
51 librados::snap_t dst_snap_id_start
,
53 const ObjectNumber
&object_number
,
54 const SnapSeqs
&snap_seqs
,
57 ceph_assert(s_instance
!= nullptr);
58 s_instance
->src_snap_id_start
= src_snap_id_start
;
59 s_instance
->src_snap_id_end
= src_snap_id_end
;
60 s_instance
->dst_snap_id_start
= dst_snap_id_start
;
61 s_instance
->object_number
= object_number
;
62 s_instance
->snap_seqs
= snap_seqs
;
63 s_instance
->on_finish
= on_finish
;
67 Context
* on_finish
= nullptr;
73 MOCK_METHOD0(send
, void());
77 struct SnapshotCopyRequest
<MockTestImageCtx
> {
78 librados::snap_t src_snap_id_start
;
79 librados::snap_t src_snap_id_end
;
80 librados::snap_t dst_snap_id_start
;
81 SnapSeqs
* snap_seqs
= nullptr;
83 static SnapshotCopyRequest
* s_instance
;
84 static SnapshotCopyRequest
* create(MockTestImageCtx
*src_image_ctx
,
85 MockTestImageCtx
*dst_image_ctx
,
86 librados::snap_t src_snap_id_start
,
87 librados::snap_t src_snap_id_end
,
88 librados::snap_t dst_snap_id_start
,
90 ::MockContextWQ
*work_queue
,
93 ceph_assert(s_instance
!= nullptr);
94 s_instance
->src_snap_id_start
= src_snap_id_start
;
95 s_instance
->src_snap_id_end
= src_snap_id_end
;
96 s_instance
->dst_snap_id_start
= dst_snap_id_start
;
97 s_instance
->snap_seqs
= snap_seqs
;
98 s_instance
->on_finish
= on_finish
;
102 Context
* on_finish
= nullptr;
104 SnapshotCopyRequest() {
108 MOCK_METHOD0(send
, void());
111 ImageCopyRequest
<MockTestImageCtx
>* ImageCopyRequest
<MockTestImageCtx
>::s_instance
= nullptr;
112 SnapshotCopyRequest
<MockTestImageCtx
>* SnapshotCopyRequest
<MockTestImageCtx
>::s_instance
= nullptr;
114 } // namespace deep_copy
120 struct CreateNonPrimaryRequest
<MockTestImageCtx
> {
121 bool demoted
= false;
122 std::string primary_mirror_uuid
;
123 uint64_t primary_snap_id
;
125 uint64_t* snap_id
= nullptr;
127 static CreateNonPrimaryRequest
* s_instance
;
128 static CreateNonPrimaryRequest
* create(MockTestImageCtx
*image_ctx
,
130 const std::string
&primary_mirror_uuid
,
131 uint64_t primary_snap_id
,
132 const SnapSeqs
& snap_seqs
,
133 const ImageState
&image_state
,
135 Context
*on_finish
) {
136 ceph_assert(s_instance
!= nullptr);
137 s_instance
->demoted
= demoted
;
138 s_instance
->primary_mirror_uuid
= primary_mirror_uuid
;
139 s_instance
->primary_snap_id
= primary_snap_id
;
140 s_instance
->snap_seqs
= snap_seqs
;
141 s_instance
->snap_id
= snap_id
;
142 s_instance
->on_finish
= on_finish
;
146 Context
* on_finish
= nullptr;
148 CreateNonPrimaryRequest() {
152 MOCK_METHOD0(send
, void());
156 struct GetImageStateRequest
<MockTestImageCtx
> {
157 uint64_t snap_id
= CEPH_NOSNAP
;
159 static GetImageStateRequest
* s_instance
;
160 static GetImageStateRequest
* create(MockTestImageCtx
*image_ctx
,
162 ImageState
*image_state
,
163 Context
*on_finish
) {
164 ceph_assert(s_instance
!= nullptr);
165 s_instance
->snap_id
= snap_id
;
166 s_instance
->on_finish
= on_finish
;
170 Context
* on_finish
= nullptr;
172 GetImageStateRequest() {
176 MOCK_METHOD0(send
, void());
180 struct ImageMeta
<MockTestImageCtx
> {
181 MOCK_METHOD1(load
, void(Context
*));
183 bool resync_requested
= false;
187 struct UnlinkPeerRequest
<MockTestImageCtx
> {
189 std::string mirror_peer_uuid
;
191 static UnlinkPeerRequest
* s_instance
;
192 static UnlinkPeerRequest
*create (MockTestImageCtx
*image_ctx
,
194 const std::string
&mirror_peer_uuid
,
195 Context
*on_finish
) {
196 ceph_assert(s_instance
!= nullptr);
197 s_instance
->snap_id
= snap_id
;
198 s_instance
->mirror_peer_uuid
= mirror_peer_uuid
;
199 s_instance
->on_finish
= on_finish
;
203 Context
* on_finish
= nullptr;
205 UnlinkPeerRequest() {
209 MOCK_METHOD0(send
, void());
212 CreateNonPrimaryRequest
<MockTestImageCtx
>* CreateNonPrimaryRequest
<MockTestImageCtx
>::s_instance
= nullptr;
213 GetImageStateRequest
<MockTestImageCtx
>* GetImageStateRequest
<MockTestImageCtx
>::s_instance
= nullptr;
214 UnlinkPeerRequest
<MockTestImageCtx
>* UnlinkPeerRequest
<MockTestImageCtx
>::s_instance
= nullptr;
216 } // namespace snapshot
217 } // namespace mirror
218 } // namespace librbd
224 struct InstanceWatcher
<librbd::MockTestImageCtx
> {
225 MOCK_METHOD1(cancel_sync_request
, void(const std::string
&));
226 MOCK_METHOD2(notify_sync_request
, void(const std::string
&,
228 MOCK_METHOD1(notify_sync_complete
, void(const std::string
&));
232 struct Threads
<librbd::MockTestImageCtx
> {
233 MockSafeTimer
*timer
;
234 ceph::mutex
&timer_lock
;
236 MockContextWQ
*work_queue
;
238 Threads(Threads
<librbd::ImageCtx
>* threads
)
239 : timer(new MockSafeTimer()),
240 timer_lock(threads
->timer_lock
),
241 work_queue(new MockContextWQ()) {
251 struct MockReplayerListener
: public image_replayer::ReplayerListener
{
252 MOCK_METHOD0(handle_notification
, void());
255 } // anonymous namespace
257 namespace image_replayer
{
260 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
261 static CloseImageRequest
* s_instance
;
262 librbd::MockTestImageCtx
**image_ctx
= nullptr;
263 Context
*on_finish
= nullptr;
265 static CloseImageRequest
* create(librbd::MockTestImageCtx
**image_ctx
,
266 Context
*on_finish
) {
267 ceph_assert(s_instance
!= nullptr);
268 s_instance
->image_ctx
= image_ctx
;
269 s_instance
->on_finish
= on_finish
;
273 CloseImageRequest() {
274 ceph_assert(s_instance
== nullptr);
278 ~CloseImageRequest() {
279 ceph_assert(s_instance
== this);
280 s_instance
= nullptr;
283 MOCK_METHOD0(send
, void());
286 CloseImageRequest
<librbd::MockTestImageCtx
>* CloseImageRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
291 struct ApplyImageStateRequest
<librbd::MockTestImageCtx
> {
292 Context
* on_finish
= nullptr;
294 static ApplyImageStateRequest
* s_instance
;
295 static ApplyImageStateRequest
* create(
296 const std::string
& local_mirror_uuid
,
297 const std::string
& remote_mirror_uuid
,
298 librbd::MockTestImageCtx
* local_image_ctx
,
299 librbd::MockTestImageCtx
* remote_image_ctx
,
300 const librbd::mirror::snapshot::ImageState
& image_state
,
301 Context
* on_finish
) {
302 ceph_assert(s_instance
!= nullptr);
303 s_instance
->on_finish
= on_finish
;
307 ApplyImageStateRequest() {
311 MOCK_METHOD0(send
, void());
315 struct StateBuilder
<librbd::MockTestImageCtx
> {
316 StateBuilder(librbd::MockTestImageCtx
& local_image_ctx
,
317 librbd::MockTestImageCtx
& remote_image_ctx
,
318 librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
>&
320 : local_image_ctx(&local_image_ctx
),
321 remote_image_ctx(&remote_image_ctx
),
322 local_image_meta(&local_image_meta
) {
325 librbd::MockTestImageCtx
* local_image_ctx
;
326 librbd::MockTestImageCtx
* remote_image_ctx
;
328 std::string remote_mirror_uuid
= "remote mirror uuid";
330 librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
>*
331 local_image_meta
= nullptr;
334 ApplyImageStateRequest
<librbd::MockTestImageCtx
>* ApplyImageStateRequest
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
336 } // namespace snapshot
337 } // namespace image_replayer
338 } // namespace mirror
341 #include "tools/rbd_mirror/image_replayer/snapshot/Replayer.cc"
345 namespace image_replayer
{
349 using ::testing::DoAll
;
350 using ::testing::InSequence
;
351 using ::testing::Invoke
;
352 using ::testing::Return
;
353 using ::testing::ReturnArg
;
354 using ::testing::StrEq
;
355 using ::testing::WithArg
;
357 class TestMockImageReplayerSnapshotReplayer
: public TestMockFixture
{
359 typedef Replayer
<librbd::MockTestImageCtx
> MockReplayer
;
360 typedef ApplyImageStateRequest
<librbd::MockTestImageCtx
> MockApplyImageStateRequest
;
361 typedef StateBuilder
<librbd::MockTestImageCtx
> MockStateBuilder
;
362 typedef InstanceWatcher
<librbd::MockTestImageCtx
> MockInstanceWatcher
;
363 typedef Threads
<librbd::MockTestImageCtx
> MockThreads
;
364 typedef CloseImageRequest
<librbd::MockTestImageCtx
> MockCloseImageRequest
;
365 typedef librbd::deep_copy::ImageCopyRequest
<librbd::MockTestImageCtx
> MockImageCopyRequest
;
366 typedef librbd::deep_copy::SnapshotCopyRequest
<librbd::MockTestImageCtx
> MockSnapshotCopyRequest
;
367 typedef librbd::mirror::snapshot::CreateNonPrimaryRequest
<librbd::MockTestImageCtx
> MockCreateNonPrimaryRequest
;
368 typedef librbd::mirror::snapshot::GetImageStateRequest
<librbd::MockTestImageCtx
> MockGetImageStateRequest
;
369 typedef librbd::mirror::snapshot::ImageMeta
<librbd::MockTestImageCtx
> MockImageMeta
;
370 typedef librbd::mirror::snapshot::UnlinkPeerRequest
<librbd::MockTestImageCtx
> MockUnlinkPeerRequest
;
372 void SetUp() override
{
373 TestMockFixture::SetUp();
376 ASSERT_EQ(0, create_image(rbd
, m_local_io_ctx
, m_image_name
, m_image_size
));
377 ASSERT_EQ(0, open_image(m_local_io_ctx
, m_image_name
, &m_local_image_ctx
));
379 ASSERT_EQ(0, create_image(rbd
, m_remote_io_ctx
, m_image_name
,
381 ASSERT_EQ(0, open_image(m_remote_io_ctx
, m_image_name
,
382 &m_remote_image_ctx
));
385 void expect_work_queue_repeatedly(MockThreads
&mock_threads
) {
386 EXPECT_CALL(*mock_threads
.work_queue
, queue(_
, _
))
387 .WillRepeatedly(Invoke([this](Context
*ctx
, int r
) {
388 m_threads
->work_queue
->queue(ctx
, r
);
392 void expect_add_event_after_repeatedly(MockThreads
&mock_threads
) {
393 EXPECT_CALL(*mock_threads
.timer
, add_event_after(_
, _
))
395 DoAll(Invoke([this](double seconds
, Context
*ctx
) {
396 m_threads
->timer
->add_event_after(seconds
, ctx
);
399 EXPECT_CALL(*mock_threads
.timer
, cancel_event(_
))
401 Invoke([this](Context
*ctx
) {
402 return m_threads
->timer
->cancel_event(ctx
);
406 void expect_register_update_watcher(librbd::MockTestImageCtx
& mock_image_ctx
,
407 librbd::UpdateWatchCtx
** update_watch_ctx
,
408 uint64_t watch_handle
, int r
) {
409 EXPECT_CALL(*mock_image_ctx
.state
, register_update_watcher(_
, _
))
410 .WillOnce(Invoke([update_watch_ctx
, watch_handle
, r
]
411 (librbd::UpdateWatchCtx
* ctx
, uint64_t* handle
) {
413 *update_watch_ctx
= ctx
;
414 *handle
= watch_handle
;
420 void expect_unregister_update_watcher(librbd::MockTestImageCtx
& mock_image_ctx
,
421 uint64_t watch_handle
, int r
) {
422 EXPECT_CALL(*mock_image_ctx
.state
, unregister_update_watcher(watch_handle
, _
))
423 .WillOnce(WithArg
<1>(Invoke([this, r
](Context
* ctx
) {
424 m_threads
->work_queue
->queue(ctx
, r
);
428 void expect_load_image_meta(MockImageMeta
& mock_image_meta
,
429 bool resync_requested
, int r
) {
430 EXPECT_CALL(mock_image_meta
, load(_
))
431 .WillOnce(Invoke([this, &mock_image_meta
, resync_requested
, r
](Context
* ctx
) {
432 mock_image_meta
.resync_requested
= resync_requested
;
433 m_threads
->work_queue
->queue(ctx
, r
);
437 void expect_is_refresh_required(librbd::MockTestImageCtx
& mock_image_ctx
,
439 EXPECT_CALL(*mock_image_ctx
.state
, is_refresh_required())
440 .WillOnce(Return(is_required
));
443 void expect_refresh(librbd::MockTestImageCtx
& mock_image_ctx
,
444 const std::map
<uint64_t, librbd::SnapInfo
>& snaps
,
446 EXPECT_CALL(*mock_image_ctx
.state
, refresh(_
))
447 .WillOnce(Invoke([this, &mock_image_ctx
, snaps
, r
](Context
* ctx
) {
448 mock_image_ctx
.snap_info
= snaps
;
449 m_threads
->work_queue
->queue(ctx
, r
);
453 void expect_notify_update(librbd::MockTestImageCtx
& mock_image_ctx
) {
454 EXPECT_CALL(mock_image_ctx
, notify_update(_
))
455 .WillOnce(Invoke([this](Context
* ctx
) {
456 m_threads
->work_queue
->queue(ctx
, 0);
460 void expect_prune_non_primary_snapshot(librbd::MockTestImageCtx
& mock_image_ctx
,
461 uint64_t snap_id
, int r
) {
462 EXPECT_CALL(mock_image_ctx
, get_snap_info(snap_id
))
463 .WillOnce(Invoke([&mock_image_ctx
](uint64_t snap_id
) -> librbd::SnapInfo
* {
464 auto it
= mock_image_ctx
.snap_info
.find(snap_id
);
465 if (it
== mock_image_ctx
.snap_info
.end()) {
470 EXPECT_CALL(*mock_image_ctx
.operations
, snap_remove(_
, _
, _
))
471 .WillOnce(WithArg
<2>(Invoke([this, r
](Context
* ctx
) {
472 m_threads
->work_queue
->queue(ctx
, r
);
476 void expect_snapshot_copy(MockSnapshotCopyRequest
& mock_snapshot_copy_request
,
477 uint64_t src_snap_id_start
,
478 uint64_t src_snap_id_end
,
479 uint64_t dst_snap_id_start
,
480 const librbd::SnapSeqs
& snap_seqs
, int r
) {
481 EXPECT_CALL(mock_snapshot_copy_request
, send())
482 .WillOnce(Invoke([this, &req
=mock_snapshot_copy_request
,
483 src_snap_id_start
, src_snap_id_end
, dst_snap_id_start
,
485 ASSERT_EQ(src_snap_id_start
, req
.src_snap_id_start
);
486 ASSERT_EQ(src_snap_id_end
, req
.src_snap_id_end
);
487 ASSERT_EQ(dst_snap_id_start
, req
.dst_snap_id_start
);
488 *req
.snap_seqs
= snap_seqs
;
489 m_threads
->work_queue
->queue(req
.on_finish
, r
);
493 void expect_get_image_state(MockGetImageStateRequest
& mock_get_image_state_request
,
494 uint64_t snap_id
, int r
) {
495 EXPECT_CALL(mock_get_image_state_request
, send())
496 .WillOnce(Invoke([this, &req
=mock_get_image_state_request
, snap_id
, r
]() {
497 ASSERT_EQ(snap_id
, req
.snap_id
);
498 m_threads
->work_queue
->queue(req
.on_finish
, r
);
502 void expect_create_non_primary_request(MockCreateNonPrimaryRequest
& mock_create_non_primary_request
,
504 const std::string
& primary_mirror_uuid
,
505 uint64_t primary_snap_id
,
506 const librbd::SnapSeqs
& snap_seqs
,
507 uint64_t snap_id
, int r
) {
508 EXPECT_CALL(mock_create_non_primary_request
, send())
509 .WillOnce(Invoke([this, &req
=mock_create_non_primary_request
, demoted
,
510 primary_mirror_uuid
, primary_snap_id
, snap_seqs
,
512 ASSERT_EQ(demoted
, req
.demoted
);
513 ASSERT_EQ(primary_mirror_uuid
, req
.primary_mirror_uuid
);
514 ASSERT_EQ(primary_snap_id
, req
.primary_snap_id
);
515 ASSERT_EQ(snap_seqs
, req
.snap_seqs
);
516 *req
.snap_id
= snap_id
;
517 m_threads
->work_queue
->queue(req
.on_finish
, r
);
521 void expect_notify_sync_request(MockInstanceWatcher
& mock_instance_watcher
,
522 const std::string
& image_id
, int r
) {
523 EXPECT_CALL(mock_instance_watcher
, notify_sync_request(image_id
, _
))
524 .WillOnce(WithArg
<1>(Invoke([this, r
](Context
* ctx
) {
525 m_threads
->work_queue
->queue(ctx
, r
);
529 void expect_notify_sync_complete(MockInstanceWatcher
& mock_instance_watcher
,
530 const std::string
& image_id
) {
531 EXPECT_CALL(mock_instance_watcher
, notify_sync_complete(image_id
));
534 void expect_image_copy(MockImageCopyRequest
& mock_image_copy_request
,
535 uint64_t src_snap_id_start
, uint64_t src_snap_id_end
,
536 uint64_t dst_snap_id_start
,
537 const librbd::deep_copy::ObjectNumber
& object_number
,
538 const librbd::SnapSeqs
& snap_seqs
, int r
) {
539 EXPECT_CALL(mock_image_copy_request
, send())
540 .WillOnce(Invoke([this, &req
=mock_image_copy_request
, src_snap_id_start
,
541 src_snap_id_end
, dst_snap_id_start
, object_number
,
543 ASSERT_EQ(src_snap_id_start
, req
.src_snap_id_start
);
544 ASSERT_EQ(src_snap_id_end
, req
.src_snap_id_end
);
545 ASSERT_EQ(dst_snap_id_start
, req
.dst_snap_id_start
);
546 ASSERT_EQ(object_number
, req
.object_number
);
547 ASSERT_EQ(snap_seqs
, req
.snap_seqs
);
548 m_threads
->work_queue
->queue(req
.on_finish
, r
);
552 void expect_unlink_peer(MockUnlinkPeerRequest
& mock_unlink_peer_request
,
553 uint64_t snap_id
, const std::string
& mirror_peer_uuid
,
555 EXPECT_CALL(mock_unlink_peer_request
, send())
556 .WillOnce(Invoke([this, &req
=mock_unlink_peer_request
, snap_id
,
557 mirror_peer_uuid
, r
]() {
558 ASSERT_EQ(snap_id
, req
.snap_id
);
559 ASSERT_EQ(mirror_peer_uuid
, req
.mirror_peer_uuid
);
560 m_threads
->work_queue
->queue(req
.on_finish
, r
);
564 void expect_apply_image_state(
565 MockApplyImageStateRequest
& mock_request
, int r
) {
566 EXPECT_CALL(mock_request
, send())
567 .WillOnce(Invoke([this, &req
=mock_request
, r
]() {
568 m_threads
->work_queue
->queue(req
.on_finish
, r
);
572 void expect_mirror_image_snapshot_set_copy_progress(
573 librbd::MockTestImageCtx
& mock_test_image_ctx
, uint64_t snap_id
,
574 bool completed
, uint64_t last_copied_object
, int r
) {
577 encode(completed
, bl
);
578 encode(last_copied_object
, bl
);
580 EXPECT_CALL(get_mock_io_ctx(mock_test_image_ctx
.md_ctx
),
581 exec(mock_test_image_ctx
.header_oid
, _
, StrEq("rbd"),
582 StrEq("mirror_image_snapshot_set_copy_progress"),
583 ContentsEqual(bl
), _
, _
))
584 .WillOnce(Return(r
));
587 void expect_send(MockCloseImageRequest
&mock_close_image_request
, int r
) {
588 EXPECT_CALL(mock_close_image_request
, send())
589 .WillOnce(Invoke([this, &mock_close_image_request
, r
]() {
590 *mock_close_image_request
.image_ctx
= nullptr;
591 m_threads
->work_queue
->queue(mock_close_image_request
.on_finish
, r
);
595 void expect_notification(MockThreads
& mock_threads
,
596 MockReplayerListener
& mock_replayer_listener
) {
597 EXPECT_CALL(mock_replayer_listener
, handle_notification())
598 .WillRepeatedly(Invoke([this]() {
599 std::unique_lock locker
{m_lock
};
605 int wait_for_notification(uint32_t count
) {
606 std::unique_lock locker
{m_lock
};
607 for (uint32_t idx
= 0; idx
< count
; ++idx
) {
608 while (m_notifications
== 0) {
609 if (m_cond
.wait_for(locker
, 10s
) == std::cv_status::timeout
) {
618 int init_entry_replayer(MockReplayer
& mock_replayer
,
619 MockThreads
& mock_threads
,
620 librbd::MockTestImageCtx
& mock_local_image_ctx
,
621 librbd::MockTestImageCtx
& mock_remote_image_ctx
,
622 MockReplayerListener
& mock_replayer_listener
,
623 MockImageMeta
& mock_image_meta
,
624 librbd::UpdateWatchCtx
** update_watch_ctx
) {
625 expect_register_update_watcher(mock_local_image_ctx
, update_watch_ctx
, 123,
627 expect_register_update_watcher(mock_remote_image_ctx
, update_watch_ctx
, 234,
629 expect_load_image_meta(mock_image_meta
, false, 0);
630 expect_is_refresh_required(mock_local_image_ctx
, false);
631 expect_is_refresh_required(mock_remote_image_ctx
, false);
633 C_SaferCond init_ctx
;
634 mock_replayer
.init(&init_ctx
);
635 int r
= init_ctx
.wait();
640 return wait_for_notification(2);
643 int shut_down_entry_replayer(MockReplayer
& mock_replayer
,
644 MockThreads
& mock_threads
,
645 librbd::MockTestImageCtx
& mock_local_image_ctx
,
646 librbd::MockTestImageCtx
& mock_remote_image_ctx
) {
647 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, 0);
648 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
650 C_SaferCond shutdown_ctx
;
651 mock_replayer
.shut_down(&shutdown_ctx
);
652 return shutdown_ctx
.wait();
655 librbd::ImageCtx
* m_local_image_ctx
= nullptr;
656 librbd::ImageCtx
* m_remote_image_ctx
= nullptr;
658 PoolMetaCache m_pool_meta_cache
{g_ceph_context
};
660 ceph::mutex m_lock
= ceph::make_mutex(
661 "TestMockImageReplayerSnapshotReplayer");
662 ceph::condition_variable m_cond
;
663 uint32_t m_notifications
= 0;
666 TEST_F(TestMockImageReplayerSnapshotReplayer
, InitShutDown
) {
667 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
668 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
670 MockThreads
mock_threads(m_threads
);
671 expect_work_queue_repeatedly(mock_threads
);
673 MockReplayerListener mock_replayer_listener
;
674 expect_notification(mock_threads
, mock_replayer_listener
);
678 MockInstanceWatcher mock_instance_watcher
;
679 MockImageMeta mock_image_meta
;
680 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
681 mock_remote_image_ctx
,
683 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
684 "local mirror uuid", &m_pool_meta_cache
,
685 &mock_state_builder
, &mock_replayer_listener
};
686 m_pool_meta_cache
.set_remote_pool_meta(
687 m_remote_io_ctx
.get_id(),
688 {"remote mirror uuid", "remote mirror peer uuid"});
690 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
691 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
692 mock_local_image_ctx
,
693 mock_remote_image_ctx
,
694 mock_replayer_listener
,
697 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
698 mock_local_image_ctx
,
699 mock_remote_image_ctx
));
702 TEST_F(TestMockImageReplayerSnapshotReplayer
, SyncSnapshot
) {
703 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
704 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
706 // it should sync two snapshots and skip two (user and mirror w/o matching
708 mock_remote_image_ctx
.snap_info
= {
709 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
710 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
711 "", CEPH_NOSNAP
, true, 0, {}},
713 {2U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
715 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
716 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {""},
717 "", CEPH_NOSNAP
, true, 0, {}},
719 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
720 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
721 "", CEPH_NOSNAP
, true, 0, {}},
724 MockThreads
mock_threads(m_threads
);
725 expect_work_queue_repeatedly(mock_threads
);
727 MockReplayerListener mock_replayer_listener
;
728 expect_notification(mock_threads
, mock_replayer_listener
);
732 MockInstanceWatcher mock_instance_watcher
;
733 MockImageMeta mock_image_meta
;
734 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
735 mock_remote_image_ctx
,
737 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
738 "local mirror uuid", &m_pool_meta_cache
,
739 &mock_state_builder
, &mock_replayer_listener
};
740 m_pool_meta_cache
.set_remote_pool_meta(
741 m_remote_io_ctx
.get_id(),
742 {"remote mirror uuid", "remote mirror peer uuid"});
744 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
747 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
749 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
753 expect_load_image_meta(mock_image_meta
, false, 0);
754 expect_is_refresh_required(mock_local_image_ctx
, false);
755 expect_is_refresh_required(mock_remote_image_ctx
, false);
756 MockSnapshotCopyRequest mock_snapshot_copy_request
;
757 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
759 MockGetImageStateRequest mock_get_image_state_request
;
760 expect_get_image_state(mock_get_image_state_request
, 1, 0);
761 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
762 expect_create_non_primary_request(mock_create_non_primary_request
,
763 false, "remote mirror uuid", 1,
764 {{1, CEPH_NOSNAP
}}, 11, 0);
765 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
766 MockImageCopyRequest mock_image_copy_request
;
767 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
768 {{1, CEPH_NOSNAP
}}, 0);
769 MockApplyImageStateRequest mock_apply_state_request
;
770 expect_apply_image_state(mock_apply_state_request
, 0);
771 expect_mirror_image_snapshot_set_copy_progress(
772 mock_local_image_ctx
, 11, true, 0, 0);
773 expect_notify_update(mock_local_image_ctx
);
774 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
777 expect_load_image_meta(mock_image_meta
, false, 0);
778 expect_is_refresh_required(mock_local_image_ctx
, true);
780 mock_local_image_ctx
, {
781 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
782 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
783 1, true, 0, {{1, CEPH_NOSNAP
}}},
786 expect_is_refresh_required(mock_remote_image_ctx
, false);
787 expect_snapshot_copy(mock_snapshot_copy_request
, 1, 4, 11,
788 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP
}}, 0);
789 expect_get_image_state(mock_get_image_state_request
, 4, 0);
790 expect_create_non_primary_request(mock_create_non_primary_request
,
791 false, "remote mirror uuid", 4,
792 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP
}}, 14,
794 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
795 expect_image_copy(mock_image_copy_request
, 1, 4, 11, {},
796 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP
}}, 0);
797 expect_apply_image_state(mock_apply_state_request
, 0);
798 expect_mirror_image_snapshot_set_copy_progress(
799 mock_local_image_ctx
, 14, true, 0, 0);
800 expect_notify_update(mock_local_image_ctx
);
801 MockUnlinkPeerRequest mock_unlink_peer_request
;
802 expect_unlink_peer(mock_unlink_peer_request
, 1, "remote mirror peer uuid",
804 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
806 // prune non-primary snap1
807 expect_load_image_meta(mock_image_meta
, false, 0);
808 expect_is_refresh_required(mock_local_image_ctx
, true);
810 mock_local_image_ctx
, {
811 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
812 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
815 {12U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
817 {14U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
818 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
822 expect_is_refresh_required(mock_remote_image_ctx
, true);
824 mock_remote_image_ctx
, {
825 {2U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
827 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
828 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {""},
829 "", CEPH_NOSNAP
, true, 0, {}},
831 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
832 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
833 "", CEPH_NOSNAP
, true, 0, {}},
836 expect_prune_non_primary_snapshot(mock_local_image_ctx
, 11, 0);
839 expect_load_image_meta(mock_image_meta
, false, 0);
840 expect_is_refresh_required(mock_local_image_ctx
, true);
842 mock_local_image_ctx
, {
843 {14U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
844 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
848 expect_is_refresh_required(mock_remote_image_ctx
, false);
851 C_SaferCond init_ctx
;
852 mock_replayer
.init(&init_ctx
);
853 ASSERT_EQ(0, init_ctx
.wait());
855 // wait for sync to complete
856 ASSERT_EQ(0, wait_for_notification(4));
859 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
860 mock_local_image_ctx
,
861 mock_remote_image_ctx
));
864 TEST_F(TestMockImageReplayerSnapshotReplayer
, InterruptedSync
) {
865 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
866 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
868 MockThreads
mock_threads(m_threads
);
869 expect_work_queue_repeatedly(mock_threads
);
871 MockReplayerListener mock_replayer_listener
;
872 expect_notification(mock_threads
, mock_replayer_listener
);
876 MockInstanceWatcher mock_instance_watcher
;
877 MockImageMeta mock_image_meta
;
878 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
879 mock_remote_image_ctx
,
881 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
882 "local mirror uuid", &m_pool_meta_cache
,
883 &mock_state_builder
, &mock_replayer_listener
};
884 m_pool_meta_cache
.set_remote_pool_meta(
885 m_remote_io_ctx
.get_id(),
886 {"remote mirror uuid", "remote mirror peer uuid"});
888 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
889 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
890 mock_local_image_ctx
,
891 mock_remote_image_ctx
,
892 mock_replayer_listener
,
896 // inject a incomplete sync snapshot
897 mock_remote_image_ctx
.snap_info
= {
898 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
899 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
900 "", CEPH_NOSNAP
, true, 0, {}},
902 mock_local_image_ctx
.snap_info
= {
903 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
904 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
905 1, false, 123, {{1, CEPH_NOSNAP
}}},
909 expect_load_image_meta(mock_image_meta
, false, 0);
910 expect_is_refresh_required(mock_local_image_ctx
, false);
911 expect_is_refresh_required(mock_remote_image_ctx
, false);
912 MockGetImageStateRequest mock_get_image_state_request
;
913 expect_get_image_state(mock_get_image_state_request
, 11, 0);
914 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
915 MockImageCopyRequest mock_image_copy_request
;
916 expect_image_copy(mock_image_copy_request
, 0, 1, 0,
917 librbd::deep_copy::ObjectNumber
{123U},
918 {{1, CEPH_NOSNAP
}}, 0);
919 MockApplyImageStateRequest mock_apply_state_request
;
920 expect_apply_image_state(mock_apply_state_request
, 0);
921 expect_mirror_image_snapshot_set_copy_progress(
922 mock_local_image_ctx
, 11, true, 123, 0);
923 expect_notify_update(mock_local_image_ctx
);
924 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
927 expect_load_image_meta(mock_image_meta
, false, 0);
928 expect_is_refresh_required(mock_local_image_ctx
, true);
930 mock_local_image_ctx
, {
931 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
932 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
936 expect_is_refresh_required(mock_remote_image_ctx
, false);
939 update_watch_ctx
->handle_notify();
941 // wait for sync to complete
942 ASSERT_EQ(0, wait_for_notification(2));
944 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
945 mock_local_image_ctx
,
946 mock_remote_image_ctx
));
949 TEST_F(TestMockImageReplayerSnapshotReplayer
, RemoteImageDemoted
) {
950 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
951 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
953 MockThreads
mock_threads(m_threads
);
954 expect_work_queue_repeatedly(mock_threads
);
956 MockReplayerListener mock_replayer_listener
;
957 expect_notification(mock_threads
, mock_replayer_listener
);
961 MockInstanceWatcher mock_instance_watcher
;
962 MockImageMeta mock_image_meta
;
963 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
964 mock_remote_image_ctx
,
966 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
967 "local mirror uuid", &m_pool_meta_cache
,
968 &mock_state_builder
, &mock_replayer_listener
};
969 m_pool_meta_cache
.set_remote_pool_meta(
970 m_remote_io_ctx
.get_id(),
971 {"remote mirror uuid", "remote mirror peer uuid"});
973 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
974 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
975 mock_local_image_ctx
,
976 mock_remote_image_ctx
,
977 mock_replayer_listener
,
981 // inject a demotion snapshot
982 mock_remote_image_ctx
.snap_info
= {
983 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
984 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
,
985 {"remote mirror peer uuid"}, "", CEPH_NOSNAP
, true, 0, {}},
989 expect_load_image_meta(mock_image_meta
, false, 0);
990 expect_is_refresh_required(mock_local_image_ctx
, false);
991 expect_is_refresh_required(mock_remote_image_ctx
, false);
992 MockSnapshotCopyRequest mock_snapshot_copy_request
;
993 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
995 MockGetImageStateRequest mock_get_image_state_request
;
996 expect_get_image_state(mock_get_image_state_request
, 1, 0);
997 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
998 expect_create_non_primary_request(mock_create_non_primary_request
,
999 true, "remote mirror uuid", 1,
1000 {{1, CEPH_NOSNAP
}}, 11, 0);
1001 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1002 MockImageCopyRequest mock_image_copy_request
;
1003 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
1004 {{1, CEPH_NOSNAP
}}, 0);
1005 MockApplyImageStateRequest mock_apply_state_request
;
1006 expect_apply_image_state(mock_apply_state_request
, 0);
1007 expect_mirror_image_snapshot_set_copy_progress(
1008 mock_local_image_ctx
, 11, true, 0, 0);
1009 expect_notify_update(mock_local_image_ctx
);
1010 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
1013 expect_load_image_meta(mock_image_meta
, false, 0);
1014 expect_is_refresh_required(mock_local_image_ctx
, true);
1016 mock_local_image_ctx
, {
1017 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1018 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
1022 expect_is_refresh_required(mock_remote_image_ctx
, false);
1025 update_watch_ctx
->handle_notify();
1027 // wait for sync to complete and expect replay complete
1028 ASSERT_EQ(0, wait_for_notification(2));
1029 ASSERT_FALSE(mock_replayer
.is_replaying());
1031 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1032 mock_local_image_ctx
,
1033 mock_remote_image_ctx
));
1036 TEST_F(TestMockImageReplayerSnapshotReplayer
, LocalImagePromoted
) {
1037 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1038 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1040 MockThreads
mock_threads(m_threads
);
1041 expect_work_queue_repeatedly(mock_threads
);
1043 MockReplayerListener mock_replayer_listener
;
1044 expect_notification(mock_threads
, mock_replayer_listener
);
1048 MockInstanceWatcher mock_instance_watcher
;
1049 MockImageMeta mock_image_meta
;
1050 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1051 mock_remote_image_ctx
,
1053 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1054 "local mirror uuid", &m_pool_meta_cache
,
1055 &mock_state_builder
, &mock_replayer_listener
};
1056 m_pool_meta_cache
.set_remote_pool_meta(
1057 m_remote_io_ctx
.get_id(),
1058 {"remote mirror uuid", "remote mirror peer uuid"});
1060 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1061 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1062 mock_local_image_ctx
,
1063 mock_remote_image_ctx
,
1064 mock_replayer_listener
,
1066 &update_watch_ctx
));
1068 // inject a promotion snapshot
1069 mock_local_image_ctx
.snap_info
= {
1070 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1071 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
,
1072 {"remote mirror peer uuid"}, "", CEPH_NOSNAP
, true, 0, {}},
1076 expect_load_image_meta(mock_image_meta
, false, 0);
1077 expect_is_refresh_required(mock_local_image_ctx
, false);
1078 expect_is_refresh_required(mock_remote_image_ctx
, false);
1081 update_watch_ctx
->handle_notify();
1083 // wait for sync to complete and expect replay complete
1084 ASSERT_EQ(0, wait_for_notification(1));
1085 ASSERT_FALSE(mock_replayer
.is_replaying());
1087 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1088 mock_local_image_ctx
,
1089 mock_remote_image_ctx
));
1092 TEST_F(TestMockImageReplayerSnapshotReplayer
, ResyncRequested
) {
1093 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1094 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1096 MockThreads
mock_threads(m_threads
);
1097 expect_work_queue_repeatedly(mock_threads
);
1099 MockReplayerListener mock_replayer_listener
;
1100 expect_notification(mock_threads
, mock_replayer_listener
);
1104 MockInstanceWatcher mock_instance_watcher
;
1105 MockImageMeta mock_image_meta
;
1106 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1107 mock_remote_image_ctx
,
1109 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1110 "local mirror uuid", &m_pool_meta_cache
,
1111 &mock_state_builder
, &mock_replayer_listener
};
1112 m_pool_meta_cache
.set_remote_pool_meta(
1113 m_remote_io_ctx
.get_id(),
1114 {"remote mirror uuid", "remote mirror peer uuid"});
1116 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1117 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1118 mock_local_image_ctx
,
1119 mock_remote_image_ctx
,
1120 mock_replayer_listener
,
1122 &update_watch_ctx
));
1125 expect_load_image_meta(mock_image_meta
, true, 0);
1128 update_watch_ctx
->handle_notify();
1130 // wait for sync to complete and expect replay complete
1131 ASSERT_EQ(0, wait_for_notification(1));
1132 ASSERT_FALSE(mock_replayer
.is_replaying());
1134 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1135 mock_local_image_ctx
,
1136 mock_remote_image_ctx
));
1139 TEST_F(TestMockImageReplayerSnapshotReplayer
, RegisterLocalUpdateWatcherError
) {
1140 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1141 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1143 MockThreads
mock_threads(m_threads
);
1144 expect_work_queue_repeatedly(mock_threads
);
1148 MockInstanceWatcher mock_instance_watcher
;
1149 MockImageMeta mock_image_meta
;
1150 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1151 mock_remote_image_ctx
,
1153 MockReplayerListener mock_replayer_listener
;
1154 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1155 "local mirror uuid", &m_pool_meta_cache
,
1156 &mock_state_builder
, &mock_replayer_listener
};
1157 m_pool_meta_cache
.set_remote_pool_meta(
1158 m_remote_io_ctx
.get_id(),
1159 {"remote mirror uuid", "remote mirror peer uuid"});
1162 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1163 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
1167 C_SaferCond init_ctx
;
1168 mock_replayer
.init(&init_ctx
);
1169 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
1172 TEST_F(TestMockImageReplayerSnapshotReplayer
, RegisterRemoteUpdateWatcherError
) {
1173 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1174 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1176 MockThreads
mock_threads(m_threads
);
1177 expect_work_queue_repeatedly(mock_threads
);
1181 MockInstanceWatcher mock_instance_watcher
;
1182 MockImageMeta mock_image_meta
;
1183 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1184 mock_remote_image_ctx
,
1186 MockReplayerListener mock_replayer_listener
;
1187 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1188 "local mirror uuid", &m_pool_meta_cache
,
1189 &mock_state_builder
, &mock_replayer_listener
};
1190 m_pool_meta_cache
.set_remote_pool_meta(
1191 m_remote_io_ctx
.get_id(),
1192 {"remote mirror uuid", "remote mirror peer uuid"});
1195 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1196 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
1198 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
1201 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
1204 C_SaferCond init_ctx
;
1205 mock_replayer
.init(&init_ctx
);
1206 ASSERT_EQ(-EINVAL
, init_ctx
.wait());
1209 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnregisterRemoteUpdateWatcherError
) {
1210 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1211 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1213 MockThreads
mock_threads(m_threads
);
1214 expect_work_queue_repeatedly(mock_threads
);
1216 MockReplayerListener mock_replayer_listener
;
1217 expect_notification(mock_threads
, mock_replayer_listener
);
1221 MockInstanceWatcher mock_instance_watcher
;
1222 MockImageMeta mock_image_meta
;
1223 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1224 mock_remote_image_ctx
,
1226 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1227 "local mirror uuid", &m_pool_meta_cache
,
1228 &mock_state_builder
, &mock_replayer_listener
};
1229 m_pool_meta_cache
.set_remote_pool_meta(
1230 m_remote_io_ctx
.get_id(),
1231 {"remote mirror uuid", "remote mirror peer uuid"});
1233 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1234 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1235 mock_local_image_ctx
,
1236 mock_remote_image_ctx
,
1237 mock_replayer_listener
,
1239 &update_watch_ctx
));
1243 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, -EINVAL
);
1244 expect_unregister_update_watcher(mock_local_image_ctx
, 123, 0);
1246 C_SaferCond shutdown_ctx
;
1247 mock_replayer
.shut_down(&shutdown_ctx
);
1248 ASSERT_EQ(-EINVAL
, shutdown_ctx
.wait());
1251 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnregisterLocalUpdateWatcherError
) {
1252 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1253 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1255 MockThreads
mock_threads(m_threads
);
1256 expect_work_queue_repeatedly(mock_threads
);
1258 MockReplayerListener mock_replayer_listener
;
1259 expect_notification(mock_threads
, mock_replayer_listener
);
1263 MockInstanceWatcher mock_instance_watcher
;
1264 MockImageMeta mock_image_meta
;
1265 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1266 mock_remote_image_ctx
,
1268 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1269 "local mirror uuid", &m_pool_meta_cache
,
1270 &mock_state_builder
, &mock_replayer_listener
};
1271 m_pool_meta_cache
.set_remote_pool_meta(
1272 m_remote_io_ctx
.get_id(),
1273 {"remote mirror uuid", "remote mirror peer uuid"});
1275 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1276 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1277 mock_local_image_ctx
,
1278 mock_remote_image_ctx
,
1279 mock_replayer_listener
,
1281 &update_watch_ctx
));
1285 expect_unregister_update_watcher(mock_remote_image_ctx
, 234, 0);
1286 expect_unregister_update_watcher(mock_local_image_ctx
, 123, -EINVAL
);
1288 C_SaferCond shutdown_ctx
;
1289 mock_replayer
.shut_down(&shutdown_ctx
);
1290 ASSERT_EQ(-EINVAL
, shutdown_ctx
.wait());
1293 TEST_F(TestMockImageReplayerSnapshotReplayer
, LoadImageMetaError
) {
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, -EINVAL
);
1329 update_watch_ctx
->handle_notify();
1331 // wait for sync to complete and expect replay complete
1332 ASSERT_EQ(0, wait_for_notification(1));
1333 ASSERT_FALSE(mock_replayer
.is_replaying());
1334 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1336 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1337 mock_local_image_ctx
,
1338 mock_remote_image_ctx
));
1341 TEST_F(TestMockImageReplayerSnapshotReplayer
, RefreshLocalImageError
) {
1342 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1343 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1345 MockThreads
mock_threads(m_threads
);
1346 expect_work_queue_repeatedly(mock_threads
);
1348 MockReplayerListener mock_replayer_listener
;
1349 expect_notification(mock_threads
, mock_replayer_listener
);
1353 MockInstanceWatcher mock_instance_watcher
;
1354 MockImageMeta mock_image_meta
;
1355 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1356 mock_remote_image_ctx
,
1358 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1359 "local mirror uuid", &m_pool_meta_cache
,
1360 &mock_state_builder
, &mock_replayer_listener
};
1361 m_pool_meta_cache
.set_remote_pool_meta(
1362 m_remote_io_ctx
.get_id(),
1363 {"remote mirror uuid", "remote mirror peer uuid"});
1365 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1366 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1367 mock_local_image_ctx
,
1368 mock_remote_image_ctx
,
1369 mock_replayer_listener
,
1371 &update_watch_ctx
));
1374 expect_load_image_meta(mock_image_meta
, false, 0);
1375 expect_is_refresh_required(mock_local_image_ctx
, true);
1376 expect_refresh(mock_local_image_ctx
, {}, -EINVAL
);
1379 update_watch_ctx
->handle_notify();
1381 // wait for sync to complete and expect replay complete
1382 ASSERT_EQ(0, wait_for_notification(1));
1383 ASSERT_FALSE(mock_replayer
.is_replaying());
1384 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1386 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1387 mock_local_image_ctx
,
1388 mock_remote_image_ctx
));
1391 TEST_F(TestMockImageReplayerSnapshotReplayer
, RefreshRemoteImageError
) {
1392 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1393 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1395 MockThreads
mock_threads(m_threads
);
1396 expect_work_queue_repeatedly(mock_threads
);
1398 MockReplayerListener mock_replayer_listener
;
1399 expect_notification(mock_threads
, mock_replayer_listener
);
1403 MockInstanceWatcher mock_instance_watcher
;
1404 MockImageMeta mock_image_meta
;
1405 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1406 mock_remote_image_ctx
,
1408 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1409 "local mirror uuid", &m_pool_meta_cache
,
1410 &mock_state_builder
, &mock_replayer_listener
};
1411 m_pool_meta_cache
.set_remote_pool_meta(
1412 m_remote_io_ctx
.get_id(),
1413 {"remote mirror uuid", "remote mirror peer uuid"});
1415 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1416 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1417 mock_local_image_ctx
,
1418 mock_remote_image_ctx
,
1419 mock_replayer_listener
,
1421 &update_watch_ctx
));
1424 expect_load_image_meta(mock_image_meta
, false, 0);
1425 expect_is_refresh_required(mock_local_image_ctx
, false);
1426 expect_is_refresh_required(mock_remote_image_ctx
, true);
1427 expect_refresh(mock_remote_image_ctx
, {}, -EINVAL
);
1430 update_watch_ctx
->handle_notify();
1432 // wait for sync to complete and expect replay complete
1433 ASSERT_EQ(0, wait_for_notification(1));
1434 ASSERT_FALSE(mock_replayer
.is_replaying());
1435 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1437 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1438 mock_local_image_ctx
,
1439 mock_remote_image_ctx
));
1442 TEST_F(TestMockImageReplayerSnapshotReplayer
, CopySnapshotsError
) {
1443 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1444 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1446 MockThreads
mock_threads(m_threads
);
1447 expect_work_queue_repeatedly(mock_threads
);
1449 MockReplayerListener mock_replayer_listener
;
1450 expect_notification(mock_threads
, mock_replayer_listener
);
1454 MockInstanceWatcher mock_instance_watcher
;
1455 MockImageMeta mock_image_meta
;
1456 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1457 mock_remote_image_ctx
,
1459 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1460 "local mirror uuid", &m_pool_meta_cache
,
1461 &mock_state_builder
, &mock_replayer_listener
};
1462 m_pool_meta_cache
.set_remote_pool_meta(
1463 m_remote_io_ctx
.get_id(),
1464 {"remote mirror uuid", "remote mirror peer uuid"});
1466 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1467 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1468 mock_local_image_ctx
,
1469 mock_remote_image_ctx
,
1470 mock_replayer_listener
,
1472 &update_watch_ctx
));
1475 mock_remote_image_ctx
.snap_info
= {
1476 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1477 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1478 CEPH_NOSNAP
, true, 0, {}},
1482 expect_load_image_meta(mock_image_meta
, false, 0);
1483 expect_is_refresh_required(mock_local_image_ctx
, false);
1484 expect_is_refresh_required(mock_remote_image_ctx
, false);
1485 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1486 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1490 update_watch_ctx
->handle_notify();
1492 // wait for sync to complete and expect replay complete
1493 ASSERT_EQ(0, wait_for_notification(1));
1494 ASSERT_FALSE(mock_replayer
.is_replaying());
1495 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1497 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1498 mock_local_image_ctx
,
1499 mock_remote_image_ctx
));
1502 TEST_F(TestMockImageReplayerSnapshotReplayer
, GetImageStateError
) {
1503 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1504 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1506 MockThreads
mock_threads(m_threads
);
1507 expect_work_queue_repeatedly(mock_threads
);
1509 MockReplayerListener mock_replayer_listener
;
1510 expect_notification(mock_threads
, mock_replayer_listener
);
1514 MockInstanceWatcher mock_instance_watcher
;
1515 MockImageMeta mock_image_meta
;
1516 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1517 mock_remote_image_ctx
,
1519 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1520 "local mirror uuid", &m_pool_meta_cache
,
1521 &mock_state_builder
, &mock_replayer_listener
};
1522 m_pool_meta_cache
.set_remote_pool_meta(
1523 m_remote_io_ctx
.get_id(),
1524 {"remote mirror uuid", "remote mirror peer uuid"});
1526 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1527 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1528 mock_local_image_ctx
,
1529 mock_remote_image_ctx
,
1530 mock_replayer_listener
,
1532 &update_watch_ctx
));
1535 mock_remote_image_ctx
.snap_info
= {
1536 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1537 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1538 CEPH_NOSNAP
, true, 0, {}},
1542 expect_load_image_meta(mock_image_meta
, false, 0);
1543 expect_is_refresh_required(mock_local_image_ctx
, false);
1544 expect_is_refresh_required(mock_remote_image_ctx
, false);
1545 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1546 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1548 MockGetImageStateRequest mock_get_image_state_request
;
1549 expect_get_image_state(mock_get_image_state_request
, 1, -EINVAL
);
1552 update_watch_ctx
->handle_notify();
1554 // wait for sync to complete and expect replay complete
1555 ASSERT_EQ(0, wait_for_notification(1));
1556 ASSERT_FALSE(mock_replayer
.is_replaying());
1557 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1559 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1560 mock_local_image_ctx
,
1561 mock_remote_image_ctx
));
1564 TEST_F(TestMockImageReplayerSnapshotReplayer
, CreateNonPrimarySnapshotError
) {
1565 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1566 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1568 MockThreads
mock_threads(m_threads
);
1569 expect_work_queue_repeatedly(mock_threads
);
1571 MockReplayerListener mock_replayer_listener
;
1572 expect_notification(mock_threads
, mock_replayer_listener
);
1576 MockInstanceWatcher mock_instance_watcher
;
1577 MockImageMeta mock_image_meta
;
1578 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1579 mock_remote_image_ctx
,
1581 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1582 "local mirror uuid", &m_pool_meta_cache
,
1583 &mock_state_builder
, &mock_replayer_listener
};
1584 m_pool_meta_cache
.set_remote_pool_meta(
1585 m_remote_io_ctx
.get_id(),
1586 {"remote mirror uuid", "remote mirror peer uuid"});
1588 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1589 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1590 mock_local_image_ctx
,
1591 mock_remote_image_ctx
,
1592 mock_replayer_listener
,
1594 &update_watch_ctx
));
1597 mock_remote_image_ctx
.snap_info
= {
1598 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1599 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1600 CEPH_NOSNAP
, true, 0, {}},
1604 expect_load_image_meta(mock_image_meta
, false, 0);
1605 expect_is_refresh_required(mock_local_image_ctx
, false);
1606 expect_is_refresh_required(mock_remote_image_ctx
, false);
1607 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1608 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1610 MockGetImageStateRequest mock_get_image_state_request
;
1611 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1612 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1613 expect_create_non_primary_request(mock_create_non_primary_request
,
1614 false, "remote mirror uuid", 1,
1615 {{1, CEPH_NOSNAP
}}, 11, -EINVAL
);
1618 update_watch_ctx
->handle_notify();
1620 // wait for sync to complete and expect replay complete
1621 ASSERT_EQ(0, wait_for_notification(1));
1622 ASSERT_FALSE(mock_replayer
.is_replaying());
1623 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1625 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1626 mock_local_image_ctx
,
1627 mock_remote_image_ctx
));
1630 TEST_F(TestMockImageReplayerSnapshotReplayer
, RequestSyncError
) {
1631 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1632 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1634 MockThreads
mock_threads(m_threads
);
1635 expect_work_queue_repeatedly(mock_threads
);
1637 MockReplayerListener mock_replayer_listener
;
1638 expect_notification(mock_threads
, mock_replayer_listener
);
1642 MockInstanceWatcher mock_instance_watcher
;
1643 MockImageMeta mock_image_meta
;
1644 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1645 mock_remote_image_ctx
,
1647 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1648 "local mirror uuid", &m_pool_meta_cache
,
1649 &mock_state_builder
, &mock_replayer_listener
};
1650 m_pool_meta_cache
.set_remote_pool_meta(
1651 m_remote_io_ctx
.get_id(),
1652 {"remote mirror uuid", "remote mirror peer uuid"});
1654 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1655 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1656 mock_local_image_ctx
,
1657 mock_remote_image_ctx
,
1658 mock_replayer_listener
,
1660 &update_watch_ctx
));
1663 mock_remote_image_ctx
.snap_info
= {
1664 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1665 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1666 CEPH_NOSNAP
, true, 0, {}},
1670 expect_load_image_meta(mock_image_meta
, false, 0);
1671 expect_is_refresh_required(mock_local_image_ctx
, false);
1672 expect_is_refresh_required(mock_remote_image_ctx
, false);
1673 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1674 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1676 MockGetImageStateRequest mock_get_image_state_request
;
1677 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1678 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1679 expect_create_non_primary_request(mock_create_non_primary_request
,
1680 false, "remote mirror uuid", 1,
1681 {{1, CEPH_NOSNAP
}}, 11, 0);
1682 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
,
1686 update_watch_ctx
->handle_notify();
1688 // wait for sync to complete and expect replay complete
1689 ASSERT_EQ(0, wait_for_notification(1));
1690 ASSERT_FALSE(mock_replayer
.is_replaying());
1691 ASSERT_EQ(-ECANCELED
, mock_replayer
.get_error_code());
1693 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1694 mock_local_image_ctx
,
1695 mock_remote_image_ctx
));
1699 TEST_F(TestMockImageReplayerSnapshotReplayer
, CopyImageError
) {
1700 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1701 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1703 MockThreads
mock_threads(m_threads
);
1704 expect_work_queue_repeatedly(mock_threads
);
1706 MockReplayerListener mock_replayer_listener
;
1707 expect_notification(mock_threads
, mock_replayer_listener
);
1711 MockInstanceWatcher mock_instance_watcher
;
1712 MockImageMeta mock_image_meta
;
1713 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1714 mock_remote_image_ctx
,
1716 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1717 "local mirror uuid", &m_pool_meta_cache
,
1718 &mock_state_builder
, &mock_replayer_listener
};
1719 m_pool_meta_cache
.set_remote_pool_meta(
1720 m_remote_io_ctx
.get_id(),
1721 {"remote mirror uuid", "remote mirror peer uuid"});
1723 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1724 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1725 mock_local_image_ctx
,
1726 mock_remote_image_ctx
,
1727 mock_replayer_listener
,
1729 &update_watch_ctx
));
1732 mock_remote_image_ctx
.snap_info
= {
1733 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1734 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1735 CEPH_NOSNAP
,true, 0, {}},
1739 expect_load_image_meta(mock_image_meta
, false, 0);
1740 expect_is_refresh_required(mock_local_image_ctx
, false);
1741 expect_is_refresh_required(mock_remote_image_ctx
, false);
1742 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1743 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1745 MockGetImageStateRequest mock_get_image_state_request
;
1746 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1747 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1748 expect_create_non_primary_request(mock_create_non_primary_request
,
1749 false, "remote mirror uuid", 1,
1750 {{1, CEPH_NOSNAP
}}, 11, 0);
1751 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1752 MockImageCopyRequest mock_image_copy_request
;
1753 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
1754 {{1, CEPH_NOSNAP
}}, -EINVAL
);
1755 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
1758 update_watch_ctx
->handle_notify();
1760 // wait for sync to complete and expect replay complete
1761 ASSERT_EQ(0, wait_for_notification(1));
1762 ASSERT_FALSE(mock_replayer
.is_replaying());
1763 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1765 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1766 mock_local_image_ctx
,
1767 mock_remote_image_ctx
));
1770 TEST_F(TestMockImageReplayerSnapshotReplayer
, UpdateNonPrimarySnapshotError
) {
1771 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1772 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1774 MockThreads
mock_threads(m_threads
);
1775 expect_work_queue_repeatedly(mock_threads
);
1777 MockReplayerListener mock_replayer_listener
;
1778 expect_notification(mock_threads
, mock_replayer_listener
);
1782 MockInstanceWatcher mock_instance_watcher
;
1783 MockImageMeta mock_image_meta
;
1784 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1785 mock_remote_image_ctx
,
1787 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1788 "local mirror uuid", &m_pool_meta_cache
,
1789 &mock_state_builder
, &mock_replayer_listener
};
1790 m_pool_meta_cache
.set_remote_pool_meta(
1791 m_remote_io_ctx
.get_id(),
1792 {"remote mirror uuid", "remote mirror peer uuid"});
1794 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1795 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1796 mock_local_image_ctx
,
1797 mock_remote_image_ctx
,
1798 mock_replayer_listener
,
1800 &update_watch_ctx
));
1803 mock_remote_image_ctx
.snap_info
= {
1804 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1805 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1806 CEPH_NOSNAP
, true, 0, {}},
1810 expect_load_image_meta(mock_image_meta
, false, 0);
1811 expect_is_refresh_required(mock_local_image_ctx
, false);
1812 expect_is_refresh_required(mock_remote_image_ctx
, false);
1813 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1814 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
1816 MockGetImageStateRequest mock_get_image_state_request
;
1817 expect_get_image_state(mock_get_image_state_request
, 1, 0);
1818 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1819 expect_create_non_primary_request(mock_create_non_primary_request
,
1820 false, "remote mirror uuid", 1,
1821 {{1, CEPH_NOSNAP
}}, 11, 0);
1822 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1823 MockImageCopyRequest mock_image_copy_request
;
1824 expect_image_copy(mock_image_copy_request
, 0, 1, 0, {},
1825 {{1, CEPH_NOSNAP
}}, 0);
1826 MockApplyImageStateRequest mock_apply_state_request
;
1827 expect_apply_image_state(mock_apply_state_request
, 0);
1828 expect_mirror_image_snapshot_set_copy_progress(
1829 mock_local_image_ctx
, 11, true, 0, -EINVAL
);
1830 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
1833 update_watch_ctx
->handle_notify();
1835 // wait for sync to complete and expect replay complete
1836 ASSERT_EQ(0, wait_for_notification(1));
1837 ASSERT_FALSE(mock_replayer
.is_replaying());
1838 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1840 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1841 mock_local_image_ctx
,
1842 mock_remote_image_ctx
));
1845 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnlinkPeerError
) {
1846 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1847 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1849 MockThreads
mock_threads(m_threads
);
1850 expect_work_queue_repeatedly(mock_threads
);
1852 MockReplayerListener mock_replayer_listener
;
1853 expect_notification(mock_threads
, mock_replayer_listener
);
1857 MockInstanceWatcher mock_instance_watcher
;
1858 MockImageMeta mock_image_meta
;
1859 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1860 mock_remote_image_ctx
,
1862 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1863 "local mirror uuid", &m_pool_meta_cache
,
1864 &mock_state_builder
, &mock_replayer_listener
};
1865 m_pool_meta_cache
.set_remote_pool_meta(
1866 m_remote_io_ctx
.get_id(),
1867 {"remote mirror uuid", "remote mirror peer uuid"});
1869 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1870 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1871 mock_local_image_ctx
,
1872 mock_remote_image_ctx
,
1873 mock_replayer_listener
,
1875 &update_watch_ctx
));
1878 mock_remote_image_ctx
.snap_info
= {
1879 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1880 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"}, "",
1881 CEPH_NOSNAP
, true, 0, {}},
1883 {2U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
1884 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
1885 "", CEPH_NOSNAP
, true, 0, {}},
1887 mock_local_image_ctx
.snap_info
= {
1888 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1889 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
1894 expect_load_image_meta(mock_image_meta
, false, 0);
1895 expect_is_refresh_required(mock_local_image_ctx
, false);
1896 expect_is_refresh_required(mock_remote_image_ctx
, false);
1897 MockSnapshotCopyRequest mock_snapshot_copy_request
;
1898 expect_snapshot_copy(mock_snapshot_copy_request
, 1, 2, 11, {{2, CEPH_NOSNAP
}},
1900 MockGetImageStateRequest mock_get_image_state_request
;
1901 expect_get_image_state(mock_get_image_state_request
, 2, 0);
1902 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
1903 expect_create_non_primary_request(mock_create_non_primary_request
,
1904 false, "remote mirror uuid", 2,
1905 {{2, CEPH_NOSNAP
}}, 12, 0);
1906 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
1907 MockImageCopyRequest mock_image_copy_request
;
1908 expect_image_copy(mock_image_copy_request
, 1, 2, 11, {},
1909 {{2, CEPH_NOSNAP
}}, 0);
1910 MockApplyImageStateRequest mock_apply_state_request
;
1911 expect_apply_image_state(mock_apply_state_request
, 0);
1912 expect_mirror_image_snapshot_set_copy_progress(
1913 mock_local_image_ctx
, 12, true, 0, 0);
1914 expect_notify_update(mock_local_image_ctx
);
1915 MockUnlinkPeerRequest mock_unlink_peer_request
;
1916 expect_unlink_peer(mock_unlink_peer_request
, 1, "remote mirror peer uuid",
1918 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
1921 update_watch_ctx
->handle_notify();
1923 // wait for sync to complete and expect replay complete
1924 ASSERT_EQ(0, wait_for_notification(1));
1925 ASSERT_FALSE(mock_replayer
.is_replaying());
1926 ASSERT_EQ(-EINVAL
, mock_replayer
.get_error_code());
1928 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1929 mock_local_image_ctx
,
1930 mock_remote_image_ctx
));
1933 TEST_F(TestMockImageReplayerSnapshotReplayer
, SplitBrain
) {
1934 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1935 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
1937 MockThreads
mock_threads(m_threads
);
1938 expect_work_queue_repeatedly(mock_threads
);
1940 MockReplayerListener mock_replayer_listener
;
1941 expect_notification(mock_threads
, mock_replayer_listener
);
1945 MockInstanceWatcher mock_instance_watcher
;
1946 MockImageMeta mock_image_meta
;
1947 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
1948 mock_remote_image_ctx
,
1950 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
1951 "local mirror uuid", &m_pool_meta_cache
,
1952 &mock_state_builder
, &mock_replayer_listener
};
1953 m_pool_meta_cache
.set_remote_pool_meta(
1954 m_remote_io_ctx
.get_id(),
1955 {"remote mirror uuid", "remote mirror peer uuid"});
1957 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
1958 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
1959 mock_local_image_ctx
,
1960 mock_remote_image_ctx
,
1961 mock_replayer_listener
,
1963 &update_watch_ctx
));
1965 // inject a primary demote to local image
1966 mock_remote_image_ctx
.snap_info
= {
1967 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1968 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
1969 "", CEPH_NOSNAP
, true, 0, {}},
1971 mock_local_image_ctx
.snap_info
= {
1972 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
1973 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", CEPH_NOSNAP
,
1977 // detect split-brain
1978 expect_load_image_meta(mock_image_meta
, false, 0);
1979 expect_is_refresh_required(mock_local_image_ctx
, false);
1980 expect_is_refresh_required(mock_remote_image_ctx
, false);
1983 update_watch_ctx
->handle_notify();
1985 // wait for sync to complete and expect replay complete
1986 ASSERT_EQ(0, wait_for_notification(1));
1987 ASSERT_FALSE(mock_replayer
.is_replaying());
1988 ASSERT_EQ(-EEXIST
, mock_replayer
.get_error_code());
1989 ASSERT_EQ(std::string
{"split-brain"}, mock_replayer
.get_error_description());
1991 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
1992 mock_local_image_ctx
,
1993 mock_remote_image_ctx
));
1996 TEST_F(TestMockImageReplayerSnapshotReplayer
, RemoteFailover
) {
1997 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
1998 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2000 MockThreads
mock_threads(m_threads
);
2001 expect_work_queue_repeatedly(mock_threads
);
2003 MockReplayerListener mock_replayer_listener
;
2004 expect_notification(mock_threads
, mock_replayer_listener
);
2008 MockInstanceWatcher mock_instance_watcher
;
2009 MockImageMeta mock_image_meta
;
2010 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2011 mock_remote_image_ctx
,
2013 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2014 "local mirror uuid", &m_pool_meta_cache
,
2015 &mock_state_builder
, &mock_replayer_listener
};
2016 m_pool_meta_cache
.set_remote_pool_meta(
2017 m_remote_io_ctx
.get_id(),
2018 {"remote mirror uuid", "remote mirror peer uuid"});
2020 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2021 ASSERT_EQ(0, init_entry_replayer(mock_replayer
, mock_threads
,
2022 mock_local_image_ctx
,
2023 mock_remote_image_ctx
,
2024 mock_replayer_listener
,
2026 &update_watch_ctx
));
2028 // inject a primary demote to local image
2029 mock_remote_image_ctx
.snap_info
= {
2030 {1U, librbd::SnapInfo
{"snap1", cls::rbd::UserSnapshotNamespace
{},
2032 {2U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2033 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED
,
2034 {"remote mirror peer uuid"}, "local mirror uuid", 12U, true, 0, {}},
2036 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2037 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2038 "", CEPH_NOSNAP
, true, 0, {}},
2040 mock_local_image_ctx
.snap_ids
= {
2041 {{cls::rbd::UserSnapshotNamespace
{}, "snap1"}, 11},
2042 {{cls::rbd::MirrorSnapshotNamespace
{}, "snap2"}, 12}};
2043 mock_local_image_ctx
.snap_info
= {
2044 {11U, librbd::SnapInfo
{"snap1", cls::rbd::UserSnapshotNamespace
{},
2046 {12U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2047 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", CEPH_NOSNAP
,
2051 // attach to promoted remote image
2052 expect_load_image_meta(mock_image_meta
, false, 0);
2053 expect_is_refresh_required(mock_local_image_ctx
, false);
2054 expect_is_refresh_required(mock_remote_image_ctx
, false);
2055 MockSnapshotCopyRequest mock_snapshot_copy_request
;
2056 expect_snapshot_copy(mock_snapshot_copy_request
, 2, 3, 12,
2057 {{2, 12}, {3, CEPH_NOSNAP
}}, 0);
2058 MockGetImageStateRequest mock_get_image_state_request
;
2059 expect_get_image_state(mock_get_image_state_request
, 3, 0);
2060 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
2061 expect_create_non_primary_request(mock_create_non_primary_request
,
2062 false, "remote mirror uuid", 3,
2063 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP
}}, 13,
2065 expect_notify_sync_request(mock_instance_watcher
, mock_local_image_ctx
.id
, 0);
2066 MockImageCopyRequest mock_image_copy_request
;
2067 expect_image_copy(mock_image_copy_request
, 2, 3, 12, {},
2068 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP
}}, 0);
2069 MockApplyImageStateRequest mock_apply_state_request
;
2070 expect_apply_image_state(mock_apply_state_request
, 0);
2071 expect_mirror_image_snapshot_set_copy_progress(
2072 mock_local_image_ctx
, 13, true, 0, 0);
2073 expect_notify_update(mock_local_image_ctx
);
2074 MockUnlinkPeerRequest mock_unlink_peer_request
;
2075 expect_unlink_peer(mock_unlink_peer_request
, 2, "remote mirror peer uuid", 0);
2076 expect_notify_sync_complete(mock_instance_watcher
, mock_local_image_ctx
.id
);
2079 expect_load_image_meta(mock_image_meta
, false, 0);
2080 expect_is_refresh_required(mock_local_image_ctx
, true);
2082 mock_local_image_ctx
, {
2083 {11U, librbd::SnapInfo
{"snap1", cls::rbd::UserSnapshotNamespace
{},
2085 {12U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2086 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", CEPH_NOSNAP
,
2089 {13U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2090 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {},
2091 "remote mirror uuid", 3, true, 0,
2092 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP
}}},
2095 expect_is_refresh_required(mock_remote_image_ctx
, true);
2097 mock_remote_image_ctx
, {
2098 {1U, librbd::SnapInfo
{"snap1", cls::rbd::UserSnapshotNamespace
{},
2100 {2U, librbd::SnapInfo
{"snap2", cls::rbd::MirrorSnapshotNamespace
{
2101 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED
,
2102 {"remote mirror peer uuid"}, "local mirror uuid", 12U, true, 0, {}},
2104 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2105 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {}, "", CEPH_NOSNAP
, true, 0,
2111 update_watch_ctx
->handle_notify();
2113 // wait for sync to complete and expect replay complete
2114 ASSERT_EQ(0, wait_for_notification(2));
2115 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2116 mock_local_image_ctx
,
2117 mock_remote_image_ctx
));
2120 TEST_F(TestMockImageReplayerSnapshotReplayer
, UnlinkRemoteSnapshot
) {
2121 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
2122 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2124 // it should attempt to unlink from remote snap1 since we don't need it
2126 mock_local_image_ctx
.snap_info
= {
2127 {14U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
2128 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
2131 mock_remote_image_ctx
.snap_info
= {
2132 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2133 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2134 "", CEPH_NOSNAP
, true, 0, {}},
2136 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
2137 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2138 "", CEPH_NOSNAP
, true, 0, {}},
2141 MockThreads
mock_threads(m_threads
);
2142 expect_work_queue_repeatedly(mock_threads
);
2144 MockReplayerListener mock_replayer_listener
;
2145 expect_notification(mock_threads
, mock_replayer_listener
);
2149 MockInstanceWatcher mock_instance_watcher
;
2150 MockImageMeta mock_image_meta
;
2151 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2152 mock_remote_image_ctx
,
2154 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2155 "local mirror uuid", &m_pool_meta_cache
,
2156 &mock_state_builder
, &mock_replayer_listener
};
2157 m_pool_meta_cache
.set_remote_pool_meta(
2158 m_remote_io_ctx
.get_id(),
2159 {"remote mirror uuid", "remote mirror peer uuid"});
2161 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2164 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
2166 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
2170 expect_load_image_meta(mock_image_meta
, false, 0);
2171 expect_is_refresh_required(mock_local_image_ctx
, false);
2172 expect_is_refresh_required(mock_remote_image_ctx
, false);
2173 MockUnlinkPeerRequest mock_unlink_peer_request
;
2174 expect_unlink_peer(mock_unlink_peer_request
, 1, "remote mirror peer uuid",
2178 expect_load_image_meta(mock_image_meta
, false, 0);
2179 expect_is_refresh_required(mock_local_image_ctx
, false);
2180 expect_is_refresh_required(mock_remote_image_ctx
, true);
2182 mock_remote_image_ctx
, {
2183 {2U, librbd::SnapInfo
{"snap2", cls::rbd::UserSnapshotNamespace
{},
2185 {3U, librbd::SnapInfo
{"snap3", cls::rbd::MirrorSnapshotNamespace
{
2186 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {""},
2187 "", CEPH_NOSNAP
, true, 0, {}},
2189 {4U, librbd::SnapInfo
{"snap4", cls::rbd::MirrorSnapshotNamespace
{
2190 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2191 "", CEPH_NOSNAP
, true, 0, {}},
2196 C_SaferCond init_ctx
;
2197 mock_replayer
.init(&init_ctx
);
2198 ASSERT_EQ(0, init_ctx
.wait());
2200 // wait for sync to complete
2201 ASSERT_EQ(0, wait_for_notification(3));
2204 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2205 mock_local_image_ctx
,
2206 mock_remote_image_ctx
));
2209 TEST_F(TestMockImageReplayerSnapshotReplayer
, SkipImageSync
) {
2210 librbd::MockTestImageCtx mock_local_image_ctx
{*m_local_image_ctx
};
2211 librbd::MockTestImageCtx mock_remote_image_ctx
{*m_remote_image_ctx
};
2213 mock_remote_image_ctx
.snap_info
= {
2214 {1U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2215 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"remote mirror peer uuid"},
2216 "", 0U, true, 0, {}},
2219 MockThreads
mock_threads(m_threads
);
2220 expect_work_queue_repeatedly(mock_threads
);
2222 MockReplayerListener mock_replayer_listener
;
2223 expect_notification(mock_threads
, mock_replayer_listener
);
2227 MockInstanceWatcher mock_instance_watcher
;
2228 MockImageMeta mock_image_meta
;
2229 MockStateBuilder
mock_state_builder(mock_local_image_ctx
,
2230 mock_remote_image_ctx
,
2232 MockReplayer mock_replayer
{&mock_threads
, &mock_instance_watcher
,
2233 "local mirror uuid", &m_pool_meta_cache
,
2234 &mock_state_builder
, &mock_replayer_listener
};
2235 m_pool_meta_cache
.set_remote_pool_meta(
2236 m_remote_io_ctx
.get_id(),
2237 {"remote mirror uuid", "remote mirror peer uuid"});
2239 librbd::UpdateWatchCtx
* update_watch_ctx
= nullptr;
2242 expect_register_update_watcher(mock_local_image_ctx
, &update_watch_ctx
, 123,
2244 expect_register_update_watcher(mock_remote_image_ctx
, &update_watch_ctx
, 234,
2248 expect_load_image_meta(mock_image_meta
, false, 0);
2249 expect_is_refresh_required(mock_local_image_ctx
, false);
2250 expect_is_refresh_required(mock_remote_image_ctx
, false);
2251 MockSnapshotCopyRequest mock_snapshot_copy_request
;
2252 expect_snapshot_copy(mock_snapshot_copy_request
, 0, 1, 0, {{1, CEPH_NOSNAP
}},
2254 MockGetImageStateRequest mock_get_image_state_request
;
2255 expect_get_image_state(mock_get_image_state_request
, 1, 0);
2256 MockCreateNonPrimaryRequest mock_create_non_primary_request
;
2257 expect_create_non_primary_request(mock_create_non_primary_request
,
2258 false, "remote mirror uuid", 1,
2259 {{1, CEPH_NOSNAP
}}, 11, 0);
2260 MockApplyImageStateRequest mock_apply_state_request
;
2261 expect_apply_image_state(mock_apply_state_request
, 0);
2262 expect_mirror_image_snapshot_set_copy_progress(
2263 mock_local_image_ctx
, 11, true, 0, 0);
2264 expect_notify_update(mock_local_image_ctx
);
2267 expect_load_image_meta(mock_image_meta
, false, 0);
2268 expect_is_refresh_required(mock_local_image_ctx
, true);
2270 mock_local_image_ctx
, {
2271 {11U, librbd::SnapInfo
{"snap1", cls::rbd::MirrorSnapshotNamespace
{
2272 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "remote mirror uuid",
2273 1, true, 0, {{1, CEPH_NOSNAP
}}},
2276 expect_is_refresh_required(mock_remote_image_ctx
, false);
2279 C_SaferCond init_ctx
;
2280 mock_replayer
.init(&init_ctx
);
2281 ASSERT_EQ(0, init_ctx
.wait());
2283 // wait for sync to complete
2284 ASSERT_EQ(0, wait_for_notification(3));
2287 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer
, mock_threads
,
2288 mock_local_image_ctx
,
2289 mock_remote_image_ctx
));
2292 } // namespace snapshot
2293 } // namespace image_replayer
2294 } // namespace mirror