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