]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rbd_mirror/image_replayer/snapshot/test_mock_Replayer.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / rbd_mirror / image_replayer / snapshot / test_mock_Replayer.cc
CommitLineData
9f95a23c
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "test/rbd_mirror/test_mock_fixture.h"
5#include "librbd/deep_copy/ImageCopyRequest.h"
6#include "librbd/deep_copy/SnapshotCopyRequest.h"
f67539c2 7#include "librbd/mirror/ImageStateUpdateRequest.h"
9f95a23c
TL
8#include "librbd/mirror/snapshot/CreateNonPrimaryRequest.h"
9#include "librbd/mirror/snapshot/GetImageStateRequest.h"
10#include "librbd/mirror/snapshot/ImageMeta.h"
11#include "librbd/mirror/snapshot/UnlinkPeerRequest.h"
12#include "tools/rbd_mirror/InstanceWatcher.h"
13#include "tools/rbd_mirror/Threads.h"
14#include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
15#include "tools/rbd_mirror/image_replayer/ReplayerListener.h"
16#include "tools/rbd_mirror/image_replayer/Utils.h"
17#include "tools/rbd_mirror/image_replayer/snapshot/ApplyImageStateRequest.h"
18#include "tools/rbd_mirror/image_replayer/snapshot/Replayer.h"
19#include "tools/rbd_mirror/image_replayer/snapshot/StateBuilder.h"
20#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
21#include "test/librbd/mock/MockImageCtx.h"
1911f103 22#include "test/librbd/mock/MockOperations.h"
9f95a23c
TL
23#include "test/rbd_mirror/mock/MockContextWQ.h"
24#include "test/rbd_mirror/mock/MockSafeTimer.h"
25
20effc67
TL
26using namespace std::chrono_literals;
27
9f95a23c
TL
28namespace librbd {
29namespace {
30
31struct MockTestImageCtx : public librbd::MockImageCtx {
32 explicit MockTestImageCtx(librbd::ImageCtx &image_ctx)
33 : librbd::MockImageCtx(image_ctx) {
34 }
35};
36
37} // anonymous namespace
38
39namespace deep_copy {
40
41template <>
42struct ImageCopyRequest<MockTestImageCtx> {
43 uint64_t src_snap_id_start;
44 uint64_t src_snap_id_end;
45 uint64_t dst_snap_id_start;
46 librbd::deep_copy::ObjectNumber object_number;
47 librbd::SnapSeqs snap_seqs;
48
49 static ImageCopyRequest* s_instance;
50 static ImageCopyRequest* create(MockTestImageCtx *src_image_ctx,
51 MockTestImageCtx *dst_image_ctx,
52 librados::snap_t src_snap_id_start,
53 librados::snap_t src_snap_id_end,
54 librados::snap_t dst_snap_id_start,
55 bool flatten,
56 const ObjectNumber &object_number,
57 const SnapSeqs &snap_seqs,
1911f103 58 Handler *handler,
9f95a23c
TL
59 Context *on_finish) {
60 ceph_assert(s_instance != nullptr);
61 s_instance->src_snap_id_start = src_snap_id_start;
62 s_instance->src_snap_id_end = src_snap_id_end;
63 s_instance->dst_snap_id_start = dst_snap_id_start;
64 s_instance->object_number = object_number;
65 s_instance->snap_seqs = snap_seqs;
66 s_instance->on_finish = on_finish;
67 return s_instance;
68 }
69
70 Context* on_finish = nullptr;
71
72 ImageCopyRequest() {
73 s_instance = this;
74 }
75
76 MOCK_METHOD0(send, void());
77};
78
79template <>
80struct SnapshotCopyRequest<MockTestImageCtx> {
81 librados::snap_t src_snap_id_start;
82 librados::snap_t src_snap_id_end;
83 librados::snap_t dst_snap_id_start;
84 SnapSeqs* snap_seqs = nullptr;
85
86 static SnapshotCopyRequest* s_instance;
87 static SnapshotCopyRequest* create(MockTestImageCtx *src_image_ctx,
88 MockTestImageCtx *dst_image_ctx,
89 librados::snap_t src_snap_id_start,
90 librados::snap_t src_snap_id_end,
91 librados::snap_t dst_snap_id_start,
92 bool flatten,
93 ::MockContextWQ *work_queue,
94 SnapSeqs *snap_seqs,
95 Context *on_finish) {
96 ceph_assert(s_instance != nullptr);
97 s_instance->src_snap_id_start = src_snap_id_start;
98 s_instance->src_snap_id_end = src_snap_id_end;
99 s_instance->dst_snap_id_start = dst_snap_id_start;
100 s_instance->snap_seqs = snap_seqs;
101 s_instance->on_finish = on_finish;
102 return s_instance;
103 }
104
105 Context* on_finish = nullptr;
106
107 SnapshotCopyRequest() {
108 s_instance = this;
109 }
110
111 MOCK_METHOD0(send, void());
112};
113
114ImageCopyRequest<MockTestImageCtx>* ImageCopyRequest<MockTestImageCtx>::s_instance = nullptr;
115SnapshotCopyRequest<MockTestImageCtx>* SnapshotCopyRequest<MockTestImageCtx>::s_instance = nullptr;
116
117} // namespace deep_copy
118
119namespace mirror {
f67539c2
TL
120
121template <>
122struct ImageStateUpdateRequest<MockTestImageCtx> {
123 static ImageStateUpdateRequest* s_instance;
124 static ImageStateUpdateRequest* create(
125 librados::IoCtx& io_ctx,
126 const std::string& image_id,
127 cls::rbd::MirrorImageState mirror_image_state,
128 const cls::rbd::MirrorImage& mirror_image,
129 Context* on_finish) {
130 ceph_assert(s_instance != nullptr);
131 EXPECT_EQ(cls::rbd::MIRROR_IMAGE_STATE_ENABLED,
132 mirror_image_state);
133 EXPECT_EQ(cls::rbd::MirrorImage{}, mirror_image);
134 s_instance->on_finish = on_finish;
135 return s_instance;
136 }
137
138 Context* on_finish = nullptr;
139 ImageStateUpdateRequest() {
140 s_instance = this;
141 }
142
143 MOCK_METHOD0(send, void());
144};
145
146ImageStateUpdateRequest<MockTestImageCtx>* ImageStateUpdateRequest<MockTestImageCtx>::s_instance = nullptr;
147
9f95a23c
TL
148namespace snapshot {
149
150template <>
151struct CreateNonPrimaryRequest<MockTestImageCtx> {
152 bool demoted = false;
153 std::string primary_mirror_uuid;
154 uint64_t primary_snap_id;
155 SnapSeqs snap_seqs;
156 uint64_t* snap_id = nullptr;
157
158 static CreateNonPrimaryRequest* s_instance;
159 static CreateNonPrimaryRequest* create(MockTestImageCtx *image_ctx,
160 bool demoted,
161 const std::string &primary_mirror_uuid,
162 uint64_t primary_snap_id,
163 const SnapSeqs& snap_seqs,
164 const ImageState &image_state,
165 uint64_t *snap_id,
166 Context *on_finish) {
167 ceph_assert(s_instance != nullptr);
168 s_instance->demoted = demoted;
169 s_instance->primary_mirror_uuid = primary_mirror_uuid;
170 s_instance->primary_snap_id = primary_snap_id;
171 s_instance->snap_seqs = snap_seqs;
172 s_instance->snap_id = snap_id;
173 s_instance->on_finish = on_finish;
174 return s_instance;
175 }
176
177 Context* on_finish = nullptr;
178
179 CreateNonPrimaryRequest() {
180 s_instance = this;
181 }
182
183 MOCK_METHOD0(send, void());
184};
185
186template <>
187struct GetImageStateRequest<MockTestImageCtx> {
188 uint64_t snap_id = CEPH_NOSNAP;
189
190 static GetImageStateRequest* s_instance;
191 static GetImageStateRequest* create(MockTestImageCtx *image_ctx,
192 uint64_t snap_id,
193 ImageState *image_state,
194 Context *on_finish) {
195 ceph_assert(s_instance != nullptr);
196 s_instance->snap_id = snap_id;
197 s_instance->on_finish = on_finish;
198 return s_instance;
199 }
200
201 Context* on_finish = nullptr;
202
203 GetImageStateRequest() {
204 s_instance = this;
205 }
206
207 MOCK_METHOD0(send, void());
208};
209
210template <>
211struct ImageMeta<MockTestImageCtx> {
212 MOCK_METHOD1(load, void(Context*));
213
214 bool resync_requested = false;
215};
216
217template <>
218struct UnlinkPeerRequest<MockTestImageCtx> {
219 uint64_t snap_id;
220 std::string mirror_peer_uuid;
221
222 static UnlinkPeerRequest* s_instance;
223 static UnlinkPeerRequest*create (MockTestImageCtx *image_ctx,
224 uint64_t snap_id,
225 const std::string &mirror_peer_uuid,
226 Context *on_finish) {
227 ceph_assert(s_instance != nullptr);
228 s_instance->snap_id = snap_id;
229 s_instance->mirror_peer_uuid = mirror_peer_uuid;
230 s_instance->on_finish = on_finish;
231 return s_instance;
232 }
233
234 Context* on_finish = nullptr;
235
236 UnlinkPeerRequest() {
237 s_instance = this;
238 }
239
240 MOCK_METHOD0(send, void());
241};
242
243CreateNonPrimaryRequest<MockTestImageCtx>* CreateNonPrimaryRequest<MockTestImageCtx>::s_instance = nullptr;
244GetImageStateRequest<MockTestImageCtx>* GetImageStateRequest<MockTestImageCtx>::s_instance = nullptr;
245UnlinkPeerRequest<MockTestImageCtx>* UnlinkPeerRequest<MockTestImageCtx>::s_instance = nullptr;
246
247} // namespace snapshot
248} // namespace mirror
249} // namespace librbd
250
251namespace rbd {
252namespace mirror {
253
254template <>
255struct InstanceWatcher<librbd::MockTestImageCtx> {
256 MOCK_METHOD1(cancel_sync_request, void(const std::string&));
257 MOCK_METHOD2(notify_sync_request, void(const std::string&,
258 Context*));
259 MOCK_METHOD1(notify_sync_complete, void(const std::string&));
260};
261
262template <>
263struct Threads<librbd::MockTestImageCtx> {
264 MockSafeTimer *timer;
265 ceph::mutex &timer_lock;
266
267 MockContextWQ *work_queue;
268
269 Threads(Threads<librbd::ImageCtx>* threads)
270 : timer(new MockSafeTimer()),
271 timer_lock(threads->timer_lock),
272 work_queue(new MockContextWQ()) {
273 }
274 ~Threads() {
275 delete timer;
276 delete work_queue;
277 }
278};
279
280namespace {
281
282struct MockReplayerListener : public image_replayer::ReplayerListener {
283 MOCK_METHOD0(handle_notification, void());
284};
285
286} // anonymous namespace
287
288namespace image_replayer {
289
290template<>
291struct CloseImageRequest<librbd::MockTestImageCtx> {
292 static CloseImageRequest* s_instance;
293 librbd::MockTestImageCtx **image_ctx = nullptr;
294 Context *on_finish = nullptr;
295
296 static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx,
297 Context *on_finish) {
298 ceph_assert(s_instance != nullptr);
299 s_instance->image_ctx = image_ctx;
300 s_instance->on_finish = on_finish;
301 return s_instance;
302 }
303
304 CloseImageRequest() {
305 ceph_assert(s_instance == nullptr);
306 s_instance = this;
307 }
308
309 ~CloseImageRequest() {
310 ceph_assert(s_instance == this);
311 s_instance = nullptr;
312 }
313
314 MOCK_METHOD0(send, void());
315};
316
317CloseImageRequest<librbd::MockTestImageCtx>* CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
318
319namespace snapshot {
320
321template <>
322struct ApplyImageStateRequest<librbd::MockTestImageCtx> {
323 Context* on_finish = nullptr;
324
325 static ApplyImageStateRequest* s_instance;
326 static ApplyImageStateRequest* create(
327 const std::string& local_mirror_uuid,
328 const std::string& remote_mirror_uuid,
329 librbd::MockTestImageCtx* local_image_ctx,
330 librbd::MockTestImageCtx* remote_image_ctx,
331 const librbd::mirror::snapshot::ImageState& image_state,
332 Context* on_finish) {
333 ceph_assert(s_instance != nullptr);
334 s_instance->on_finish = on_finish;
335 return s_instance;
336 }
337
338 ApplyImageStateRequest() {
339 s_instance = this;
340 }
341
342 MOCK_METHOD0(send, void());
343};
344
345template<>
346struct StateBuilder<librbd::MockTestImageCtx> {
347 StateBuilder(librbd::MockTestImageCtx& local_image_ctx,
348 librbd::MockTestImageCtx& remote_image_ctx,
349 librbd::mirror::snapshot::ImageMeta<librbd::MockTestImageCtx>&
350 local_image_meta)
351 : local_image_ctx(&local_image_ctx),
352 remote_image_ctx(&remote_image_ctx),
353 local_image_meta(&local_image_meta) {
354 }
355
356 librbd::MockTestImageCtx* local_image_ctx;
357 librbd::MockTestImageCtx* remote_image_ctx;
358
359 std::string remote_mirror_uuid = "remote mirror uuid";
360
361 librbd::mirror::snapshot::ImageMeta<librbd::MockTestImageCtx>*
362 local_image_meta = nullptr;
363};
364
365ApplyImageStateRequest<librbd::MockTestImageCtx>* ApplyImageStateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
366
367} // namespace snapshot
368} // namespace image_replayer
369} // namespace mirror
370} // namespace rbd
371
372#include "tools/rbd_mirror/image_replayer/snapshot/Replayer.cc"
373
374namespace rbd {
375namespace mirror {
376namespace image_replayer {
377namespace snapshot {
378
379using ::testing::_;
380using ::testing::DoAll;
381using ::testing::InSequence;
382using ::testing::Invoke;
383using ::testing::Return;
384using ::testing::ReturnArg;
385using ::testing::StrEq;
386using ::testing::WithArg;
387
388class TestMockImageReplayerSnapshotReplayer : public TestMockFixture {
389public:
390 typedef Replayer<librbd::MockTestImageCtx> MockReplayer;
391 typedef ApplyImageStateRequest<librbd::MockTestImageCtx> MockApplyImageStateRequest;
392 typedef StateBuilder<librbd::MockTestImageCtx> MockStateBuilder;
393 typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
394 typedef Threads<librbd::MockTestImageCtx> MockThreads;
395 typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
396 typedef librbd::deep_copy::ImageCopyRequest<librbd::MockTestImageCtx> MockImageCopyRequest;
397 typedef librbd::deep_copy::SnapshotCopyRequest<librbd::MockTestImageCtx> MockSnapshotCopyRequest;
f67539c2 398 typedef librbd::mirror::ImageStateUpdateRequest<librbd::MockTestImageCtx> MockImageStateUpdateRequest;
9f95a23c
TL
399 typedef librbd::mirror::snapshot::CreateNonPrimaryRequest<librbd::MockTestImageCtx> MockCreateNonPrimaryRequest;
400 typedef librbd::mirror::snapshot::GetImageStateRequest<librbd::MockTestImageCtx> MockGetImageStateRequest;
401 typedef librbd::mirror::snapshot::ImageMeta<librbd::MockTestImageCtx> MockImageMeta;
402 typedef librbd::mirror::snapshot::UnlinkPeerRequest<librbd::MockTestImageCtx> MockUnlinkPeerRequest;
403
404 void SetUp() override {
405 TestMockFixture::SetUp();
406
407 librbd::RBD rbd;
408 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
409 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
410
411 ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name,
412 m_image_size));
413 ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name,
414 &m_remote_image_ctx));
415 }
416
417 void expect_work_queue_repeatedly(MockThreads &mock_threads) {
418 EXPECT_CALL(*mock_threads.work_queue, queue(_, _))
419 .WillRepeatedly(Invoke([this](Context *ctx, int r) {
420 m_threads->work_queue->queue(ctx, r);
421 }));
422 }
423
424 void expect_add_event_after_repeatedly(MockThreads &mock_threads) {
425 EXPECT_CALL(*mock_threads.timer, add_event_after(_, _))
426 .WillRepeatedly(
427 DoAll(Invoke([this](double seconds, Context *ctx) {
428 m_threads->timer->add_event_after(seconds, ctx);
429 }),
430 ReturnArg<1>()));
431 EXPECT_CALL(*mock_threads.timer, cancel_event(_))
432 .WillRepeatedly(
433 Invoke([this](Context *ctx) {
434 return m_threads->timer->cancel_event(ctx);
435 }));
436 }
437
438 void expect_register_update_watcher(librbd::MockTestImageCtx& mock_image_ctx,
439 librbd::UpdateWatchCtx** update_watch_ctx,
440 uint64_t watch_handle, int r) {
441 EXPECT_CALL(*mock_image_ctx.state, register_update_watcher(_, _))
442 .WillOnce(Invoke([update_watch_ctx, watch_handle, r]
443 (librbd::UpdateWatchCtx* ctx, uint64_t* handle) {
444 if (r >= 0) {
445 *update_watch_ctx = ctx;
446 *handle = watch_handle;
447 }
448 return r;
449 }));
450 }
451
452 void expect_unregister_update_watcher(librbd::MockTestImageCtx& mock_image_ctx,
453 uint64_t watch_handle, int r) {
454 EXPECT_CALL(*mock_image_ctx.state, unregister_update_watcher(watch_handle, _))
455 .WillOnce(WithArg<1>(Invoke([this, r](Context* ctx) {
456 m_threads->work_queue->queue(ctx, r);
457 })));
458 }
459
460 void expect_load_image_meta(MockImageMeta& mock_image_meta,
461 bool resync_requested, int r) {
462 EXPECT_CALL(mock_image_meta, load(_))
463 .WillOnce(Invoke([this, &mock_image_meta, resync_requested, r](Context* ctx) {
464 mock_image_meta.resync_requested = resync_requested;
465 m_threads->work_queue->queue(ctx, r);
466 }));
467 }
468
469 void expect_is_refresh_required(librbd::MockTestImageCtx& mock_image_ctx,
470 bool is_required) {
471 EXPECT_CALL(*mock_image_ctx.state, is_refresh_required())
472 .WillOnce(Return(is_required));
473 }
474
475 void expect_refresh(librbd::MockTestImageCtx& mock_image_ctx,
476 const std::map<uint64_t, librbd::SnapInfo>& snaps,
477 int r) {
478 EXPECT_CALL(*mock_image_ctx.state, refresh(_))
479 .WillOnce(Invoke([this, &mock_image_ctx, snaps, r](Context* ctx) {
480 mock_image_ctx.snap_info = snaps;
481 m_threads->work_queue->queue(ctx, r);
482 }));
483 }
484
485 void expect_notify_update(librbd::MockTestImageCtx& mock_image_ctx) {
486 EXPECT_CALL(mock_image_ctx, notify_update(_))
487 .WillOnce(Invoke([this](Context* ctx) {
488 m_threads->work_queue->queue(ctx, 0);
489 }));
490 }
491
1911f103
TL
492 void expect_prune_non_primary_snapshot(librbd::MockTestImageCtx& mock_image_ctx,
493 uint64_t snap_id, int r) {
494 EXPECT_CALL(mock_image_ctx, get_snap_info(snap_id))
495 .WillOnce(Invoke([&mock_image_ctx](uint64_t snap_id) -> librbd::SnapInfo* {
496 auto it = mock_image_ctx.snap_info.find(snap_id);
497 if (it == mock_image_ctx.snap_info.end()) {
498 return nullptr;
499 }
500 return &it->second;
501 }));
502 EXPECT_CALL(*mock_image_ctx.operations, snap_remove(_, _, _))
503 .WillOnce(WithArg<2>(Invoke([this, r](Context* ctx) {
504 m_threads->work_queue->queue(ctx, r);
505 })));
506 }
507
9f95a23c
TL
508 void expect_snapshot_copy(MockSnapshotCopyRequest& mock_snapshot_copy_request,
509 uint64_t src_snap_id_start,
510 uint64_t src_snap_id_end,
511 uint64_t dst_snap_id_start,
512 const librbd::SnapSeqs& snap_seqs, int r) {
513 EXPECT_CALL(mock_snapshot_copy_request, send())
514 .WillOnce(Invoke([this, &req=mock_snapshot_copy_request,
515 src_snap_id_start, src_snap_id_end, dst_snap_id_start,
516 snap_seqs, r]() {
517 ASSERT_EQ(src_snap_id_start, req.src_snap_id_start);
518 ASSERT_EQ(src_snap_id_end, req.src_snap_id_end);
519 ASSERT_EQ(dst_snap_id_start, req.dst_snap_id_start);
520 *req.snap_seqs = snap_seqs;
521 m_threads->work_queue->queue(req.on_finish, r);
522 }));
523 }
524
525 void expect_get_image_state(MockGetImageStateRequest& mock_get_image_state_request,
526 uint64_t snap_id, int r) {
527 EXPECT_CALL(mock_get_image_state_request, send())
528 .WillOnce(Invoke([this, &req=mock_get_image_state_request, snap_id, r]() {
529 ASSERT_EQ(snap_id, req.snap_id);
530 m_threads->work_queue->queue(req.on_finish, r);
531 }));
532 }
533
534 void expect_create_non_primary_request(MockCreateNonPrimaryRequest& mock_create_non_primary_request,
535 bool demoted,
536 const std::string& primary_mirror_uuid,
537 uint64_t primary_snap_id,
538 const librbd::SnapSeqs& snap_seqs,
539 uint64_t snap_id, int r) {
540 EXPECT_CALL(mock_create_non_primary_request, send())
541 .WillOnce(Invoke([this, &req=mock_create_non_primary_request, demoted,
542 primary_mirror_uuid, primary_snap_id, snap_seqs,
543 snap_id, r]() {
544 ASSERT_EQ(demoted, req.demoted);
545 ASSERT_EQ(primary_mirror_uuid, req.primary_mirror_uuid);
546 ASSERT_EQ(primary_snap_id, req.primary_snap_id);
547 ASSERT_EQ(snap_seqs, req.snap_seqs);
548 *req.snap_id = snap_id;
549 m_threads->work_queue->queue(req.on_finish, r);
550 }));
551 }
552
f67539c2
TL
553 void expect_update_mirror_image_state(MockImageStateUpdateRequest& mock_image_state_update_request,
554 int r) {
555 EXPECT_CALL(mock_image_state_update_request, send())
556 .WillOnce(Invoke([this, &req=mock_image_state_update_request, r]() {
557 m_threads->work_queue->queue(req.on_finish, r);
558 }));
559 }
560
9f95a23c
TL
561 void expect_notify_sync_request(MockInstanceWatcher& mock_instance_watcher,
562 const std::string& image_id, int r) {
563 EXPECT_CALL(mock_instance_watcher, notify_sync_request(image_id, _))
564 .WillOnce(WithArg<1>(Invoke([this, r](Context* ctx) {
565 m_threads->work_queue->queue(ctx, r);
566 })));
567 }
568
569 void expect_notify_sync_complete(MockInstanceWatcher& mock_instance_watcher,
570 const std::string& image_id) {
571 EXPECT_CALL(mock_instance_watcher, notify_sync_complete(image_id));
572 }
573
574 void expect_image_copy(MockImageCopyRequest& mock_image_copy_request,
575 uint64_t src_snap_id_start, uint64_t src_snap_id_end,
576 uint64_t dst_snap_id_start,
577 const librbd::deep_copy::ObjectNumber& object_number,
578 const librbd::SnapSeqs& snap_seqs, int r) {
579 EXPECT_CALL(mock_image_copy_request, send())
580 .WillOnce(Invoke([this, &req=mock_image_copy_request, src_snap_id_start,
581 src_snap_id_end, dst_snap_id_start, object_number,
582 snap_seqs, r]() {
583 ASSERT_EQ(src_snap_id_start, req.src_snap_id_start);
584 ASSERT_EQ(src_snap_id_end, req.src_snap_id_end);
585 ASSERT_EQ(dst_snap_id_start, req.dst_snap_id_start);
586 ASSERT_EQ(object_number, req.object_number);
587 ASSERT_EQ(snap_seqs, req.snap_seqs);
588 m_threads->work_queue->queue(req.on_finish, r);
589 }));
590 }
591
592 void expect_unlink_peer(MockUnlinkPeerRequest& mock_unlink_peer_request,
593 uint64_t snap_id, const std::string& mirror_peer_uuid,
594 int r) {
595 EXPECT_CALL(mock_unlink_peer_request, send())
596 .WillOnce(Invoke([this, &req=mock_unlink_peer_request, snap_id,
597 mirror_peer_uuid, r]() {
598 ASSERT_EQ(snap_id, req.snap_id);
599 ASSERT_EQ(mirror_peer_uuid, req.mirror_peer_uuid);
600 m_threads->work_queue->queue(req.on_finish, r);
601 }));
602 }
603
604 void expect_apply_image_state(
605 MockApplyImageStateRequest& mock_request, int r) {
606 EXPECT_CALL(mock_request, send())
607 .WillOnce(Invoke([this, &req=mock_request, r]() {
608 m_threads->work_queue->queue(req.on_finish, r);
609 }));
610 }
611
612 void expect_mirror_image_snapshot_set_copy_progress(
613 librbd::MockTestImageCtx& mock_test_image_ctx, uint64_t snap_id,
614 bool completed, uint64_t last_copied_object, int r) {
615 bufferlist bl;
616 encode(snap_id, bl);
617 encode(completed, bl);
618 encode(last_copied_object, bl);
619
620 EXPECT_CALL(get_mock_io_ctx(mock_test_image_ctx.md_ctx),
621 exec(mock_test_image_ctx.header_oid, _, StrEq("rbd"),
622 StrEq("mirror_image_snapshot_set_copy_progress"),
f67539c2 623 ContentsEqual(bl), _, _, _))
9f95a23c
TL
624 .WillOnce(Return(r));
625 }
626
627 void expect_send(MockCloseImageRequest &mock_close_image_request, int r) {
628 EXPECT_CALL(mock_close_image_request, send())
629 .WillOnce(Invoke([this, &mock_close_image_request, r]() {
630 *mock_close_image_request.image_ctx = nullptr;
631 m_threads->work_queue->queue(mock_close_image_request.on_finish, r);
632 }));
633 }
634
635 void expect_notification(MockThreads& mock_threads,
636 MockReplayerListener& mock_replayer_listener) {
637 EXPECT_CALL(mock_replayer_listener, handle_notification())
638 .WillRepeatedly(Invoke([this]() {
639 std::unique_lock locker{m_lock};
640 ++m_notifications;
641 m_cond.notify_all();
642 }));
643 }
644
645 int wait_for_notification(uint32_t count) {
646 std::unique_lock locker{m_lock};
647 for (uint32_t idx = 0; idx < count; ++idx) {
648 while (m_notifications == 0) {
649 if (m_cond.wait_for(locker, 10s) == std::cv_status::timeout) {
650 return -ETIMEDOUT;
651 }
652 }
653 --m_notifications;
654 }
655 return 0;
656 }
657
658 int init_entry_replayer(MockReplayer& mock_replayer,
659 MockThreads& mock_threads,
660 librbd::MockTestImageCtx& mock_local_image_ctx,
661 librbd::MockTestImageCtx& mock_remote_image_ctx,
662 MockReplayerListener& mock_replayer_listener,
663 MockImageMeta& mock_image_meta,
664 librbd::UpdateWatchCtx** update_watch_ctx) {
665 expect_register_update_watcher(mock_local_image_ctx, update_watch_ctx, 123,
666 0);
667 expect_register_update_watcher(mock_remote_image_ctx, update_watch_ctx, 234,
668 0);
669 expect_load_image_meta(mock_image_meta, false, 0);
670 expect_is_refresh_required(mock_local_image_ctx, false);
671 expect_is_refresh_required(mock_remote_image_ctx, false);
672
673 C_SaferCond init_ctx;
674 mock_replayer.init(&init_ctx);
675 int r = init_ctx.wait();
676 if (r < 0) {
677 return r;
678 }
679
680 return wait_for_notification(2);
681 }
682
683 int shut_down_entry_replayer(MockReplayer& mock_replayer,
684 MockThreads& mock_threads,
685 librbd::MockTestImageCtx& mock_local_image_ctx,
686 librbd::MockTestImageCtx& mock_remote_image_ctx) {
687 expect_unregister_update_watcher(mock_remote_image_ctx, 234, 0);
688 expect_unregister_update_watcher(mock_local_image_ctx, 123, 0);
689
690 C_SaferCond shutdown_ctx;
691 mock_replayer.shut_down(&shutdown_ctx);
692 return shutdown_ctx.wait();
693 }
694
695 librbd::ImageCtx* m_local_image_ctx = nullptr;
696 librbd::ImageCtx* m_remote_image_ctx = nullptr;
697
698 PoolMetaCache m_pool_meta_cache{g_ceph_context};
699
700 ceph::mutex m_lock = ceph::make_mutex(
701 "TestMockImageReplayerSnapshotReplayer");
702 ceph::condition_variable m_cond;
703 uint32_t m_notifications = 0;
704};
705
706TEST_F(TestMockImageReplayerSnapshotReplayer, InitShutDown) {
707 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
708 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
709
710 MockThreads mock_threads(m_threads);
711 expect_work_queue_repeatedly(mock_threads);
712
713 MockReplayerListener mock_replayer_listener;
714 expect_notification(mock_threads, mock_replayer_listener);
715
716 InSequence seq;
717
718 MockInstanceWatcher mock_instance_watcher;
719 MockImageMeta mock_image_meta;
720 MockStateBuilder mock_state_builder(mock_local_image_ctx,
721 mock_remote_image_ctx,
722 mock_image_meta);
723 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
724 "local mirror uuid", &m_pool_meta_cache,
725 &mock_state_builder, &mock_replayer_listener};
726 m_pool_meta_cache.set_remote_pool_meta(
727 m_remote_io_ctx.get_id(),
728 {"remote mirror uuid", "remote mirror peer uuid"});
729
730 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
731 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
732 mock_local_image_ctx,
733 mock_remote_image_ctx,
734 mock_replayer_listener,
735 mock_image_meta,
736 &update_watch_ctx));
737 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
738 mock_local_image_ctx,
739 mock_remote_image_ctx));
740}
741
742TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
743 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
744 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
745
746 // it should sync two snapshots and skip two (user and mirror w/o matching
747 // peer uuid)
748 mock_remote_image_ctx.snap_info = {
749 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
750 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
1911f103 751 "", CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
752 0, {}, 0, 0, {}}},
753 {2U, librbd::SnapInfo{"snap2", cls::rbd::UserSnapshotNamespace{},
754 0, {}, 0, 0, {}}},
755 {3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
756 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {""},
1911f103 757 "", CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
758 0, {}, 0, 0, {}}},
759 {4U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
760 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
1911f103 761 "", CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
762 0, {}, 0, 0, {}}}};
763
764 MockThreads mock_threads(m_threads);
765 expect_work_queue_repeatedly(mock_threads);
766
767 MockReplayerListener mock_replayer_listener;
768 expect_notification(mock_threads, mock_replayer_listener);
769
770 InSequence seq;
771
772 MockInstanceWatcher mock_instance_watcher;
773 MockImageMeta mock_image_meta;
774 MockStateBuilder mock_state_builder(mock_local_image_ctx,
775 mock_remote_image_ctx,
776 mock_image_meta);
777 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
778 "local mirror uuid", &m_pool_meta_cache,
779 &mock_state_builder, &mock_replayer_listener};
780 m_pool_meta_cache.set_remote_pool_meta(
781 m_remote_io_ctx.get_id(),
782 {"remote mirror uuid", "remote mirror peer uuid"});
783
784 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
785
786 // init
787 expect_register_update_watcher(mock_local_image_ctx, &update_watch_ctx, 123,
788 0);
789 expect_register_update_watcher(mock_remote_image_ctx, &update_watch_ctx, 234,
790 0);
791
792 // sync snap1
793 expect_load_image_meta(mock_image_meta, false, 0);
794 expect_is_refresh_required(mock_local_image_ctx, false);
795 expect_is_refresh_required(mock_remote_image_ctx, false);
796 MockSnapshotCopyRequest mock_snapshot_copy_request;
797 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
798 0);
799 MockGetImageStateRequest mock_get_image_state_request;
800 expect_get_image_state(mock_get_image_state_request, 1, 0);
801 MockCreateNonPrimaryRequest mock_create_non_primary_request;
802 expect_create_non_primary_request(mock_create_non_primary_request,
803 false, "remote mirror uuid", 1,
804 {{1, CEPH_NOSNAP}}, 11, 0);
f67539c2
TL
805 MockImageStateUpdateRequest mock_image_state_update_request;
806 expect_update_mirror_image_state(mock_image_state_update_request, 0);
9f95a23c
TL
807 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
808 MockImageCopyRequest mock_image_copy_request;
809 expect_image_copy(mock_image_copy_request, 0, 1, 0, {},
810 {{1, CEPH_NOSNAP}}, 0);
811 MockApplyImageStateRequest mock_apply_state_request;
812 expect_apply_image_state(mock_apply_state_request, 0);
813 expect_mirror_image_snapshot_set_copy_progress(
814 mock_local_image_ctx, 11, true, 0, 0);
815 expect_notify_update(mock_local_image_ctx);
816 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
817
818 // sync snap4
819 expect_load_image_meta(mock_image_meta, false, 0);
820 expect_is_refresh_required(mock_local_image_ctx, true);
821 expect_refresh(
822 mock_local_image_ctx, {
823 {11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
824 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
1911f103 825 1, true, 0, {{1, CEPH_NOSNAP}}},
9f95a23c
TL
826 0, {}, 0, 0, {}}},
827 }, 0);
f67539c2
TL
828 expect_is_refresh_required(mock_remote_image_ctx, true);
829 expect_refresh(
830 mock_remote_image_ctx, {
831 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
832 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
833 "", CEPH_NOSNAP, true, 0, {}},
834 0, {}, 0, 0, {}}},
835 {2U, librbd::SnapInfo{"snap2", cls::rbd::UserSnapshotNamespace{},
836 0, {}, 0, 0, {}}},
837 {3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
838 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {""},
839 "", CEPH_NOSNAP, true, 0, {}},
840 0, {}, 0, 0, {}}},
841 {4U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
842 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
843 "", CEPH_NOSNAP, true, 0, {}},
844 0, {}, 0, 0, {}}},
845 {5U, librbd::SnapInfo{"snap5", cls::rbd::MirrorSnapshotNamespace{
846 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
847 "", CEPH_NOSNAP, true, 0, {}},
848 0, {}, 0, 0, {}}}
849 }, 0);
9f95a23c 850 expect_snapshot_copy(mock_snapshot_copy_request, 1, 4, 11,
1911f103 851 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP}}, 0);
9f95a23c
TL
852 expect_get_image_state(mock_get_image_state_request, 4, 0);
853 expect_create_non_primary_request(mock_create_non_primary_request,
854 false, "remote mirror uuid", 4,
1911f103
TL
855 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP}}, 14,
856 0);
9f95a23c
TL
857 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
858 expect_image_copy(mock_image_copy_request, 1, 4, 11, {},
1911f103 859 {{1, 11}, {2, 12}, {4, CEPH_NOSNAP}}, 0);
9f95a23c
TL
860 expect_apply_image_state(mock_apply_state_request, 0);
861 expect_mirror_image_snapshot_set_copy_progress(
862 mock_local_image_ctx, 14, true, 0, 0);
863 expect_notify_update(mock_local_image_ctx);
864 MockUnlinkPeerRequest mock_unlink_peer_request;
865 expect_unlink_peer(mock_unlink_peer_request, 1, "remote mirror peer uuid",
866 0);
867 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
868
1911f103 869 // prune non-primary snap1
9f95a23c
TL
870 expect_load_image_meta(mock_image_meta, false, 0);
871 expect_is_refresh_required(mock_local_image_ctx, true);
872 expect_refresh(
873 mock_local_image_ctx, {
874 {11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
875 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
876 1, true, 0, {}},
877 0, {}, 0, 0, {}}},
1911f103
TL
878 {12U, librbd::SnapInfo{"snap2", cls::rbd::UserSnapshotNamespace{},
879 0, {}, 0, 0, {}}},
880 {14U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
881 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
882 4, true, 0, {}},
883 0, {}, 0, 0, {}}},
884 }, 0);
885 expect_is_refresh_required(mock_remote_image_ctx, true);
886 expect_refresh(
887 mock_remote_image_ctx, {
f67539c2
TL
888 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
889 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
890 "", CEPH_NOSNAP, true, 0, {}},
891 0, {}, 0, 0, {}}},
1911f103
TL
892 {2U, librbd::SnapInfo{"snap2", cls::rbd::UserSnapshotNamespace{},
893 0, {}, 0, 0, {}}},
894 {3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
895 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {""},
896 "", CEPH_NOSNAP, true, 0, {}},
897 0, {}, 0, 0, {}}},
898 {4U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
899 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
900 "", CEPH_NOSNAP, true, 0, {}},
901 0, {}, 0, 0, {}}}
902 }, 0);
903 expect_prune_non_primary_snapshot(mock_local_image_ctx, 11, 0);
904
905 // idle
906 expect_load_image_meta(mock_image_meta, false, 0);
907 expect_is_refresh_required(mock_local_image_ctx, true);
908 expect_refresh(
909 mock_local_image_ctx, {
9f95a23c
TL
910 {14U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
911 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
912 4, true, 0, {}},
913 0, {}, 0, 0, {}}},
914 }, 0);
f67539c2
TL
915 expect_is_refresh_required(mock_remote_image_ctx, true);
916 expect_refresh(
917 mock_remote_image_ctx, {
918 {4U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
919 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
920 "", CEPH_NOSNAP, true, 0, {}},
921 0, {}, 0, 0, {}}}
922 }, 0);
9f95a23c
TL
923
924 // fire init
925 C_SaferCond init_ctx;
926 mock_replayer.init(&init_ctx);
927 ASSERT_EQ(0, init_ctx.wait());
928
929 // wait for sync to complete
930 ASSERT_EQ(0, wait_for_notification(4));
931
932 // shut down
933 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
934 mock_local_image_ctx,
935 mock_remote_image_ctx));
936}
937
938TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSync) {
939 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
940 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
941
942 MockThreads mock_threads(m_threads);
943 expect_work_queue_repeatedly(mock_threads);
944
945 MockReplayerListener mock_replayer_listener;
946 expect_notification(mock_threads, mock_replayer_listener);
947
948 InSequence seq;
949
950 MockInstanceWatcher mock_instance_watcher;
951 MockImageMeta mock_image_meta;
952 MockStateBuilder mock_state_builder(mock_local_image_ctx,
953 mock_remote_image_ctx,
954 mock_image_meta);
955 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
956 "local mirror uuid", &m_pool_meta_cache,
957 &mock_state_builder, &mock_replayer_listener};
958 m_pool_meta_cache.set_remote_pool_meta(
959 m_remote_io_ctx.get_id(),
960 {"remote mirror uuid", "remote mirror peer uuid"});
961
962 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
963 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
964 mock_local_image_ctx,
965 mock_remote_image_ctx,
966 mock_replayer_listener,
967 mock_image_meta,
968 &update_watch_ctx));
969
970 // inject a incomplete sync snapshot
971 mock_remote_image_ctx.snap_info = {
972 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
973 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
1911f103 974 "", CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
975 0, {}, 0, 0, {}}}};
976 mock_local_image_ctx.snap_info = {
977 {11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
978 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
979 1, false, 123, {{1, CEPH_NOSNAP}}},
980 0, {}, 0, 0, {}}}};
981
982 // re-sync snap1
983 expect_load_image_meta(mock_image_meta, false, 0);
984 expect_is_refresh_required(mock_local_image_ctx, false);
985 expect_is_refresh_required(mock_remote_image_ctx, false);
986 MockGetImageStateRequest mock_get_image_state_request;
987 expect_get_image_state(mock_get_image_state_request, 11, 0);
988 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
989 MockImageCopyRequest mock_image_copy_request;
990 expect_image_copy(mock_image_copy_request, 0, 1, 0,
991 librbd::deep_copy::ObjectNumber{123U},
992 {{1, CEPH_NOSNAP}}, 0);
993 MockApplyImageStateRequest mock_apply_state_request;
994 expect_apply_image_state(mock_apply_state_request, 0);
995 expect_mirror_image_snapshot_set_copy_progress(
996 mock_local_image_ctx, 11, true, 123, 0);
997 expect_notify_update(mock_local_image_ctx);
1911f103 998 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
9f95a23c
TL
999
1000 // idle
1001 expect_load_image_meta(mock_image_meta, false, 0);
1002 expect_is_refresh_required(mock_local_image_ctx, true);
1003 expect_refresh(
1004 mock_local_image_ctx, {
1005 {11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1006 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
1007 1, true, 0, {}},
1008 0, {}, 0, 0, {}}},
1009 }, 0);
1010 expect_is_refresh_required(mock_remote_image_ctx, false);
1011
1012 // wake-up replayer
1013 update_watch_ctx->handle_notify();
1014
1015 // wait for sync to complete
1016 ASSERT_EQ(0, wait_for_notification(2));
1017
1018 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1019 mock_local_image_ctx,
1020 mock_remote_image_ctx));
1021}
1022
1023TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
1024 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1025 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1026
1027 MockThreads mock_threads(m_threads);
1028 expect_work_queue_repeatedly(mock_threads);
1029
1030 MockReplayerListener mock_replayer_listener;
1031 expect_notification(mock_threads, mock_replayer_listener);
1032
1033 InSequence seq;
1034
1035 MockInstanceWatcher mock_instance_watcher;
1036 MockImageMeta mock_image_meta;
1037 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1038 mock_remote_image_ctx,
1039 mock_image_meta);
1040 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1041 "local mirror uuid", &m_pool_meta_cache,
1042 &mock_state_builder, &mock_replayer_listener};
1043 m_pool_meta_cache.set_remote_pool_meta(
1044 m_remote_io_ctx.get_id(),
1045 {"remote mirror uuid", "remote mirror peer uuid"});
1046
1047 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1048 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1049 mock_local_image_ctx,
1050 mock_remote_image_ctx,
1051 mock_replayer_listener,
1052 mock_image_meta,
1053 &update_watch_ctx));
1054
1055 // inject a demotion snapshot
1056 mock_remote_image_ctx.snap_info = {
1057 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1058 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
1911f103 1059 {"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
1060 0, {}, 0, 0, {}}}};
1061
1062 // sync snap1
1063 expect_load_image_meta(mock_image_meta, false, 0);
1064 expect_is_refresh_required(mock_local_image_ctx, false);
1065 expect_is_refresh_required(mock_remote_image_ctx, false);
1066 MockSnapshotCopyRequest mock_snapshot_copy_request;
1067 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
1068 0);
1069 MockGetImageStateRequest mock_get_image_state_request;
1070 expect_get_image_state(mock_get_image_state_request, 1, 0);
1071 MockCreateNonPrimaryRequest mock_create_non_primary_request;
1072 expect_create_non_primary_request(mock_create_non_primary_request,
1073 true, "remote mirror uuid", 1,
1074 {{1, CEPH_NOSNAP}}, 11, 0);
f67539c2
TL
1075 MockImageStateUpdateRequest mock_image_state_update_request;
1076 expect_update_mirror_image_state(mock_image_state_update_request, 0);
9f95a23c
TL
1077 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
1078 MockImageCopyRequest mock_image_copy_request;
1079 expect_image_copy(mock_image_copy_request, 0, 1, 0, {},
1080 {{1, CEPH_NOSNAP}}, 0);
1081 MockApplyImageStateRequest mock_apply_state_request;
1082 expect_apply_image_state(mock_apply_state_request, 0);
1083 expect_mirror_image_snapshot_set_copy_progress(
1084 mock_local_image_ctx, 11, true, 0, 0);
1085 expect_notify_update(mock_local_image_ctx);
1911f103 1086 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
9f95a23c
TL
1087
1088 // idle
1089 expect_load_image_meta(mock_image_meta, false, 0);
1090 expect_is_refresh_required(mock_local_image_ctx, true);
1091 expect_refresh(
1092 mock_local_image_ctx, {
1093 {11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1094 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
1095 1, true, 0, {}},
1096 0, {}, 0, 0, {}}},
1097 }, 0);
1098 expect_is_refresh_required(mock_remote_image_ctx, false);
1099
1100 // wake-up replayer
1101 update_watch_ctx->handle_notify();
1102
1103 // wait for sync to complete and expect replay complete
1104 ASSERT_EQ(0, wait_for_notification(2));
1105 ASSERT_FALSE(mock_replayer.is_replaying());
1106
1107 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1108 mock_local_image_ctx,
1109 mock_remote_image_ctx));
1110}
1111
1112TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
1113 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1114 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1115
1116 MockThreads mock_threads(m_threads);
1117 expect_work_queue_repeatedly(mock_threads);
1118
1119 MockReplayerListener mock_replayer_listener;
1120 expect_notification(mock_threads, mock_replayer_listener);
1121
1122 InSequence seq;
1123
1124 MockInstanceWatcher mock_instance_watcher;
1125 MockImageMeta mock_image_meta;
1126 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1127 mock_remote_image_ctx,
1128 mock_image_meta);
1129 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1130 "local mirror uuid", &m_pool_meta_cache,
1131 &mock_state_builder, &mock_replayer_listener};
1132 m_pool_meta_cache.set_remote_pool_meta(
1133 m_remote_io_ctx.get_id(),
1134 {"remote mirror uuid", "remote mirror peer uuid"});
1135
1136 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1137 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1138 mock_local_image_ctx,
1139 mock_remote_image_ctx,
1140 mock_replayer_listener,
1141 mock_image_meta,
1142 &update_watch_ctx));
1143
1144 // inject a promotion snapshot
1145 mock_local_image_ctx.snap_info = {
1146 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1147 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY,
1911f103 1148 {"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
1149 0, {}, 0, 0, {}}}};
1150
1151 // idle
1152 expect_load_image_meta(mock_image_meta, false, 0);
1153 expect_is_refresh_required(mock_local_image_ctx, false);
1154 expect_is_refresh_required(mock_remote_image_ctx, false);
1155
1156 // wake-up replayer
1157 update_watch_ctx->handle_notify();
1158
1159 // wait for sync to complete and expect replay complete
1160 ASSERT_EQ(0, wait_for_notification(1));
1161 ASSERT_FALSE(mock_replayer.is_replaying());
1162
1163 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1164 mock_local_image_ctx,
1165 mock_remote_image_ctx));
1166}
1167
1168TEST_F(TestMockImageReplayerSnapshotReplayer, ResyncRequested) {
1169 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1170 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1171
1172 MockThreads mock_threads(m_threads);
1173 expect_work_queue_repeatedly(mock_threads);
1174
1175 MockReplayerListener mock_replayer_listener;
1176 expect_notification(mock_threads, mock_replayer_listener);
1177
1178 InSequence seq;
1179
1180 MockInstanceWatcher mock_instance_watcher;
1181 MockImageMeta mock_image_meta;
1182 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1183 mock_remote_image_ctx,
1184 mock_image_meta);
1185 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1186 "local mirror uuid", &m_pool_meta_cache,
1187 &mock_state_builder, &mock_replayer_listener};
1188 m_pool_meta_cache.set_remote_pool_meta(
1189 m_remote_io_ctx.get_id(),
1190 {"remote mirror uuid", "remote mirror peer uuid"});
1191
1192 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1193 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1194 mock_local_image_ctx,
1195 mock_remote_image_ctx,
1196 mock_replayer_listener,
1197 mock_image_meta,
1198 &update_watch_ctx));
1199
1200 // idle
1201 expect_load_image_meta(mock_image_meta, true, 0);
1202
1203 // wake-up replayer
1204 update_watch_ctx->handle_notify();
1205
1206 // wait for sync to complete and expect replay complete
1207 ASSERT_EQ(0, wait_for_notification(1));
1208 ASSERT_FALSE(mock_replayer.is_replaying());
1209
1210 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1211 mock_local_image_ctx,
1212 mock_remote_image_ctx));
1213}
1214
1215TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterLocalUpdateWatcherError) {
1216 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1217 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1218
1219 MockThreads mock_threads(m_threads);
1220 expect_work_queue_repeatedly(mock_threads);
1221
1222 InSequence seq;
1223
1224 MockInstanceWatcher mock_instance_watcher;
1225 MockImageMeta mock_image_meta;
1226 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1227 mock_remote_image_ctx,
1228 mock_image_meta);
1229 MockReplayerListener mock_replayer_listener;
1230 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1231 "local mirror uuid", &m_pool_meta_cache,
1232 &mock_state_builder, &mock_replayer_listener};
1233 m_pool_meta_cache.set_remote_pool_meta(
1234 m_remote_io_ctx.get_id(),
1235 {"remote mirror uuid", "remote mirror peer uuid"});
1236
1237 // init
1238 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1239 expect_register_update_watcher(mock_local_image_ctx, &update_watch_ctx, 123,
1240 -EINVAL);
1241
1242 // fire init
1243 C_SaferCond init_ctx;
1244 mock_replayer.init(&init_ctx);
1245 ASSERT_EQ(-EINVAL, init_ctx.wait());
1246}
1247
1248TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterRemoteUpdateWatcherError) {
1249 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1250 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1251
1252 MockThreads mock_threads(m_threads);
1253 expect_work_queue_repeatedly(mock_threads);
1254
1255 InSequence seq;
1256
1257 MockInstanceWatcher mock_instance_watcher;
1258 MockImageMeta mock_image_meta;
1259 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1260 mock_remote_image_ctx,
1261 mock_image_meta);
1262 MockReplayerListener mock_replayer_listener;
1263 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1264 "local mirror uuid", &m_pool_meta_cache,
1265 &mock_state_builder, &mock_replayer_listener};
1266 m_pool_meta_cache.set_remote_pool_meta(
1267 m_remote_io_ctx.get_id(),
1268 {"remote mirror uuid", "remote mirror peer uuid"});
1269
1270 // init
1271 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1272 expect_register_update_watcher(mock_local_image_ctx, &update_watch_ctx, 123,
1273 0);
1274 expect_register_update_watcher(mock_remote_image_ctx, &update_watch_ctx, 234,
1275 -EINVAL);
1276
1277 expect_unregister_update_watcher(mock_local_image_ctx, 123, 0);
1278
1279 // fire init
1280 C_SaferCond init_ctx;
1281 mock_replayer.init(&init_ctx);
1282 ASSERT_EQ(-EINVAL, init_ctx.wait());
1283}
1284
1285TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterRemoteUpdateWatcherError) {
1286 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1287 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1288
1289 MockThreads mock_threads(m_threads);
1290 expect_work_queue_repeatedly(mock_threads);
1291
1292 MockReplayerListener mock_replayer_listener;
1293 expect_notification(mock_threads, mock_replayer_listener);
1294
1295 InSequence seq;
1296
1297 MockInstanceWatcher mock_instance_watcher;
1298 MockImageMeta mock_image_meta;
1299 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1300 mock_remote_image_ctx,
1301 mock_image_meta);
1302 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1303 "local mirror uuid", &m_pool_meta_cache,
1304 &mock_state_builder, &mock_replayer_listener};
1305 m_pool_meta_cache.set_remote_pool_meta(
1306 m_remote_io_ctx.get_id(),
1307 {"remote mirror uuid", "remote mirror peer uuid"});
1308
1309 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1310 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1311 mock_local_image_ctx,
1312 mock_remote_image_ctx,
1313 mock_replayer_listener,
1314 mock_image_meta,
1315 &update_watch_ctx));
1316
1317
1318 // shut down
1319 expect_unregister_update_watcher(mock_remote_image_ctx, 234, -EINVAL);
1320 expect_unregister_update_watcher(mock_local_image_ctx, 123, 0);
1321
1322 C_SaferCond shutdown_ctx;
1323 mock_replayer.shut_down(&shutdown_ctx);
1324 ASSERT_EQ(-EINVAL, shutdown_ctx.wait());
1325}
1326
1327TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterLocalUpdateWatcherError) {
1328 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1329 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1330
1331 MockThreads mock_threads(m_threads);
1332 expect_work_queue_repeatedly(mock_threads);
1333
1334 MockReplayerListener mock_replayer_listener;
1335 expect_notification(mock_threads, mock_replayer_listener);
1336
1337 InSequence seq;
1338
1339 MockInstanceWatcher mock_instance_watcher;
1340 MockImageMeta mock_image_meta;
1341 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1342 mock_remote_image_ctx,
1343 mock_image_meta);
1344 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1345 "local mirror uuid", &m_pool_meta_cache,
1346 &mock_state_builder, &mock_replayer_listener};
1347 m_pool_meta_cache.set_remote_pool_meta(
1348 m_remote_io_ctx.get_id(),
1349 {"remote mirror uuid", "remote mirror peer uuid"});
1350
1351 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1352 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1353 mock_local_image_ctx,
1354 mock_remote_image_ctx,
1355 mock_replayer_listener,
1356 mock_image_meta,
1357 &update_watch_ctx));
1358
1359
1360 // shut down
1361 expect_unregister_update_watcher(mock_remote_image_ctx, 234, 0);
1362 expect_unregister_update_watcher(mock_local_image_ctx, 123, -EINVAL);
1363
1364 C_SaferCond shutdown_ctx;
1365 mock_replayer.shut_down(&shutdown_ctx);
1366 ASSERT_EQ(-EINVAL, shutdown_ctx.wait());
1367}
1368
1369TEST_F(TestMockImageReplayerSnapshotReplayer, LoadImageMetaError) {
1370 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1371 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1372
1373 MockThreads mock_threads(m_threads);
1374 expect_work_queue_repeatedly(mock_threads);
1375
1376 MockReplayerListener mock_replayer_listener;
1377 expect_notification(mock_threads, mock_replayer_listener);
1378
1379 InSequence seq;
1380
1381 MockInstanceWatcher mock_instance_watcher;
1382 MockImageMeta mock_image_meta;
1383 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1384 mock_remote_image_ctx,
1385 mock_image_meta);
1386 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1387 "local mirror uuid", &m_pool_meta_cache,
1388 &mock_state_builder, &mock_replayer_listener};
1389 m_pool_meta_cache.set_remote_pool_meta(
1390 m_remote_io_ctx.get_id(),
1391 {"remote mirror uuid", "remote mirror peer uuid"});
1392
1393 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1394 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1395 mock_local_image_ctx,
1396 mock_remote_image_ctx,
1397 mock_replayer_listener,
1398 mock_image_meta,
1399 &update_watch_ctx));
1400
1401 // sync
1402 expect_load_image_meta(mock_image_meta, false, -EINVAL);
1403
1404 // wake-up replayer
1405 update_watch_ctx->handle_notify();
1406
1407 // wait for sync to complete and expect replay complete
1408 ASSERT_EQ(0, wait_for_notification(1));
1409 ASSERT_FALSE(mock_replayer.is_replaying());
1410 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
1411
1412 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1413 mock_local_image_ctx,
1414 mock_remote_image_ctx));
1415}
1416
1417TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshLocalImageError) {
1418 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1419 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1420
1421 MockThreads mock_threads(m_threads);
1422 expect_work_queue_repeatedly(mock_threads);
1423
1424 MockReplayerListener mock_replayer_listener;
1425 expect_notification(mock_threads, mock_replayer_listener);
1426
1427 InSequence seq;
1428
1429 MockInstanceWatcher mock_instance_watcher;
1430 MockImageMeta mock_image_meta;
1431 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1432 mock_remote_image_ctx,
1433 mock_image_meta);
1434 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1435 "local mirror uuid", &m_pool_meta_cache,
1436 &mock_state_builder, &mock_replayer_listener};
1437 m_pool_meta_cache.set_remote_pool_meta(
1438 m_remote_io_ctx.get_id(),
1439 {"remote mirror uuid", "remote mirror peer uuid"});
1440
1441 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1442 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1443 mock_local_image_ctx,
1444 mock_remote_image_ctx,
1445 mock_replayer_listener,
1446 mock_image_meta,
1447 &update_watch_ctx));
1448
1449 // sync
1450 expect_load_image_meta(mock_image_meta, false, 0);
1451 expect_is_refresh_required(mock_local_image_ctx, true);
1452 expect_refresh(mock_local_image_ctx, {}, -EINVAL);
1453
1454 // wake-up replayer
1455 update_watch_ctx->handle_notify();
1456
1457 // wait for sync to complete and expect replay complete
1458 ASSERT_EQ(0, wait_for_notification(1));
1459 ASSERT_FALSE(mock_replayer.is_replaying());
1460 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
1461
1462 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1463 mock_local_image_ctx,
1464 mock_remote_image_ctx));
1465}
1466
1467TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshRemoteImageError) {
1468 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1469 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1470
1471 MockThreads mock_threads(m_threads);
1472 expect_work_queue_repeatedly(mock_threads);
1473
1474 MockReplayerListener mock_replayer_listener;
1475 expect_notification(mock_threads, mock_replayer_listener);
1476
1477 InSequence seq;
1478
1479 MockInstanceWatcher mock_instance_watcher;
1480 MockImageMeta mock_image_meta;
1481 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1482 mock_remote_image_ctx,
1483 mock_image_meta);
1484 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1485 "local mirror uuid", &m_pool_meta_cache,
1486 &mock_state_builder, &mock_replayer_listener};
1487 m_pool_meta_cache.set_remote_pool_meta(
1488 m_remote_io_ctx.get_id(),
1489 {"remote mirror uuid", "remote mirror peer uuid"});
1490
1491 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1492 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1493 mock_local_image_ctx,
1494 mock_remote_image_ctx,
1495 mock_replayer_listener,
1496 mock_image_meta,
1497 &update_watch_ctx));
1498
1499 // sync
1500 expect_load_image_meta(mock_image_meta, false, 0);
1501 expect_is_refresh_required(mock_local_image_ctx, false);
1502 expect_is_refresh_required(mock_remote_image_ctx, true);
1503 expect_refresh(mock_remote_image_ctx, {}, -EINVAL);
1504
1505 // wake-up replayer
1506 update_watch_ctx->handle_notify();
1507
1508 // wait for sync to complete and expect replay complete
1509 ASSERT_EQ(0, wait_for_notification(1));
1510 ASSERT_FALSE(mock_replayer.is_replaying());
1511 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
1512
1513 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1514 mock_local_image_ctx,
1515 mock_remote_image_ctx));
1516}
1517
1518TEST_F(TestMockImageReplayerSnapshotReplayer, CopySnapshotsError) {
1519 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1520 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1521
1522 MockThreads mock_threads(m_threads);
1523 expect_work_queue_repeatedly(mock_threads);
1524
1525 MockReplayerListener mock_replayer_listener;
1526 expect_notification(mock_threads, mock_replayer_listener);
1527
1528 InSequence seq;
1529
1530 MockInstanceWatcher mock_instance_watcher;
1531 MockImageMeta mock_image_meta;
1532 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1533 mock_remote_image_ctx,
1534 mock_image_meta);
1535 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1536 "local mirror uuid", &m_pool_meta_cache,
1537 &mock_state_builder, &mock_replayer_listener};
1538 m_pool_meta_cache.set_remote_pool_meta(
1539 m_remote_io_ctx.get_id(),
1540 {"remote mirror uuid", "remote mirror peer uuid"});
1541
1542 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1543 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1544 mock_local_image_ctx,
1545 mock_remote_image_ctx,
1546 mock_replayer_listener,
1547 mock_image_meta,
1548 &update_watch_ctx));
1549
1550 // inject snapshot
1551 mock_remote_image_ctx.snap_info = {
1552 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1553 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"}, "",
1911f103 1554 CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
1555 0, {}, 0, 0, {}}}};
1556
1557 // sync snap1
1558 expect_load_image_meta(mock_image_meta, false, 0);
1559 expect_is_refresh_required(mock_local_image_ctx, false);
1560 expect_is_refresh_required(mock_remote_image_ctx, false);
1561 MockSnapshotCopyRequest mock_snapshot_copy_request;
1562 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
1563 -EINVAL);
1564
1565 // wake-up replayer
1566 update_watch_ctx->handle_notify();
1567
1568 // wait for sync to complete and expect replay complete
1569 ASSERT_EQ(0, wait_for_notification(1));
1570 ASSERT_FALSE(mock_replayer.is_replaying());
1571 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
1572
1573 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1574 mock_local_image_ctx,
1575 mock_remote_image_ctx));
1576}
1577
1578TEST_F(TestMockImageReplayerSnapshotReplayer, GetImageStateError) {
1579 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1580 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1581
1582 MockThreads mock_threads(m_threads);
1583 expect_work_queue_repeatedly(mock_threads);
1584
1585 MockReplayerListener mock_replayer_listener;
1586 expect_notification(mock_threads, mock_replayer_listener);
1587
1588 InSequence seq;
1589
1590 MockInstanceWatcher mock_instance_watcher;
1591 MockImageMeta mock_image_meta;
1592 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1593 mock_remote_image_ctx,
1594 mock_image_meta);
1595 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1596 "local mirror uuid", &m_pool_meta_cache,
1597 &mock_state_builder, &mock_replayer_listener};
1598 m_pool_meta_cache.set_remote_pool_meta(
1599 m_remote_io_ctx.get_id(),
1600 {"remote mirror uuid", "remote mirror peer uuid"});
1601
1602 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1603 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1604 mock_local_image_ctx,
1605 mock_remote_image_ctx,
1606 mock_replayer_listener,
1607 mock_image_meta,
1608 &update_watch_ctx));
1609
1610 // inject snapshot
1611 mock_remote_image_ctx.snap_info = {
1612 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1613 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"}, "",
1911f103 1614 CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
1615 0, {}, 0, 0, {}}}};
1616
1617 // sync snap1
1618 expect_load_image_meta(mock_image_meta, false, 0);
1619 expect_is_refresh_required(mock_local_image_ctx, false);
1620 expect_is_refresh_required(mock_remote_image_ctx, false);
1621 MockSnapshotCopyRequest mock_snapshot_copy_request;
1622 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
1623 0);
1624 MockGetImageStateRequest mock_get_image_state_request;
1625 expect_get_image_state(mock_get_image_state_request, 1, -EINVAL);
1626
1627 // wake-up replayer
1628 update_watch_ctx->handle_notify();
1629
1630 // wait for sync to complete and expect replay complete
1631 ASSERT_EQ(0, wait_for_notification(1));
1632 ASSERT_FALSE(mock_replayer.is_replaying());
1633 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
1634
1635 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1636 mock_local_image_ctx,
1637 mock_remote_image_ctx));
1638}
1639
1640TEST_F(TestMockImageReplayerSnapshotReplayer, CreateNonPrimarySnapshotError) {
1641 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1642 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1643
1644 MockThreads mock_threads(m_threads);
1645 expect_work_queue_repeatedly(mock_threads);
1646
1647 MockReplayerListener mock_replayer_listener;
1648 expect_notification(mock_threads, mock_replayer_listener);
1649
1650 InSequence seq;
1651
1652 MockInstanceWatcher mock_instance_watcher;
1653 MockImageMeta mock_image_meta;
1654 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1655 mock_remote_image_ctx,
1656 mock_image_meta);
1657 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1658 "local mirror uuid", &m_pool_meta_cache,
1659 &mock_state_builder, &mock_replayer_listener};
1660 m_pool_meta_cache.set_remote_pool_meta(
1661 m_remote_io_ctx.get_id(),
1662 {"remote mirror uuid", "remote mirror peer uuid"});
1663
1664 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1665 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1666 mock_local_image_ctx,
1667 mock_remote_image_ctx,
1668 mock_replayer_listener,
1669 mock_image_meta,
1670 &update_watch_ctx));
1671
1672 // inject snapshot
1673 mock_remote_image_ctx.snap_info = {
1674 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1675 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"}, "",
1911f103 1676 CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
1677 0, {}, 0, 0, {}}}};
1678
1679 // sync snap1
1680 expect_load_image_meta(mock_image_meta, false, 0);
1681 expect_is_refresh_required(mock_local_image_ctx, false);
1682 expect_is_refresh_required(mock_remote_image_ctx, false);
1683 MockSnapshotCopyRequest mock_snapshot_copy_request;
1684 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
1685 0);
1686 MockGetImageStateRequest mock_get_image_state_request;
1687 expect_get_image_state(mock_get_image_state_request, 1, 0);
1688 MockCreateNonPrimaryRequest mock_create_non_primary_request;
1689 expect_create_non_primary_request(mock_create_non_primary_request,
1690 false, "remote mirror uuid", 1,
1691 {{1, CEPH_NOSNAP}}, 11, -EINVAL);
1692
1693 // wake-up replayer
1694 update_watch_ctx->handle_notify();
1695
1696 // wait for sync to complete and expect replay complete
1697 ASSERT_EQ(0, wait_for_notification(1));
1698 ASSERT_FALSE(mock_replayer.is_replaying());
1699 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
1700
1701 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1702 mock_local_image_ctx,
1703 mock_remote_image_ctx));
1704}
1705
f67539c2
TL
1706TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateMirrorImageStateError) {
1707 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1708 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1709
1710 MockThreads mock_threads(m_threads);
1711 expect_work_queue_repeatedly(mock_threads);
1712
1713 MockReplayerListener mock_replayer_listener;
1714 expect_notification(mock_threads, mock_replayer_listener);
1715
1716 InSequence seq;
1717
1718 MockInstanceWatcher mock_instance_watcher;
1719 MockImageMeta mock_image_meta;
1720 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1721 mock_remote_image_ctx,
1722 mock_image_meta);
1723 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1724 "local mirror uuid", &m_pool_meta_cache,
1725 &mock_state_builder, &mock_replayer_listener};
1726 m_pool_meta_cache.set_remote_pool_meta(
1727 m_remote_io_ctx.get_id(),
1728 {"remote mirror uuid", "remote mirror peer uuid"});
1729
1730 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1731 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1732 mock_local_image_ctx,
1733 mock_remote_image_ctx,
1734 mock_replayer_listener,
1735 mock_image_meta,
1736 &update_watch_ctx));
1737
1738 // inject snapshot
1739 mock_remote_image_ctx.snap_info = {
1740 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1741 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"}, "",
1742 CEPH_NOSNAP, true, 0, {}},
1743 0, {}, 0, 0, {}}}};
1744
1745 // sync snap1
1746 expect_load_image_meta(mock_image_meta, false, 0);
1747 expect_is_refresh_required(mock_local_image_ctx, false);
1748 expect_is_refresh_required(mock_remote_image_ctx, false);
1749 MockSnapshotCopyRequest mock_snapshot_copy_request;
1750 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
1751 0);
1752 MockGetImageStateRequest mock_get_image_state_request;
1753 expect_get_image_state(mock_get_image_state_request, 1, 0);
1754 MockCreateNonPrimaryRequest mock_create_non_primary_request;
1755 expect_create_non_primary_request(mock_create_non_primary_request,
1756 false, "remote mirror uuid", 1,
1757 {{1, CEPH_NOSNAP}}, 11, 0);
1758 MockImageStateUpdateRequest mock_image_state_update_request;
1759 expect_update_mirror_image_state(mock_image_state_update_request, -EIO);
1760
1761 // wake-up replayer
1762 update_watch_ctx->handle_notify();
1763
1764 // wait for sync to complete and expect replay complete
1765 ASSERT_EQ(0, wait_for_notification(1));
1766 ASSERT_FALSE(mock_replayer.is_replaying());
1767 ASSERT_EQ(-EIO, mock_replayer.get_error_code());
1768
1769 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1770 mock_local_image_ctx,
1771 mock_remote_image_ctx));
1772}
1773
9f95a23c
TL
1774TEST_F(TestMockImageReplayerSnapshotReplayer, RequestSyncError) {
1775 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1776 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1777
1778 MockThreads mock_threads(m_threads);
1779 expect_work_queue_repeatedly(mock_threads);
1780
1781 MockReplayerListener mock_replayer_listener;
1782 expect_notification(mock_threads, mock_replayer_listener);
1783
1784 InSequence seq;
1785
1786 MockInstanceWatcher mock_instance_watcher;
1787 MockImageMeta mock_image_meta;
1788 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1789 mock_remote_image_ctx,
1790 mock_image_meta);
1791 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1792 "local mirror uuid", &m_pool_meta_cache,
1793 &mock_state_builder, &mock_replayer_listener};
1794 m_pool_meta_cache.set_remote_pool_meta(
1795 m_remote_io_ctx.get_id(),
1796 {"remote mirror uuid", "remote mirror peer uuid"});
1797
1798 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1799 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1800 mock_local_image_ctx,
1801 mock_remote_image_ctx,
1802 mock_replayer_listener,
1803 mock_image_meta,
1804 &update_watch_ctx));
1805
1806 // inject snapshot
1807 mock_remote_image_ctx.snap_info = {
1808 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1809 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"}, "",
1911f103 1810 CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
1811 0, {}, 0, 0, {}}}};
1812
1813 // sync snap1
1814 expect_load_image_meta(mock_image_meta, false, 0);
1815 expect_is_refresh_required(mock_local_image_ctx, false);
1816 expect_is_refresh_required(mock_remote_image_ctx, false);
1817 MockSnapshotCopyRequest mock_snapshot_copy_request;
1818 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
1819 0);
1820 MockGetImageStateRequest mock_get_image_state_request;
1821 expect_get_image_state(mock_get_image_state_request, 1, 0);
1822 MockCreateNonPrimaryRequest mock_create_non_primary_request;
1823 expect_create_non_primary_request(mock_create_non_primary_request,
1824 false, "remote mirror uuid", 1,
1825 {{1, CEPH_NOSNAP}}, 11, 0);
f67539c2
TL
1826 MockImageStateUpdateRequest mock_image_state_update_request;
1827 expect_update_mirror_image_state(mock_image_state_update_request, 0);
9f95a23c
TL
1828 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id,
1829 -ECANCELED);
1830
1831 // wake-up replayer
1832 update_watch_ctx->handle_notify();
1833
1834 // wait for sync to complete and expect replay complete
1835 ASSERT_EQ(0, wait_for_notification(1));
1836 ASSERT_FALSE(mock_replayer.is_replaying());
1837 ASSERT_EQ(-ECANCELED, mock_replayer.get_error_code());
1838
1839 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1840 mock_local_image_ctx,
1841 mock_remote_image_ctx));
9f95a23c
TL
1842}
1843
1844TEST_F(TestMockImageReplayerSnapshotReplayer, CopyImageError) {
1845 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1846 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1847
1848 MockThreads mock_threads(m_threads);
1849 expect_work_queue_repeatedly(mock_threads);
1850
1851 MockReplayerListener mock_replayer_listener;
1852 expect_notification(mock_threads, mock_replayer_listener);
1853
1854 InSequence seq;
1855
1856 MockInstanceWatcher mock_instance_watcher;
1857 MockImageMeta mock_image_meta;
1858 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1859 mock_remote_image_ctx,
1860 mock_image_meta);
1861 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1862 "local mirror uuid", &m_pool_meta_cache,
1863 &mock_state_builder, &mock_replayer_listener};
1864 m_pool_meta_cache.set_remote_pool_meta(
1865 m_remote_io_ctx.get_id(),
1866 {"remote mirror uuid", "remote mirror peer uuid"});
1867
1868 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1869 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1870 mock_local_image_ctx,
1871 mock_remote_image_ctx,
1872 mock_replayer_listener,
1873 mock_image_meta,
1874 &update_watch_ctx));
1875
1876 // inject snapshot
1877 mock_remote_image_ctx.snap_info = {
1878 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1879 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"}, "",
1911f103 1880 CEPH_NOSNAP,true, 0, {}},
9f95a23c
TL
1881 0, {}, 0, 0, {}}}};
1882
1883 // sync snap1
1884 expect_load_image_meta(mock_image_meta, false, 0);
1885 expect_is_refresh_required(mock_local_image_ctx, false);
1886 expect_is_refresh_required(mock_remote_image_ctx, false);
1887 MockSnapshotCopyRequest mock_snapshot_copy_request;
1888 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
1889 0);
1890 MockGetImageStateRequest mock_get_image_state_request;
1891 expect_get_image_state(mock_get_image_state_request, 1, 0);
1892 MockCreateNonPrimaryRequest mock_create_non_primary_request;
1893 expect_create_non_primary_request(mock_create_non_primary_request,
1894 false, "remote mirror uuid", 1,
1895 {{1, CEPH_NOSNAP}}, 11, 0);
f67539c2
TL
1896 MockImageStateUpdateRequest mock_image_state_update_request;
1897 expect_update_mirror_image_state(mock_image_state_update_request, 0);
9f95a23c
TL
1898 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
1899 MockImageCopyRequest mock_image_copy_request;
1900 expect_image_copy(mock_image_copy_request, 0, 1, 0, {},
1901 {{1, CEPH_NOSNAP}}, -EINVAL);
1911f103 1902 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
9f95a23c
TL
1903
1904 // wake-up replayer
1905 update_watch_ctx->handle_notify();
1906
1907 // wait for sync to complete and expect replay complete
1908 ASSERT_EQ(0, wait_for_notification(1));
1909 ASSERT_FALSE(mock_replayer.is_replaying());
1910 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
1911
1912 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1913 mock_local_image_ctx,
1914 mock_remote_image_ctx));
1915}
1916
1917TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateNonPrimarySnapshotError) {
1918 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1919 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1920
1921 MockThreads mock_threads(m_threads);
1922 expect_work_queue_repeatedly(mock_threads);
1923
1924 MockReplayerListener mock_replayer_listener;
1925 expect_notification(mock_threads, mock_replayer_listener);
1926
1927 InSequence seq;
1928
1929 MockInstanceWatcher mock_instance_watcher;
1930 MockImageMeta mock_image_meta;
1931 MockStateBuilder mock_state_builder(mock_local_image_ctx,
1932 mock_remote_image_ctx,
1933 mock_image_meta);
1934 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
1935 "local mirror uuid", &m_pool_meta_cache,
1936 &mock_state_builder, &mock_replayer_listener};
1937 m_pool_meta_cache.set_remote_pool_meta(
1938 m_remote_io_ctx.get_id(),
1939 {"remote mirror uuid", "remote mirror peer uuid"});
1940
1941 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
1942 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
1943 mock_local_image_ctx,
1944 mock_remote_image_ctx,
1945 mock_replayer_listener,
1946 mock_image_meta,
1947 &update_watch_ctx));
1948
1949 // inject snapshot
1950 mock_remote_image_ctx.snap_info = {
1951 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1952 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"}, "",
1911f103 1953 CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
1954 0, {}, 0, 0, {}}}};
1955
1956 // sync snap1
1957 expect_load_image_meta(mock_image_meta, false, 0);
1958 expect_is_refresh_required(mock_local_image_ctx, false);
1959 expect_is_refresh_required(mock_remote_image_ctx, false);
1960 MockSnapshotCopyRequest mock_snapshot_copy_request;
1961 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
1962 0);
1963 MockGetImageStateRequest mock_get_image_state_request;
1964 expect_get_image_state(mock_get_image_state_request, 1, 0);
1965 MockCreateNonPrimaryRequest mock_create_non_primary_request;
1966 expect_create_non_primary_request(mock_create_non_primary_request,
1967 false, "remote mirror uuid", 1,
1968 {{1, CEPH_NOSNAP}}, 11, 0);
f67539c2
TL
1969 MockImageStateUpdateRequest mock_image_state_update_request;
1970 expect_update_mirror_image_state(mock_image_state_update_request, 0);
9f95a23c
TL
1971 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
1972 MockImageCopyRequest mock_image_copy_request;
1973 expect_image_copy(mock_image_copy_request, 0, 1, 0, {},
1974 {{1, CEPH_NOSNAP}}, 0);
1975 MockApplyImageStateRequest mock_apply_state_request;
1976 expect_apply_image_state(mock_apply_state_request, 0);
1977 expect_mirror_image_snapshot_set_copy_progress(
1978 mock_local_image_ctx, 11, true, 0, -EINVAL);
1911f103 1979 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
9f95a23c
TL
1980
1981 // wake-up replayer
1982 update_watch_ctx->handle_notify();
1983
1984 // wait for sync to complete and expect replay complete
1985 ASSERT_EQ(0, wait_for_notification(1));
1986 ASSERT_FALSE(mock_replayer.is_replaying());
1987 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
1988
1989 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
1990 mock_local_image_ctx,
1991 mock_remote_image_ctx));
1992}
1993
1994TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkPeerError) {
1995 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
1996 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
1997
1998 MockThreads mock_threads(m_threads);
1999 expect_work_queue_repeatedly(mock_threads);
2000
2001 MockReplayerListener mock_replayer_listener;
2002 expect_notification(mock_threads, mock_replayer_listener);
2003
2004 InSequence seq;
2005
2006 MockInstanceWatcher mock_instance_watcher;
2007 MockImageMeta mock_image_meta;
2008 MockStateBuilder mock_state_builder(mock_local_image_ctx,
2009 mock_remote_image_ctx,
2010 mock_image_meta);
2011 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
2012 "local mirror uuid", &m_pool_meta_cache,
2013 &mock_state_builder, &mock_replayer_listener};
2014 m_pool_meta_cache.set_remote_pool_meta(
2015 m_remote_io_ctx.get_id(),
2016 {"remote mirror uuid", "remote mirror peer uuid"});
2017
2018 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
2019 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
2020 mock_local_image_ctx,
2021 mock_remote_image_ctx,
2022 mock_replayer_listener,
2023 mock_image_meta,
2024 &update_watch_ctx));
2025
2026 // inject snapshot
2027 mock_remote_image_ctx.snap_info = {
2028 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
2029 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"}, "",
1911f103 2030 CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
2031 0, {}, 0, 0, {}}},
2032 {2U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
2033 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
1911f103 2034 "", CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
2035 0, {}, 0, 0, {}}}};
2036 mock_local_image_ctx.snap_info = {
2037 {11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
2038 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
2039 1, true, 0, {}},
2040 0, {}, 0, 0, {}}}};
2041
2042 // sync snap2
2043 expect_load_image_meta(mock_image_meta, false, 0);
2044 expect_is_refresh_required(mock_local_image_ctx, false);
2045 expect_is_refresh_required(mock_remote_image_ctx, false);
2046 MockSnapshotCopyRequest mock_snapshot_copy_request;
2047 expect_snapshot_copy(mock_snapshot_copy_request, 1, 2, 11, {{2, CEPH_NOSNAP}},
2048 0);
2049 MockGetImageStateRequest mock_get_image_state_request;
2050 expect_get_image_state(mock_get_image_state_request, 2, 0);
2051 MockCreateNonPrimaryRequest mock_create_non_primary_request;
2052 expect_create_non_primary_request(mock_create_non_primary_request,
2053 false, "remote mirror uuid", 2,
2054 {{2, CEPH_NOSNAP}}, 12, 0);
2055 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
2056 MockImageCopyRequest mock_image_copy_request;
2057 expect_image_copy(mock_image_copy_request, 1, 2, 11, {},
2058 {{2, CEPH_NOSNAP}}, 0);
2059 MockApplyImageStateRequest mock_apply_state_request;
2060 expect_apply_image_state(mock_apply_state_request, 0);
2061 expect_mirror_image_snapshot_set_copy_progress(
2062 mock_local_image_ctx, 12, true, 0, 0);
2063 expect_notify_update(mock_local_image_ctx);
2064 MockUnlinkPeerRequest mock_unlink_peer_request;
2065 expect_unlink_peer(mock_unlink_peer_request, 1, "remote mirror peer uuid",
2066 -EINVAL);
2067 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
2068
2069 // wake-up replayer
2070 update_watch_ctx->handle_notify();
2071
2072 // wait for sync to complete and expect replay complete
2073 ASSERT_EQ(0, wait_for_notification(1));
2074 ASSERT_FALSE(mock_replayer.is_replaying());
2075 ASSERT_EQ(-EINVAL, mock_replayer.get_error_code());
2076
2077 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
2078 mock_local_image_ctx,
2079 mock_remote_image_ctx));
2080}
2081
2082TEST_F(TestMockImageReplayerSnapshotReplayer, SplitBrain) {
2083 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
2084 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
2085
2086 MockThreads mock_threads(m_threads);
2087 expect_work_queue_repeatedly(mock_threads);
2088
2089 MockReplayerListener mock_replayer_listener;
2090 expect_notification(mock_threads, mock_replayer_listener);
2091
2092 InSequence seq;
2093
2094 MockInstanceWatcher mock_instance_watcher;
2095 MockImageMeta mock_image_meta;
2096 MockStateBuilder mock_state_builder(mock_local_image_ctx,
2097 mock_remote_image_ctx,
2098 mock_image_meta);
2099 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
2100 "local mirror uuid", &m_pool_meta_cache,
2101 &mock_state_builder, &mock_replayer_listener};
2102 m_pool_meta_cache.set_remote_pool_meta(
2103 m_remote_io_ctx.get_id(),
2104 {"remote mirror uuid", "remote mirror peer uuid"});
2105
2106 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
2107 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
2108 mock_local_image_ctx,
2109 mock_remote_image_ctx,
2110 mock_replayer_listener,
2111 mock_image_meta,
2112 &update_watch_ctx));
2113
2114 // inject a primary demote to local image
2115 mock_remote_image_ctx.snap_info = {
2116 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
2117 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
1911f103 2118 "", CEPH_NOSNAP, true, 0, {}},
9f95a23c
TL
2119 0, {}, 0, 0, {}}}};
2120 mock_local_image_ctx.snap_info = {
2121 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
1911f103
TL
2122 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {}, "", CEPH_NOSNAP,
2123 true, 0, {}},
9f95a23c
TL
2124 0, {}, 0, 0, {}}}};
2125
2126 // detect split-brain
2127 expect_load_image_meta(mock_image_meta, false, 0);
2128 expect_is_refresh_required(mock_local_image_ctx, false);
2129 expect_is_refresh_required(mock_remote_image_ctx, false);
2130
2131 // wake-up replayer
2132 update_watch_ctx->handle_notify();
2133
2134 // wait for sync to complete and expect replay complete
2135 ASSERT_EQ(0, wait_for_notification(1));
2136 ASSERT_FALSE(mock_replayer.is_replaying());
2137 ASSERT_EQ(-EEXIST, mock_replayer.get_error_code());
2138 ASSERT_EQ(std::string{"split-brain"}, mock_replayer.get_error_description());
2139
2140 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
2141 mock_local_image_ctx,
2142 mock_remote_image_ctx));
2143}
2144
f67539c2
TL
2145TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteSnapshotMissingSplitBrain) {
2146 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
2147 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
2148
2149 MockThreads mock_threads(m_threads);
2150 expect_work_queue_repeatedly(mock_threads);
2151
2152 MockReplayerListener mock_replayer_listener;
2153 expect_notification(mock_threads, mock_replayer_listener);
2154
2155 InSequence seq;
2156
2157 MockInstanceWatcher mock_instance_watcher;
2158 MockImageMeta mock_image_meta;
2159 MockStateBuilder mock_state_builder(mock_local_image_ctx,
2160 mock_remote_image_ctx,
2161 mock_image_meta);
2162 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
2163 "local mirror uuid", &m_pool_meta_cache,
2164 &mock_state_builder, &mock_replayer_listener};
2165 m_pool_meta_cache.set_remote_pool_meta(
2166 m_remote_io_ctx.get_id(),
2167 {"remote mirror uuid", "remote mirror peer uuid"});
2168
2169 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
2170 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
2171 mock_local_image_ctx,
2172 mock_remote_image_ctx,
2173 mock_replayer_listener,
2174 mock_image_meta,
2175 &update_watch_ctx));
2176
2177 // inject a missing remote start snap (deleted)
2178 mock_local_image_ctx.snap_info = {
2179 {11U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
2180 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {},
2181 "remote mirror uuid", 1, true, 0,
2182 {{1, CEPH_NOSNAP}}},
2183 0, {}, 0, 0, {}}}};
2184 mock_remote_image_ctx.snap_info = {
2185 {2U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
2186 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
2187 "", CEPH_NOSNAP, true, 0, {}},
2188 0, {}, 0, 0, {}}},
2189 {3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
2190 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
2191 "", CEPH_NOSNAP, true, 0, {}},
2192 0, {}, 0, 0, {}}}};
2193
2194 // split-brain due to missing snapshot 1
2195 expect_load_image_meta(mock_image_meta, false, 0);
2196 expect_is_refresh_required(mock_local_image_ctx, false);
2197 expect_is_refresh_required(mock_remote_image_ctx, false);
2198
2199 // wake-up replayer
2200 update_watch_ctx->handle_notify();
2201
2202 // wait for sync to complete and expect replay complete
2203 ASSERT_EQ(0, wait_for_notification(1));
2204 ASSERT_FALSE(mock_replayer.is_replaying());
2205 ASSERT_EQ(-EEXIST, mock_replayer.get_error_code());
2206 ASSERT_EQ(std::string{"split-brain"}, mock_replayer.get_error_description());
2207
2208 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
2209 mock_local_image_ctx,
2210 mock_remote_image_ctx));
2211}
2212
1911f103
TL
2213TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
2214 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
2215 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
2216
2217 MockThreads mock_threads(m_threads);
2218 expect_work_queue_repeatedly(mock_threads);
2219
2220 MockReplayerListener mock_replayer_listener;
2221 expect_notification(mock_threads, mock_replayer_listener);
2222
2223 InSequence seq;
2224
2225 MockInstanceWatcher mock_instance_watcher;
2226 MockImageMeta mock_image_meta;
2227 MockStateBuilder mock_state_builder(mock_local_image_ctx,
2228 mock_remote_image_ctx,
2229 mock_image_meta);
2230 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
2231 "local mirror uuid", &m_pool_meta_cache,
2232 &mock_state_builder, &mock_replayer_listener};
2233 m_pool_meta_cache.set_remote_pool_meta(
2234 m_remote_io_ctx.get_id(),
2235 {"remote mirror uuid", "remote mirror peer uuid"});
2236
2237 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
2238 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
2239 mock_local_image_ctx,
2240 mock_remote_image_ctx,
2241 mock_replayer_listener,
2242 mock_image_meta,
2243 &update_watch_ctx));
2244
2245 // inject a primary demote to local image
2246 mock_remote_image_ctx.snap_info = {
2247 {1U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
2248 0, {}, 0, 0, {}}},
2249 {2U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
2250 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
2251 {"remote mirror peer uuid"}, "local mirror uuid", 12U, true, 0, {}},
2252 0, {}, 0, 0, {}}},
2253 {3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
2254 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
2255 "", CEPH_NOSNAP, true, 0, {}},
2256 0, {}, 0, 0, {}}}};
2257 mock_local_image_ctx.snap_ids = {
2258 {{cls::rbd::UserSnapshotNamespace{}, "snap1"}, 11},
2259 {{cls::rbd::MirrorSnapshotNamespace{}, "snap2"}, 12}};
2260 mock_local_image_ctx.snap_info = {
2261 {11U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
2262 0, {}, 0, 0, {}}},
2263 {12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
2264 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {}, "", CEPH_NOSNAP,
2265 true, 0, {}},
2266 0, {}, 0, 0, {}}}};
2267
2268 // attach to promoted remote image
2269 expect_load_image_meta(mock_image_meta, false, 0);
2270 expect_is_refresh_required(mock_local_image_ctx, false);
2271 expect_is_refresh_required(mock_remote_image_ctx, false);
2272 MockSnapshotCopyRequest mock_snapshot_copy_request;
2273 expect_snapshot_copy(mock_snapshot_copy_request, 2, 3, 12,
2274 {{2, 12}, {3, CEPH_NOSNAP}}, 0);
2275 MockGetImageStateRequest mock_get_image_state_request;
2276 expect_get_image_state(mock_get_image_state_request, 3, 0);
2277 MockCreateNonPrimaryRequest mock_create_non_primary_request;
2278 expect_create_non_primary_request(mock_create_non_primary_request,
2279 false, "remote mirror uuid", 3,
2280 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP}}, 13,
2281 0);
2282 expect_notify_sync_request(mock_instance_watcher, mock_local_image_ctx.id, 0);
2283 MockImageCopyRequest mock_image_copy_request;
2284 expect_image_copy(mock_image_copy_request, 2, 3, 12, {},
2285 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP}}, 0);
2286 MockApplyImageStateRequest mock_apply_state_request;
2287 expect_apply_image_state(mock_apply_state_request, 0);
2288 expect_mirror_image_snapshot_set_copy_progress(
2289 mock_local_image_ctx, 13, true, 0, 0);
2290 expect_notify_update(mock_local_image_ctx);
2291 MockUnlinkPeerRequest mock_unlink_peer_request;
2292 expect_unlink_peer(mock_unlink_peer_request, 2, "remote mirror peer uuid", 0);
2293 expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
2294
2295 // idle
2296 expect_load_image_meta(mock_image_meta, false, 0);
2297 expect_is_refresh_required(mock_local_image_ctx, true);
2298 expect_refresh(
2299 mock_local_image_ctx, {
2300 {11U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
2301 0, {}, 0, 0, {}}},
2302 {12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
2303 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {}, "", CEPH_NOSNAP,
2304 true, 0, {}},
2305 0, {}, 0, 0, {}}},
2306 {13U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
2307 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {},
2308 "remote mirror uuid", 3, true, 0,
2309 {{1, 11}, {2, 12}, {3, CEPH_NOSNAP}}},
2310 0, {}, 0, 0, {}}},
2311 }, 0);
2312 expect_is_refresh_required(mock_remote_image_ctx, true);
2313 expect_refresh(
2314 mock_remote_image_ctx, {
2315 {1U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
2316 0, {}, 0, 0, {}}},
2317 {2U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
2318 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
2319 {"remote mirror peer uuid"}, "local mirror uuid", 12U, true, 0, {}},
2320 0, {}, 0, 0, {}}},
2321 {3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
2322 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {}, "", CEPH_NOSNAP, true, 0,
2323 {}},
2324 0, {}, 0, 0, {}}}
2325 }, 0);
2326
2327 // wake-up replayer
2328 update_watch_ctx->handle_notify();
2329
2330 // wait for sync to complete and expect replay complete
2331 ASSERT_EQ(0, wait_for_notification(2));
2332 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
2333 mock_local_image_ctx,
2334 mock_remote_image_ctx));
2335}
2336
2337TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkRemoteSnapshot) {
2338 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
2339 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
2340
2341 // it should attempt to unlink from remote snap1 since we don't need it
2342 // anymore
2343 mock_local_image_ctx.snap_info = {
2344 {14U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
2345 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
2346 4, true, 0, {}},
2347 0, {}, 0, 0, {}}}};
2348 mock_remote_image_ctx.snap_info = {
2349 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
2350 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
2351 "", CEPH_NOSNAP, true, 0, {}},
2352 0, {}, 0, 0, {}}},
2353 {4U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
2354 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
2355 "", CEPH_NOSNAP, true, 0, {}},
2356 0, {}, 0, 0, {}}}};
2357
2358 MockThreads mock_threads(m_threads);
2359 expect_work_queue_repeatedly(mock_threads);
2360
2361 MockReplayerListener mock_replayer_listener;
2362 expect_notification(mock_threads, mock_replayer_listener);
2363
2364 InSequence seq;
2365
2366 MockInstanceWatcher mock_instance_watcher;
2367 MockImageMeta mock_image_meta;
2368 MockStateBuilder mock_state_builder(mock_local_image_ctx,
2369 mock_remote_image_ctx,
2370 mock_image_meta);
2371 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
2372 "local mirror uuid", &m_pool_meta_cache,
2373 &mock_state_builder, &mock_replayer_listener};
2374 m_pool_meta_cache.set_remote_pool_meta(
2375 m_remote_io_ctx.get_id(),
2376 {"remote mirror uuid", "remote mirror peer uuid"});
2377
2378 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
2379
2380 // init
2381 expect_register_update_watcher(mock_local_image_ctx, &update_watch_ctx, 123,
2382 0);
2383 expect_register_update_watcher(mock_remote_image_ctx, &update_watch_ctx, 234,
2384 0);
2385
2386 // unlink snap1
2387 expect_load_image_meta(mock_image_meta, false, 0);
2388 expect_is_refresh_required(mock_local_image_ctx, false);
2389 expect_is_refresh_required(mock_remote_image_ctx, false);
2390 MockUnlinkPeerRequest mock_unlink_peer_request;
2391 expect_unlink_peer(mock_unlink_peer_request, 1, "remote mirror peer uuid",
2392 0);
2393
2394 // idle
2395 expect_load_image_meta(mock_image_meta, false, 0);
2396 expect_is_refresh_required(mock_local_image_ctx, false);
2397 expect_is_refresh_required(mock_remote_image_ctx, true);
2398 expect_refresh(
2399 mock_remote_image_ctx, {
2400 {2U, librbd::SnapInfo{"snap2", cls::rbd::UserSnapshotNamespace{},
2401 0, {}, 0, 0, {}}},
2402 {3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
2403 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {""},
2404 "", CEPH_NOSNAP, true, 0, {}},
2405 0, {}, 0, 0, {}}},
2406 {4U, librbd::SnapInfo{"snap4", cls::rbd::MirrorSnapshotNamespace{
2407 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
2408 "", CEPH_NOSNAP, true, 0, {}},
2409 0, {}, 0, 0, {}}}
2410 }, 0);
2411
2412 // fire init
2413 C_SaferCond init_ctx;
2414 mock_replayer.init(&init_ctx);
2415 ASSERT_EQ(0, init_ctx.wait());
2416
2417 // wait for sync to complete
f6b5b4d7 2418 ASSERT_EQ(0, wait_for_notification(3));
1911f103
TL
2419
2420 // shut down
2421 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
2422 mock_local_image_ctx,
2423 mock_remote_image_ctx));
2424}
2425
2426TEST_F(TestMockImageReplayerSnapshotReplayer, SkipImageSync) {
2427 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
2428 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
2429
2430 mock_remote_image_ctx.snap_info = {
2431 {1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
2432 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
2433 "", 0U, true, 0, {}},
2434 0, {}, 0, 0, {}}}};
2435
2436 MockThreads mock_threads(m_threads);
2437 expect_work_queue_repeatedly(mock_threads);
2438
2439 MockReplayerListener mock_replayer_listener;
2440 expect_notification(mock_threads, mock_replayer_listener);
2441
2442 InSequence seq;
2443
2444 MockInstanceWatcher mock_instance_watcher;
2445 MockImageMeta mock_image_meta;
2446 MockStateBuilder mock_state_builder(mock_local_image_ctx,
2447 mock_remote_image_ctx,
2448 mock_image_meta);
2449 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
2450 "local mirror uuid", &m_pool_meta_cache,
2451 &mock_state_builder, &mock_replayer_listener};
2452 m_pool_meta_cache.set_remote_pool_meta(
2453 m_remote_io_ctx.get_id(),
2454 {"remote mirror uuid", "remote mirror peer uuid"});
2455
2456 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
2457
2458 // init
2459 expect_register_update_watcher(mock_local_image_ctx, &update_watch_ctx, 123,
2460 0);
2461 expect_register_update_watcher(mock_remote_image_ctx, &update_watch_ctx, 234,
2462 0);
2463
2464 // sync snap1
2465 expect_load_image_meta(mock_image_meta, false, 0);
2466 expect_is_refresh_required(mock_local_image_ctx, false);
2467 expect_is_refresh_required(mock_remote_image_ctx, false);
2468 MockSnapshotCopyRequest mock_snapshot_copy_request;
2469 expect_snapshot_copy(mock_snapshot_copy_request, 0, 1, 0, {{1, CEPH_NOSNAP}},
2470 0);
2471 MockGetImageStateRequest mock_get_image_state_request;
2472 expect_get_image_state(mock_get_image_state_request, 1, 0);
2473 MockCreateNonPrimaryRequest mock_create_non_primary_request;
2474 expect_create_non_primary_request(mock_create_non_primary_request,
2475 false, "remote mirror uuid", 1,
2476 {{1, CEPH_NOSNAP}}, 11, 0);
f67539c2
TL
2477 MockImageStateUpdateRequest mock_image_state_update_request;
2478 expect_update_mirror_image_state(mock_image_state_update_request, 0);
1911f103
TL
2479 MockApplyImageStateRequest mock_apply_state_request;
2480 expect_apply_image_state(mock_apply_state_request, 0);
2481 expect_mirror_image_snapshot_set_copy_progress(
2482 mock_local_image_ctx, 11, true, 0, 0);
2483 expect_notify_update(mock_local_image_ctx);
2484
2485 // idle
2486 expect_load_image_meta(mock_image_meta, false, 0);
2487 expect_is_refresh_required(mock_local_image_ctx, true);
2488 expect_refresh(
2489 mock_local_image_ctx, {
2490 {11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
2491 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
2492 1, true, 0, {{1, CEPH_NOSNAP}}},
2493 0, {}, 0, 0, {}}},
2494 }, 0);
2495 expect_is_refresh_required(mock_remote_image_ctx, false);
2496
2497 // fire init
2498 C_SaferCond init_ctx;
2499 mock_replayer.init(&init_ctx);
2500 ASSERT_EQ(0, init_ctx.wait());
2501
2502 // wait for sync to complete
2503 ASSERT_EQ(0, wait_for_notification(3));
2504
2505 // shut down
2506 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
2507 mock_local_image_ctx,
2508 mock_remote_image_ctx));
2509}
2510
522d829b
TL
2511TEST_F(TestMockImageReplayerSnapshotReplayer, ImageNameUpdated) {
2512 librbd::MockTestImageCtx mock_local_image_ctx{*m_local_image_ctx};
2513 librbd::MockTestImageCtx mock_remote_image_ctx{*m_remote_image_ctx};
2514
2515 MockThreads mock_threads(m_threads);
2516 expect_work_queue_repeatedly(mock_threads);
2517
2518 MockReplayerListener mock_replayer_listener;
2519 expect_notification(mock_threads, mock_replayer_listener);
2520
2521 InSequence seq;
2522
2523 MockInstanceWatcher mock_instance_watcher;
2524 MockImageMeta mock_image_meta;
2525 MockStateBuilder mock_state_builder(mock_local_image_ctx,
2526 mock_remote_image_ctx,
2527 mock_image_meta);
2528 MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
2529 "local mirror uuid", &m_pool_meta_cache,
2530 &mock_state_builder, &mock_replayer_listener};
2531 m_pool_meta_cache.set_remote_pool_meta(
2532 m_remote_io_ctx.get_id(),
2533 {"remote mirror uuid", "remote mirror peer uuid"});
2534
2535 librbd::UpdateWatchCtx* update_watch_ctx = nullptr;
2536 ASSERT_EQ(0, init_entry_replayer(mock_replayer, mock_threads,
2537 mock_local_image_ctx,
2538 mock_remote_image_ctx,
2539 mock_replayer_listener,
2540 mock_image_meta,
2541 &update_watch_ctx));
2542
2543 // change the name of the image
2544 mock_local_image_ctx.name = "NEW NAME";
2545
2546 // idle
2547 expect_load_image_meta(mock_image_meta, true, 0);
2548
2549 // wake-up replayer
2550 update_watch_ctx->handle_notify();
2551
2552 // wait for sync to complete and expect replay complete
2553 ASSERT_EQ(0, wait_for_notification(2));
2554 auto image_spec = image_replayer::util::compute_image_spec(m_local_io_ctx,
2555 "NEW NAME");
2556 ASSERT_EQ(image_spec, mock_replayer.get_image_spec());
2557 ASSERT_FALSE(mock_replayer.is_replaying());
2558
2559 // shut down
2560 ASSERT_EQ(0, shut_down_entry_replayer(mock_replayer, mock_threads,
2561 mock_local_image_ctx,
2562 mock_remote_image_ctx));
2563}
2564
9f95a23c
TL
2565} // namespace snapshot
2566} // namespace image_replayer
2567} // namespace mirror
2568} // namespace rbd