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