]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/image_replayer/test_mock_BootstrapRequest.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / rbd_mirror / image_replayer / test_mock_BootstrapRequest.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/journal/TypeTraits.h"
6 #include "tools/rbd_mirror/InstanceWatcher.h"
7 #include "tools/rbd_mirror/Threads.h"
8 #include "tools/rbd_mirror/image_replayer/BootstrapRequest.h"
9 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
10 #include "tools/rbd_mirror/image_replayer/CreateImageRequest.h"
11 #include "tools/rbd_mirror/image_replayer/IsPrimaryRequest.h"
12 #include "tools/rbd_mirror/image_replayer/OpenImageRequest.h"
13 #include "tools/rbd_mirror/image_replayer/OpenLocalImageRequest.h"
14 #include "test/journal/mock/MockJournaler.h"
15 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
16 #include "test/librbd/mock/MockImageCtx.h"
17 #include "test/librbd/mock/MockJournal.h"
18
19 namespace librbd {
20
21 namespace {
22
23 struct MockTestImageCtx : public librbd::MockImageCtx {
24 MockTestImageCtx(librbd::ImageCtx &image_ctx)
25 : librbd::MockImageCtx(image_ctx) {
26 }
27 };
28
29 } // anonymous namespace
30
31 namespace journal {
32
33 template <>
34 struct TypeTraits<librbd::MockTestImageCtx> {
35 typedef ::journal::MockJournaler Journaler;
36 };
37
38 } // namespace journal
39
40 namespace util {
41
42 static std::string s_image_id;
43
44 template <>
45 std::string generate_image_id<MockTestImageCtx>(librados::IoCtx&) {
46 ceph_assert(!s_image_id.empty());
47 return s_image_id;
48 }
49
50 } // namespace util
51 } // namespace librbd
52
53 namespace rbd {
54 namespace mirror {
55
56 class ProgressContext;
57
58 template <>
59 struct Threads<librbd::MockTestImageCtx> {
60 Mutex &timer_lock;
61 SafeTimer *timer;
62 ContextWQ *work_queue;
63
64 Threads(Threads<librbd::ImageCtx> *threads)
65 : timer_lock(threads->timer_lock), timer(threads->timer),
66 work_queue(threads->work_queue) {
67 }
68 };
69
70 template<>
71 struct ImageSync<librbd::MockTestImageCtx> {
72 static ImageSync* s_instance;
73 Context *on_finish = nullptr;
74
75 static ImageSync* create(
76 librbd::MockTestImageCtx *local_image_ctx,
77 librbd::MockTestImageCtx *remote_image_ctx,
78 SafeTimer *timer, Mutex *timer_lock,
79 const std::string &mirror_uuid, ::journal::MockJournaler *journaler,
80 librbd::journal::MirrorPeerClientMeta *client_meta, ContextWQ *work_queue,
81 InstanceWatcher<librbd::MockTestImageCtx> *instance_watcher,
82 Context *on_finish, ProgressContext *progress_ctx) {
83 ceph_assert(s_instance != nullptr);
84 s_instance->on_finish = on_finish;
85 return s_instance;
86 }
87
88 ImageSync() {
89 ceph_assert(s_instance == nullptr);
90 s_instance = this;
91 }
92 ~ImageSync() {
93 s_instance = nullptr;
94 }
95
96 MOCK_METHOD0(get, void());
97 MOCK_METHOD0(put, void());
98 MOCK_METHOD0(send, void());
99 MOCK_METHOD0(cancel, void());
100 };
101
102 ImageSync<librbd::MockTestImageCtx>*
103 ImageSync<librbd::MockTestImageCtx>::s_instance = nullptr;
104
105 template<>
106 struct InstanceWatcher<librbd::MockTestImageCtx> {
107 };
108
109 namespace image_replayer {
110
111 template<>
112 struct CloseImageRequest<librbd::MockTestImageCtx> {
113 static CloseImageRequest* s_instance;
114 librbd::MockTestImageCtx **image_ctx = nullptr;
115 Context *on_finish = nullptr;
116
117 static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx,
118 Context *on_finish) {
119 ceph_assert(s_instance != nullptr);
120 s_instance->image_ctx = image_ctx;
121 s_instance->on_finish = on_finish;
122 s_instance->construct(*image_ctx);
123 return s_instance;
124 }
125
126 CloseImageRequest() {
127 ceph_assert(s_instance == nullptr);
128 s_instance = this;
129 }
130 ~CloseImageRequest() {
131 s_instance = nullptr;
132 }
133
134 MOCK_METHOD1(construct, void(librbd::MockTestImageCtx *image_ctx));
135 MOCK_METHOD0(send, void());
136 };
137
138 template<>
139 struct CreateImageRequest<librbd::MockTestImageCtx> {
140 static CreateImageRequest* s_instance;
141 Context *on_finish = nullptr;
142
143 static CreateImageRequest* create(Threads<librbd::MockTestImageCtx>* threads,
144 librados::IoCtx &local_io_ctx,
145 const std::string &global_image_id,
146 const std::string &remote_mirror_uuid,
147 const std::string &local_image_name,
148 const std::string &local_image_id,
149 librbd::MockTestImageCtx *remote_image_ctx,
150 Context *on_finish) {
151 ceph_assert(s_instance != nullptr);
152 s_instance->on_finish = on_finish;
153 s_instance->construct(local_image_id);
154 return s_instance;
155 }
156
157 CreateImageRequest() {
158 ceph_assert(s_instance == nullptr);
159 s_instance = this;
160 }
161 ~CreateImageRequest() {
162 s_instance = nullptr;
163 }
164
165 MOCK_METHOD1(construct, void(const std::string&));
166 MOCK_METHOD0(send, void());
167 };
168
169 template<>
170 struct IsPrimaryRequest<librbd::MockTestImageCtx> {
171 static IsPrimaryRequest* s_instance;
172 bool *primary = nullptr;
173 Context *on_finish = nullptr;
174
175 static IsPrimaryRequest* create(librbd::MockTestImageCtx *image_ctx,
176 bool *primary, Context *on_finish) {
177 ceph_assert(s_instance != nullptr);
178 s_instance->primary = primary;
179 s_instance->on_finish = on_finish;
180 return s_instance;
181 }
182
183 IsPrimaryRequest() {
184 ceph_assert(s_instance == nullptr);
185 s_instance = this;
186 }
187 ~IsPrimaryRequest() {
188 s_instance = nullptr;
189 }
190
191 MOCK_METHOD0(send, void());
192 };
193
194 template<>
195 struct OpenImageRequest<librbd::MockTestImageCtx> {
196 static OpenImageRequest* s_instance;
197 librbd::MockTestImageCtx **image_ctx = nullptr;
198 Context *on_finish = nullptr;
199
200 static OpenImageRequest* create(librados::IoCtx &io_ctx,
201 librbd::MockTestImageCtx **image_ctx,
202 const std::string &image_id,
203 bool read_only, Context *on_finish) {
204 ceph_assert(s_instance != nullptr);
205 s_instance->image_ctx = image_ctx;
206 s_instance->on_finish = on_finish;
207 s_instance->construct(io_ctx, image_id);
208 return s_instance;
209 }
210
211 OpenImageRequest() {
212 ceph_assert(s_instance == nullptr);
213 s_instance = this;
214 }
215 ~OpenImageRequest() {
216 s_instance = nullptr;
217 }
218
219 MOCK_METHOD2(construct, void(librados::IoCtx &io_ctx,
220 const std::string &image_id));
221 MOCK_METHOD0(send, void());
222 };
223
224 template<>
225 struct OpenLocalImageRequest<librbd::MockTestImageCtx> {
226 static OpenLocalImageRequest* s_instance;
227 librbd::MockTestImageCtx **image_ctx = nullptr;
228 Context *on_finish = nullptr;
229
230 static OpenLocalImageRequest* create(librados::IoCtx &local_io_ctx,
231 librbd::MockTestImageCtx **local_image_ctx,
232 const std::string &local_image_id,
233 ContextWQ *work_queue,
234 Context *on_finish) {
235 ceph_assert(s_instance != nullptr);
236 s_instance->image_ctx = local_image_ctx;
237 s_instance->on_finish = on_finish;
238 s_instance->construct(local_io_ctx, local_image_id);
239 return s_instance;
240 }
241
242 OpenLocalImageRequest() {
243 ceph_assert(s_instance == nullptr);
244 s_instance = this;
245 }
246 ~OpenLocalImageRequest() {
247 s_instance = nullptr;
248 }
249
250 MOCK_METHOD2(construct, void(librados::IoCtx &io_ctx,
251 const std::string &image_id));
252 MOCK_METHOD0(send, void());
253 };
254
255 CloseImageRequest<librbd::MockTestImageCtx>*
256 CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
257 CreateImageRequest<librbd::MockTestImageCtx>*
258 CreateImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
259 IsPrimaryRequest<librbd::MockTestImageCtx>*
260 IsPrimaryRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
261 OpenImageRequest<librbd::MockTestImageCtx>*
262 OpenImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
263 OpenLocalImageRequest<librbd::MockTestImageCtx>*
264 OpenLocalImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
265
266 } // namespace image_replayer
267 } // namespace mirror
268 } // namespace rbd
269
270 // template definitions
271 #include "tools/rbd_mirror/image_replayer/BootstrapRequest.cc"
272
273 namespace rbd {
274 namespace mirror {
275 namespace image_replayer {
276
277 using ::testing::_;
278 using ::testing::DoAll;
279 using ::testing::InSequence;
280 using ::testing::Invoke;
281 using ::testing::Return;
282 using ::testing::SetArgPointee;
283 using ::testing::StrEq;
284 using ::testing::WithArg;
285
286 MATCHER_P(IsSameIoCtx, io_ctx, "") {
287 return &get_mock_io_ctx(arg) == &get_mock_io_ctx(*io_ctx);
288 }
289
290 class TestMockImageReplayerBootstrapRequest : public TestMockFixture {
291 public:
292 typedef Threads<librbd::MockTestImageCtx> MockThreads;
293 typedef BootstrapRequest<librbd::MockTestImageCtx> MockBootstrapRequest;
294 typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
295 typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest;
296 typedef ImageSync<librbd::MockTestImageCtx> MockImageSync;
297 typedef InstanceWatcher<librbd::MockTestImageCtx> MockInstanceWatcher;
298 typedef IsPrimaryRequest<librbd::MockTestImageCtx> MockIsPrimaryRequest;
299 typedef OpenImageRequest<librbd::MockTestImageCtx> MockOpenImageRequest;
300 typedef OpenLocalImageRequest<librbd::MockTestImageCtx> MockOpenLocalImageRequest;
301 typedef std::list<cls::journal::Tag> Tags;
302
303 void SetUp() override {
304 TestMockFixture::SetUp();
305
306 librbd::RBD rbd;
307 ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
308 ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
309 }
310
311 void create_local_image() {
312 librbd::RBD rbd;
313 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
314 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &m_local_image_ctx));
315 }
316
317 void expect_journaler_get_client(::journal::MockJournaler &mock_journaler,
318 const std::string &client_id,
319 cls::journal::Client &client, int r) {
320 EXPECT_CALL(mock_journaler, get_client(StrEq(client_id), _, _))
321 .WillOnce(DoAll(WithArg<1>(Invoke([client](cls::journal::Client *out_client) {
322 *out_client = client;
323 })),
324 WithArg<2>(Invoke([this, r](Context *on_finish) {
325 m_threads->work_queue->queue(on_finish, r);
326 }))));
327 }
328
329 void expect_journaler_get_tags(::journal::MockJournaler &mock_journaler,
330 uint64_t tag_class, const Tags& tags,
331 int r) {
332 EXPECT_CALL(mock_journaler, get_tags(tag_class, _, _))
333 .WillOnce(DoAll(WithArg<1>(Invoke([tags](Tags *out_tags) {
334 *out_tags = tags;
335 })),
336 WithArg<2>(Invoke([this, r](Context *on_finish) {
337 m_threads->work_queue->queue(on_finish, r);
338 }))));
339 }
340
341 void expect_journaler_register_client(::journal::MockJournaler &mock_journaler,
342 const librbd::journal::ClientData &client_data,
343 int r) {
344 bufferlist bl;
345 encode(client_data, bl);
346
347 EXPECT_CALL(mock_journaler, register_client(ContentsEqual(bl), _))
348 .WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) {
349 m_threads->work_queue->queue(on_finish, r);
350 })));
351 }
352
353 void expect_journaler_unregister_client(::journal::MockJournaler &mock_journaler,
354 int r) {
355 EXPECT_CALL(mock_journaler, unregister_client(_))
356 .WillOnce(Invoke([this, r](Context *on_finish) {
357 m_threads->work_queue->queue(on_finish, r);
358 }));
359 }
360
361 void expect_journaler_update_client(::journal::MockJournaler &mock_journaler,
362 const librbd::journal::ClientData &client_data,
363 int r) {
364 bufferlist bl;
365 encode(client_data, bl);
366
367 EXPECT_CALL(mock_journaler, update_client(ContentsEqual(bl), _))
368 .WillOnce(WithArg<1>(Invoke([this, r](Context *on_finish) {
369 m_threads->work_queue->queue(on_finish, r);
370 })));
371 }
372
373 void expect_open_image(MockOpenImageRequest &mock_open_image_request,
374 librados::IoCtx &io_ctx, const std::string &image_id,
375 librbd::MockTestImageCtx &mock_image_ctx, int r) {
376 EXPECT_CALL(mock_open_image_request, construct(IsSameIoCtx(&io_ctx), image_id));
377 EXPECT_CALL(mock_open_image_request, send())
378 .WillOnce(Invoke([this, &mock_open_image_request, &mock_image_ctx, r]() {
379 *mock_open_image_request.image_ctx = &mock_image_ctx;
380 m_threads->work_queue->queue(mock_open_image_request.on_finish, r);
381 }));
382 }
383
384 void expect_open_local_image(MockOpenLocalImageRequest &mock_open_local_image_request,
385 librados::IoCtx &io_ctx, const std::string &image_id,
386 librbd::MockTestImageCtx *mock_image_ctx, int r) {
387 EXPECT_CALL(mock_open_local_image_request,
388 construct(IsSameIoCtx(&io_ctx), image_id));
389 EXPECT_CALL(mock_open_local_image_request, send())
390 .WillOnce(Invoke([this, &mock_open_local_image_request, mock_image_ctx, r]() {
391 *mock_open_local_image_request.image_ctx = mock_image_ctx;
392 m_threads->work_queue->queue(mock_open_local_image_request.on_finish,
393 r);
394 }));
395 }
396
397 void expect_close_image(MockCloseImageRequest &mock_close_image_request,
398 librbd::MockTestImageCtx &mock_image_ctx, int r) {
399 EXPECT_CALL(mock_close_image_request, construct(&mock_image_ctx));
400 EXPECT_CALL(mock_close_image_request, send())
401 .WillOnce(Invoke([this, &mock_close_image_request, r]() {
402 *mock_close_image_request.image_ctx = nullptr;
403 m_threads->work_queue->queue(mock_close_image_request.on_finish, r);
404 }));
405 }
406
407 void expect_is_primary(MockIsPrimaryRequest &mock_is_primary_request,
408 bool primary, int r) {
409 EXPECT_CALL(mock_is_primary_request, send())
410 .WillOnce(Invoke([this, &mock_is_primary_request, primary, r]() {
411 *mock_is_primary_request.primary = primary;
412 m_threads->work_queue->queue(mock_is_primary_request.on_finish, r);
413 }));
414 }
415
416 void expect_journal_get_tag_tid(librbd::MockJournal &mock_journal,
417 uint64_t tag_tid) {
418 EXPECT_CALL(mock_journal, get_tag_tid()).WillOnce(Return(tag_tid));
419 }
420
421 void expect_journal_get_tag_data(librbd::MockJournal &mock_journal,
422 const librbd::journal::TagData &tag_data) {
423 EXPECT_CALL(mock_journal, get_tag_data()).WillOnce(Return(tag_data));
424 }
425
426 void expect_is_resync_requested(librbd::MockJournal &mock_journal,
427 bool do_resync, int r) {
428 EXPECT_CALL(mock_journal, is_resync_requested(_))
429 .WillOnce(DoAll(SetArgPointee<0>(do_resync),
430 Return(r)));
431 }
432
433 void expect_create_image(MockCreateImageRequest &mock_create_image_request,
434 const std::string &image_id, int r) {
435 EXPECT_CALL(mock_create_image_request, construct(image_id));
436 EXPECT_CALL(mock_create_image_request, send())
437 .WillOnce(Invoke([this, &mock_create_image_request, r]() {
438 m_threads->work_queue->queue(mock_create_image_request.on_finish, r);
439 }));
440 }
441
442 void expect_image_sync(MockImageSync &mock_image_sync, int r) {
443 EXPECT_CALL(mock_image_sync, get());
444 EXPECT_CALL(mock_image_sync, send())
445 .WillOnce(Invoke([this, &mock_image_sync, r]() {
446 m_threads->work_queue->queue(mock_image_sync.on_finish, r);
447 }));
448 EXPECT_CALL(mock_image_sync, put());
449 }
450
451 bufferlist encode_tag_data(const librbd::journal::TagData &tag_data) {
452 bufferlist bl;
453 encode(tag_data, bl);
454 return bl;
455 }
456
457 MockBootstrapRequest *create_request(MockThreads* mock_threads,
458 MockInstanceWatcher *mock_instance_watcher,
459 ::journal::MockJournaler &mock_journaler,
460 const std::string &local_image_id,
461 const std::string &remote_image_id,
462 const std::string &global_image_id,
463 const std::string &local_mirror_uuid,
464 const std::string &remote_mirror_uuid,
465 cls::journal::ClientState *client_state,
466 librbd::journal::MirrorPeerClientMeta *mirror_peer_client_meta,
467 Context *on_finish) {
468 return new MockBootstrapRequest(mock_threads, m_local_io_ctx,
469 m_remote_io_ctx,
470 mock_instance_watcher,
471 &m_local_test_image_ctx,
472 local_image_id,
473 remote_image_id,
474 global_image_id,
475 local_mirror_uuid,
476 remote_mirror_uuid,
477 &mock_journaler,
478 client_state, mirror_peer_client_meta,
479 on_finish, &m_do_resync);
480 }
481
482 librbd::ImageCtx *m_remote_image_ctx;
483 librbd::ImageCtx *m_local_image_ctx = nullptr;
484 librbd::MockTestImageCtx *m_local_test_image_ctx = nullptr;
485 bool m_do_resync;
486 };
487
488 TEST_F(TestMockImageReplayerBootstrapRequest, NonPrimaryRemoteSyncingState) {
489 create_local_image();
490
491 InSequence seq;
492
493 // lookup remote image tag class
494 cls::journal::Client client;
495 librbd::journal::ClientData client_data{
496 librbd::journal::ImageClientMeta{123}};
497 encode(client_data, client.data);
498 ::journal::MockJournaler mock_journaler;
499 expect_journaler_get_client(mock_journaler,
500 librbd::Journal<>::IMAGE_CLIENT_ID,
501 client, 0);
502
503 // open the remote image
504 librbd::MockJournal mock_journal;
505 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
506 MockOpenImageRequest mock_open_image_request;
507 expect_open_image(mock_open_image_request, m_remote_io_ctx,
508 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
509
510 // test if remote image is primary
511 MockIsPrimaryRequest mock_is_primary_request;
512 expect_is_primary(mock_is_primary_request, false, 0);
513
514 // switch the state to replaying
515 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
516 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
517 mock_local_image_ctx.id};
518 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
519 client_data.client_meta = mirror_peer_client_meta;
520 expect_journaler_update_client(mock_journaler, client_data, 0);
521
522 MockCloseImageRequest mock_close_image_request;
523 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
524
525 C_SaferCond ctx;
526 MockThreads mock_threads(m_threads);
527 MockInstanceWatcher mock_instance_watcher;
528 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
529 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
530 MockBootstrapRequest *request = create_request(
531 &mock_threads, &mock_instance_watcher, mock_journaler,
532 mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
533 "local mirror uuid", "remote mirror uuid", &client_state,
534 &mirror_peer_client_meta, &ctx);
535 request->send();
536 ASSERT_EQ(-EREMOTEIO, ctx.wait());
537 }
538
539 TEST_F(TestMockImageReplayerBootstrapRequest, NonPrimaryRemoteNotTagOwner) {
540 create_local_image();
541
542 InSequence seq;
543
544 // lookup remote image tag class
545 cls::journal::Client client;
546 librbd::journal::ClientData client_data{
547 librbd::journal::ImageClientMeta{123}};
548 encode(client_data, client.data);
549 ::journal::MockJournaler mock_journaler;
550 expect_journaler_get_client(mock_journaler,
551 librbd::Journal<>::IMAGE_CLIENT_ID,
552 client, 0);
553
554 // open the remote image
555 librbd::MockJournal mock_journal;
556 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
557 MockOpenImageRequest mock_open_image_request;
558 expect_open_image(mock_open_image_request, m_remote_io_ctx,
559 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
560
561 // test if remote image is primary
562 MockIsPrimaryRequest mock_is_primary_request;
563 expect_is_primary(mock_is_primary_request, false, 0);
564
565 // open the local image
566 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
567 mock_local_image_ctx.journal = &mock_journal;
568 MockOpenLocalImageRequest mock_open_local_image_request;
569 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
570 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
571 expect_is_resync_requested(mock_journal, false, 0);
572
573 expect_journal_get_tag_tid(mock_journal, 345);
574 expect_journal_get_tag_data(mock_journal, {librbd::Journal<>::LOCAL_MIRROR_UUID,
575 librbd::Journal<>::ORPHAN_MIRROR_UUID,
576 true, 344, 0});
577
578 MockCloseImageRequest mock_close_image_request;
579 expect_close_image(mock_close_image_request, mock_local_image_ctx, 0);
580 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
581
582 C_SaferCond ctx;
583 MockThreads mock_threads(m_threads);
584 MockInstanceWatcher mock_instance_watcher;
585 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
586 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
587 mock_local_image_ctx.id};
588 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
589 MockBootstrapRequest *request = create_request(
590 &mock_threads, &mock_instance_watcher, mock_journaler,
591 mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
592 "local mirror uuid", "remote mirror uuid", &client_state,
593 &mirror_peer_client_meta, &ctx);
594 request->send();
595 ASSERT_EQ(-EREMOTEIO, ctx.wait());
596 }
597
598 TEST_F(TestMockImageReplayerBootstrapRequest, RemoteDemotePromote) {
599 create_local_image();
600
601 InSequence seq;
602
603 // lookup remote image tag class
604 cls::journal::Client client;
605 librbd::journal::ClientData client_data{
606 librbd::journal::ImageClientMeta{123}};
607 encode(client_data, client.data);
608 ::journal::MockJournaler mock_journaler;
609 expect_journaler_get_client(mock_journaler,
610 librbd::Journal<>::IMAGE_CLIENT_ID,
611 client, 0);
612
613 // open the remote image
614 librbd::MockJournal mock_journal;
615 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
616 MockOpenImageRequest mock_open_image_request;
617 expect_open_image(mock_open_image_request, m_remote_io_ctx,
618 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
619
620 // test if remote image is primary
621 MockIsPrimaryRequest mock_is_primary_request;
622 expect_is_primary(mock_is_primary_request, false, 0);
623
624 // open the local image
625 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
626 mock_local_image_ctx.journal = &mock_journal;
627 MockOpenLocalImageRequest mock_open_local_image_request;
628 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
629 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
630 expect_is_resync_requested(mock_journal, false, 0);
631
632 expect_journal_get_tag_tid(mock_journal, 345);
633 expect_journal_get_tag_data(mock_journal, {"remote mirror uuid"});
634
635 // remote demotion / promotion event
636 Tags tags = {
637 {2, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
638 librbd::Journal<>::LOCAL_MIRROR_UUID,
639 true, 1, 99})},
640 {3, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
641 librbd::Journal<>::LOCAL_MIRROR_UUID,
642 true, 2, 1})},
643 {4, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
644 librbd::Journal<>::ORPHAN_MIRROR_UUID,
645 true, 2, 1})},
646 {5, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
647 librbd::Journal<>::ORPHAN_MIRROR_UUID,
648 true, 4, 369})}
649 };
650 expect_journaler_get_tags(mock_journaler, 123, tags, 0);
651
652 MockCloseImageRequest mock_close_image_request;
653 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
654
655 C_SaferCond ctx;
656 MockThreads mock_threads(m_threads);
657 MockInstanceWatcher mock_instance_watcher;
658 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
659 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
660 mock_local_image_ctx.id};
661 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
662 MockBootstrapRequest *request = create_request(
663 &mock_threads, &mock_instance_watcher, mock_journaler,
664 mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
665 "local mirror uuid", "remote mirror uuid", &client_state,
666 &mirror_peer_client_meta, &ctx);
667 request->send();
668 ASSERT_EQ(0, ctx.wait());
669 }
670
671 TEST_F(TestMockImageReplayerBootstrapRequest, MultipleRemoteDemotePromotes) {
672 create_local_image();
673
674 InSequence seq;
675
676 // lookup remote image tag class
677 cls::journal::Client client;
678 librbd::journal::ClientData client_data{
679 librbd::journal::ImageClientMeta{123}};
680 encode(client_data, client.data);
681 ::journal::MockJournaler mock_journaler;
682 expect_journaler_get_client(mock_journaler,
683 librbd::Journal<>::IMAGE_CLIENT_ID,
684 client, 0);
685
686 // open the remote image
687 librbd::MockJournal mock_journal;
688 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
689 MockOpenImageRequest mock_open_image_request;
690 expect_open_image(mock_open_image_request, m_remote_io_ctx,
691 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
692
693 // test if remote image is primary
694 MockIsPrimaryRequest mock_is_primary_request;
695 expect_is_primary(mock_is_primary_request, true, 0);
696
697 // open the local image
698 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
699 mock_local_image_ctx.journal = &mock_journal;
700 MockOpenLocalImageRequest mock_open_local_image_request;
701 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
702 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
703 expect_is_resync_requested(mock_journal, false, 0);
704
705 expect_journal_get_tag_tid(mock_journal, 345);
706 expect_journal_get_tag_data(mock_journal, {librbd::Journal<>::ORPHAN_MIRROR_UUID,
707 "remote mirror uuid", true, 4, 1});
708
709 // remote demotion / promotion event
710 Tags tags = {
711 {2, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
712 librbd::Journal<>::LOCAL_MIRROR_UUID,
713 true, 1, 99})},
714 {3, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
715 librbd::Journal<>::LOCAL_MIRROR_UUID,
716 true, 2, 1})},
717 {4, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
718 librbd::Journal<>::ORPHAN_MIRROR_UUID,
719 true, 3, 1})},
720 {5, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
721 librbd::Journal<>::LOCAL_MIRROR_UUID,
722 true, 4, 1})},
723 {6, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
724 librbd::Journal<>::ORPHAN_MIRROR_UUID,
725 true, 5, 1})},
726 {7, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
727 librbd::Journal<>::LOCAL_MIRROR_UUID,
728 true, 6, 1})},
729 {8, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
730 librbd::Journal<>::ORPHAN_MIRROR_UUID,
731 true, 7, 1})}
732 };
733 expect_journaler_get_tags(mock_journaler, 123, tags, 0);
734
735 MockCloseImageRequest mock_close_image_request;
736 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
737
738 C_SaferCond ctx;
739 MockThreads mock_threads(m_threads);
740 MockInstanceWatcher mock_instance_watcher;
741 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
742 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
743 mock_local_image_ctx.id};
744 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
745 MockBootstrapRequest *request = create_request(
746 &mock_threads, &mock_instance_watcher, mock_journaler,
747 mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
748 "local mirror uuid", "remote mirror uuid", &client_state,
749 &mirror_peer_client_meta, &ctx);
750 request->send();
751 ASSERT_EQ(0, ctx.wait());
752 }
753
754 TEST_F(TestMockImageReplayerBootstrapRequest, LocalDemoteRemotePromote) {
755 create_local_image();
756
757 InSequence seq;
758
759 // lookup remote image tag class
760 cls::journal::Client client;
761 librbd::journal::ClientData client_data{
762 librbd::journal::ImageClientMeta{123}};
763 encode(client_data, client.data);
764 ::journal::MockJournaler mock_journaler;
765 expect_journaler_get_client(mock_journaler,
766 librbd::Journal<>::IMAGE_CLIENT_ID,
767 client, 0);
768
769 // open the remote image
770 librbd::MockJournal mock_journal;
771 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
772 MockOpenImageRequest mock_open_image_request;
773 expect_open_image(mock_open_image_request, m_remote_io_ctx,
774 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
775
776 // test if remote image is primary
777 MockIsPrimaryRequest mock_is_primary_request;
778 expect_is_primary(mock_is_primary_request, true, 0);
779
780 // open the local image
781 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
782 mock_local_image_ctx.journal = &mock_journal;
783 MockOpenLocalImageRequest mock_open_local_image_request;
784 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
785 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
786 expect_is_resync_requested(mock_journal, false, 0);
787
788 expect_journal_get_tag_tid(mock_journal, 346);
789 expect_journal_get_tag_data(mock_journal,
790 {librbd::Journal<>::ORPHAN_MIRROR_UUID,
791 librbd::Journal<>::LOCAL_MIRROR_UUID,
792 true, 345, 1});
793
794 // remote demotion / promotion event
795 Tags tags = {
796 {2, 123, encode_tag_data({"local mirror uuid", "local mirror uuid",
797 true, 344, 99})},
798 {3, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
799 "local mirror uuid", true, 345, 1})},
800 {4, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
801 librbd::Journal<>::ORPHAN_MIRROR_UUID,
802 true, 3, 1})}
803 };
804 expect_journaler_get_tags(mock_journaler, 123, tags, 0);
805
806 MockCloseImageRequest mock_close_image_request;
807 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
808
809 C_SaferCond ctx;
810 MockThreads mock_threads(m_threads);
811 MockInstanceWatcher mock_instance_watcher;
812 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
813 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
814 mock_local_image_ctx.id};
815 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
816 MockBootstrapRequest *request = create_request(
817 &mock_threads, &mock_instance_watcher, mock_journaler,
818 mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
819 "local mirror uuid", "remote mirror uuid", &client_state,
820 &mirror_peer_client_meta, &ctx);
821 request->send();
822 ASSERT_EQ(0, ctx.wait());
823 }
824
825 TEST_F(TestMockImageReplayerBootstrapRequest, SplitBrainForcePromote) {
826 create_local_image();
827
828 InSequence seq;
829
830 // lookup remote image tag class
831 cls::journal::Client client;
832 librbd::journal::ClientData client_data{
833 librbd::journal::ImageClientMeta{123}};
834 encode(client_data, client.data);
835 ::journal::MockJournaler mock_journaler;
836 expect_journaler_get_client(mock_journaler,
837 librbd::Journal<>::IMAGE_CLIENT_ID,
838 client, 0);
839
840 // open the remote image
841 librbd::MockJournal mock_journal;
842 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
843 MockOpenImageRequest mock_open_image_request;
844 expect_open_image(mock_open_image_request, m_remote_io_ctx,
845 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
846
847 // test if remote image is primary
848 MockIsPrimaryRequest mock_is_primary_request;
849 expect_is_primary(mock_is_primary_request, true, 0);
850
851 // open the local image
852 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
853 mock_local_image_ctx.journal = &mock_journal;
854 MockOpenLocalImageRequest mock_open_local_image_request;
855 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
856 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
857 expect_is_resync_requested(mock_journal, false, 0);
858
859 expect_journal_get_tag_tid(mock_journal, 345);
860 expect_journal_get_tag_data(mock_journal, {librbd::Journal<>::LOCAL_MIRROR_UUID,
861 librbd::Journal<>::ORPHAN_MIRROR_UUID,
862 true, 344, 0});
863
864 // remote demotion / promotion event
865 Tags tags = {
866 {2, 123, encode_tag_data({librbd::Journal<>::LOCAL_MIRROR_UUID,
867 librbd::Journal<>::LOCAL_MIRROR_UUID,
868 true, 1, 99})},
869 {3, 123, encode_tag_data({librbd::Journal<>::ORPHAN_MIRROR_UUID,
870 librbd::Journal<>::LOCAL_MIRROR_UUID,
871 true, 2, 1})}
872 };
873 expect_journaler_get_tags(mock_journaler, 123, tags, 0);
874
875 MockCloseImageRequest mock_close_image_request;
876 expect_close_image(mock_close_image_request, mock_local_image_ctx, 0);
877 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
878
879 C_SaferCond ctx;
880 MockThreads mock_threads(m_threads);
881 MockInstanceWatcher mock_instance_watcher;
882 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
883 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
884 mock_local_image_ctx.id};
885 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
886 MockBootstrapRequest *request = create_request(
887 &mock_threads, &mock_instance_watcher, mock_journaler,
888 mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
889 "local mirror uuid", "remote mirror uuid", &client_state,
890 &mirror_peer_client_meta, &ctx);
891 request->send();
892 ASSERT_EQ(-EEXIST, ctx.wait());
893 ASSERT_EQ(NULL, m_local_test_image_ctx);
894 }
895
896 TEST_F(TestMockImageReplayerBootstrapRequest, ResyncRequested) {
897 create_local_image();
898
899 InSequence seq;
900
901 // lookup remote image tag class
902 cls::journal::Client client;
903 librbd::journal::ClientData client_data{
904 librbd::journal::ImageClientMeta{123}};
905 encode(client_data, client.data);
906 ::journal::MockJournaler mock_journaler;
907 expect_journaler_get_client(mock_journaler,
908 librbd::Journal<>::IMAGE_CLIENT_ID,
909 client, 0);
910
911 // open the remote image
912 librbd::MockJournal mock_journal;
913 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
914 MockOpenImageRequest mock_open_image_request;
915 expect_open_image(mock_open_image_request, m_remote_io_ctx,
916 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
917
918 // test if remote image is primary
919 MockIsPrimaryRequest mock_is_primary_request;
920 expect_is_primary(mock_is_primary_request, true, 0);
921
922 // open the local image
923 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
924 mock_local_image_ctx.journal = &mock_journal;
925 MockOpenLocalImageRequest mock_open_local_image_request;
926 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
927 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
928
929 // resync is requested
930 expect_is_resync_requested(mock_journal, true, 0);
931
932 expect_journal_get_tag_tid(mock_journal, 345);
933 expect_journal_get_tag_data(mock_journal, {"remote mirror uuid"});
934
935 MockCloseImageRequest mock_close_image_request;
936 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
937
938 C_SaferCond ctx;
939 MockThreads mock_threads(m_threads);
940 MockInstanceWatcher mock_instance_watcher;
941 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
942 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta{
943 mock_local_image_ctx.id};
944 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
945 MockBootstrapRequest *request = create_request(
946 &mock_threads, &mock_instance_watcher, mock_journaler,
947 mock_local_image_ctx.id, mock_remote_image_ctx.id, "global image id",
948 "local mirror uuid", "remote mirror uuid", &client_state,
949 &mirror_peer_client_meta, &ctx);
950 m_do_resync = false;
951 request->send();
952 ASSERT_EQ(0, ctx.wait());
953 ASSERT_TRUE(m_do_resync);
954 }
955
956 TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemote) {
957 create_local_image();
958
959 InSequence seq;
960
961 // lookup remote image tag class
962 cls::journal::Client client;
963 librbd::journal::ClientData client_data{
964 librbd::journal::ImageClientMeta{123}};
965 encode(client_data, client.data);
966 ::journal::MockJournaler mock_journaler;
967 expect_journaler_get_client(mock_journaler,
968 librbd::Journal<>::IMAGE_CLIENT_ID,
969 client, 0);
970
971 // open the remote image
972 librbd::MockJournal mock_journal;
973 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
974 MockOpenImageRequest mock_open_image_request;
975 expect_open_image(mock_open_image_request, m_remote_io_ctx,
976 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
977
978 // test if remote image is primary
979 MockIsPrimaryRequest mock_is_primary_request;
980 expect_is_primary(mock_is_primary_request, true, 0);
981
982 // update client state back to syncing
983 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
984 mock_local_image_ctx.journal = &mock_journal;
985
986 librbd::util::s_image_id = mock_local_image_ctx.id;
987 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
988 mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
989 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
990 client_data.client_meta = mirror_peer_client_meta;
991 client.data.clear();
992 encode(client_data, client.data);
993 expect_journaler_update_client(mock_journaler, client_data, 0);
994
995 // create the local image
996 MockCreateImageRequest mock_create_image_request;
997 expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0);
998
999 // open the local image
1000 MockOpenLocalImageRequest mock_open_local_image_request;
1001 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
1002 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
1003 expect_is_resync_requested(mock_journal, false, 0);
1004
1005 expect_journal_get_tag_tid(mock_journal, 345);
1006 expect_journal_get_tag_data(mock_journal, {"remote mirror uuid"});
1007
1008 // sync the remote image to the local image
1009 MockImageSync mock_image_sync;
1010 expect_image_sync(mock_image_sync, 0);
1011
1012 MockCloseImageRequest mock_close_image_request;
1013 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
1014
1015 C_SaferCond ctx;
1016 MockThreads mock_threads(m_threads);
1017 MockInstanceWatcher mock_instance_watcher;
1018 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
1019 mirror_peer_client_meta.image_id = "";
1020 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
1021 MockBootstrapRequest *request = create_request(
1022 &mock_threads, &mock_instance_watcher, mock_journaler, "",
1023 mock_remote_image_ctx.id, "global image id", "local mirror uuid",
1024 "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
1025 request->send();
1026 ASSERT_EQ(0, ctx.wait());
1027 }
1028
1029 TEST_F(TestMockImageReplayerBootstrapRequest, PrimaryRemoteLocalDeleted) {
1030 create_local_image();
1031
1032 InSequence seq;
1033
1034 // lookup remote image tag class
1035 cls::journal::Client client;
1036 librbd::journal::ClientData client_data{
1037 librbd::journal::ImageClientMeta{123}};
1038 encode(client_data, client.data);
1039 ::journal::MockJournaler mock_journaler;
1040 expect_journaler_get_client(mock_journaler,
1041 librbd::Journal<>::IMAGE_CLIENT_ID,
1042 client, 0);
1043
1044 // open the remote image
1045 librbd::MockJournal mock_journal;
1046 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
1047 MockOpenImageRequest mock_open_image_request;
1048 expect_open_image(mock_open_image_request, m_remote_io_ctx,
1049 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
1050
1051 // test if remote image is primary
1052 MockIsPrimaryRequest mock_is_primary_request;
1053 expect_is_primary(mock_is_primary_request, true, 0);
1054
1055 // open the missing local image
1056 MockOpenLocalImageRequest mock_open_local_image_request;
1057 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
1058 "missing image id", nullptr, -ENOENT);
1059
1060 // re-register the client
1061 expect_journaler_unregister_client(mock_journaler, 0);
1062 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
1063 mirror_peer_client_meta.image_id = "";
1064 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
1065 client_data.client_meta = mirror_peer_client_meta;
1066 expect_journaler_register_client(mock_journaler, client_data, 0);
1067
1068 // test if remote image is primary
1069 expect_is_primary(mock_is_primary_request, true, 0);
1070
1071 // update client state back to syncing
1072 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
1073 mock_local_image_ctx.journal = &mock_journal;
1074
1075 librbd::util::s_image_id = mock_local_image_ctx.id;
1076 mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
1077 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
1078 client_data.client_meta = mirror_peer_client_meta;
1079 client.data.clear();
1080 encode(client_data, client.data);
1081 expect_journaler_update_client(mock_journaler, client_data, 0);
1082
1083 // create the missing local image
1084 MockCreateImageRequest mock_create_image_request;
1085 expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0);
1086
1087 // open the local image
1088 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
1089 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
1090 expect_is_resync_requested(mock_journal, false, 0);
1091
1092 expect_journal_get_tag_tid(mock_journal, 345);
1093 expect_journal_get_tag_data(mock_journal, {"remote mirror uuid"});
1094
1095 // sync the remote image to the local image
1096 MockImageSync mock_image_sync;
1097 expect_image_sync(mock_image_sync, 0);
1098
1099 MockCloseImageRequest mock_close_image_request;
1100 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
1101
1102 C_SaferCond ctx;
1103 MockThreads mock_threads(m_threads);
1104 MockInstanceWatcher mock_instance_watcher;
1105 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
1106 mirror_peer_client_meta.image_id = "missing image id";
1107 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
1108 MockBootstrapRequest *request = create_request(
1109 &mock_threads, &mock_instance_watcher, mock_journaler, "missing image id",
1110 mock_remote_image_ctx.id, "global image id", "local mirror uuid",
1111 "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
1112 request->send();
1113 ASSERT_EQ(0, ctx.wait());
1114 }
1115
1116 TEST_F(TestMockImageReplayerBootstrapRequest, LocalImageIdCollision) {
1117 create_local_image();
1118
1119 InSequence seq;
1120
1121 // lookup remote image tag class
1122 cls::journal::Client client;
1123 librbd::journal::ClientData client_data{
1124 librbd::journal::ImageClientMeta{123}};
1125 encode(client_data, client.data);
1126 ::journal::MockJournaler mock_journaler;
1127 expect_journaler_get_client(mock_journaler,
1128 librbd::Journal<>::IMAGE_CLIENT_ID,
1129 client, 0);
1130
1131 // open the remote image
1132 librbd::MockJournal mock_journal;
1133 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
1134 MockOpenImageRequest mock_open_image_request;
1135 expect_open_image(mock_open_image_request, m_remote_io_ctx,
1136 mock_remote_image_ctx.id, mock_remote_image_ctx, 0);
1137
1138 // test if remote image is primary
1139 MockIsPrimaryRequest mock_is_primary_request;
1140 expect_is_primary(mock_is_primary_request, true, 0);
1141
1142 // update client state back to syncing
1143 librbd::MockTestImageCtx mock_local_image_ctx(*m_local_image_ctx);
1144 mock_local_image_ctx.journal = &mock_journal;
1145
1146 librbd::util::s_image_id = mock_local_image_ctx.id;
1147 librbd::journal::MirrorPeerClientMeta mirror_peer_client_meta;
1148 mirror_peer_client_meta.image_id = mock_local_image_ctx.id;
1149 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_SYNCING;
1150 client_data.client_meta = mirror_peer_client_meta;
1151 client.data.clear();
1152 encode(client_data, client.data);
1153 expect_journaler_update_client(mock_journaler, client_data, 0);
1154
1155 // create the local image
1156 MockCreateImageRequest mock_create_image_request;
1157 expect_create_image(mock_create_image_request, mock_local_image_ctx.id,
1158 -EBADF);
1159
1160 expect_journaler_update_client(mock_journaler, client_data, 0);
1161 expect_create_image(mock_create_image_request, mock_local_image_ctx.id, 0);
1162
1163 // open the local image
1164 MockOpenLocalImageRequest mock_open_local_image_request;
1165 expect_open_local_image(mock_open_local_image_request, m_local_io_ctx,
1166 mock_local_image_ctx.id, &mock_local_image_ctx, 0);
1167 expect_is_resync_requested(mock_journal, false, 0);
1168
1169 expect_journal_get_tag_tid(mock_journal, 345);
1170 expect_journal_get_tag_data(mock_journal, {"remote mirror uuid"});
1171
1172 // sync the remote image to the local image
1173 MockImageSync mock_image_sync;
1174 expect_image_sync(mock_image_sync, 0);
1175
1176 MockCloseImageRequest mock_close_image_request;
1177 expect_close_image(mock_close_image_request, mock_remote_image_ctx, 0);
1178
1179 C_SaferCond ctx;
1180 MockThreads mock_threads(m_threads);
1181 MockInstanceWatcher mock_instance_watcher;
1182 cls::journal::ClientState client_state = cls::journal::CLIENT_STATE_CONNECTED;
1183 mirror_peer_client_meta.image_id = "";
1184 mirror_peer_client_meta.state = librbd::journal::MIRROR_PEER_STATE_REPLAYING;
1185 MockBootstrapRequest *request = create_request(
1186 &mock_threads, &mock_instance_watcher, mock_journaler, "",
1187 mock_remote_image_ctx.id, "global image id", "local mirror uuid",
1188 "remote mirror uuid", &client_state, &mirror_peer_client_meta, &ctx);
1189 request->send();
1190 ASSERT_EQ(0, ctx.wait());
1191 }
1192
1193 } // namespace image_replayer
1194 } // namespace mirror
1195 } // namespace rbd