1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "test/rbd_mirror/test_mock_fixture.h"
5 #include "librbd/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"
23 struct MockTestImageCtx
: public librbd::MockImageCtx
{
24 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
25 : librbd::MockImageCtx(image_ctx
) {
29 } // anonymous namespace
34 struct TypeTraits
<librbd::MockTestImageCtx
> {
35 typedef ::journal::MockJournaler Journaler
;
38 } // namespace journal
42 static std::string s_image_id
;
45 std::string generate_image_id
<MockTestImageCtx
>(librados::IoCtx
&) {
46 ceph_assert(!s_image_id
.empty());
56 class ProgressContext
;
59 struct Threads
<librbd::MockTestImageCtx
> {
62 ContextWQ
*work_queue
;
64 Threads(Threads
<librbd::ImageCtx
> *threads
)
65 : timer_lock(threads
->timer_lock
), timer(threads
->timer
),
66 work_queue(threads
->work_queue
) {
71 struct ImageSync
<librbd::MockTestImageCtx
> {
72 static ImageSync
* s_instance
;
73 Context
*on_finish
= nullptr;
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
;
89 ceph_assert(s_instance
== nullptr);
96 MOCK_METHOD0(get
, void());
97 MOCK_METHOD0(put
, void());
98 MOCK_METHOD0(send
, void());
99 MOCK_METHOD0(cancel
, void());
102 ImageSync
<librbd::MockTestImageCtx
>*
103 ImageSync
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
106 struct InstanceWatcher
<librbd::MockTestImageCtx
> {
109 namespace image_replayer
{
112 struct CloseImageRequest
<librbd::MockTestImageCtx
> {
113 static CloseImageRequest
* s_instance
;
114 librbd::MockTestImageCtx
**image_ctx
= nullptr;
115 Context
*on_finish
= nullptr;
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
);
126 CloseImageRequest() {
127 ceph_assert(s_instance
== nullptr);
130 ~CloseImageRequest() {
131 s_instance
= nullptr;
134 MOCK_METHOD1(construct
, void(librbd::MockTestImageCtx
*image_ctx
));
135 MOCK_METHOD0(send
, void());
139 struct CreateImageRequest
<librbd::MockTestImageCtx
> {
140 static CreateImageRequest
* s_instance
;
141 Context
*on_finish
= nullptr;
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
);
157 CreateImageRequest() {
158 ceph_assert(s_instance
== nullptr);
161 ~CreateImageRequest() {
162 s_instance
= nullptr;
165 MOCK_METHOD1(construct
, void(const std::string
&));
166 MOCK_METHOD0(send
, void());
170 struct IsPrimaryRequest
<librbd::MockTestImageCtx
> {
171 static IsPrimaryRequest
* s_instance
;
172 bool *primary
= nullptr;
173 Context
*on_finish
= nullptr;
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
;
184 ceph_assert(s_instance
== nullptr);
187 ~IsPrimaryRequest() {
188 s_instance
= nullptr;
191 MOCK_METHOD0(send
, void());
195 struct OpenImageRequest
<librbd::MockTestImageCtx
> {
196 static OpenImageRequest
* s_instance
;
197 librbd::MockTestImageCtx
**image_ctx
= nullptr;
198 Context
*on_finish
= nullptr;
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
);
212 ceph_assert(s_instance
== nullptr);
215 ~OpenImageRequest() {
216 s_instance
= nullptr;
219 MOCK_METHOD2(construct
, void(librados::IoCtx
&io_ctx
,
220 const std::string
&image_id
));
221 MOCK_METHOD0(send
, void());
225 struct OpenLocalImageRequest
<librbd::MockTestImageCtx
> {
226 static OpenLocalImageRequest
* s_instance
;
227 librbd::MockTestImageCtx
**image_ctx
= nullptr;
228 Context
*on_finish
= nullptr;
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
);
242 OpenLocalImageRequest() {
243 ceph_assert(s_instance
== nullptr);
246 ~OpenLocalImageRequest() {
247 s_instance
= nullptr;
250 MOCK_METHOD2(construct
, void(librados::IoCtx
&io_ctx
,
251 const std::string
&image_id
));
252 MOCK_METHOD0(send
, void());
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;
266 } // namespace image_replayer
267 } // namespace mirror
270 // template definitions
271 #include "tools/rbd_mirror/image_replayer/BootstrapRequest.cc"
275 namespace image_replayer
{
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
;
286 MATCHER_P(IsSameIoCtx
, io_ctx
, "") {
287 return &get_mock_io_ctx(arg
) == &get_mock_io_ctx(*io_ctx
);
290 class TestMockImageReplayerBootstrapRequest
: public TestMockFixture
{
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
;
303 void SetUp() override
{
304 TestMockFixture::SetUp();
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
));
311 void create_local_image() {
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
));
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
;
324 WithArg
<2>(Invoke([this, r
](Context
*on_finish
) {
325 m_threads
->work_queue
->queue(on_finish
, r
);
329 void expect_journaler_get_tags(::journal::MockJournaler
&mock_journaler
,
330 uint64_t tag_class
, const Tags
& tags
,
332 EXPECT_CALL(mock_journaler
, get_tags(tag_class
, _
, _
))
333 .WillOnce(DoAll(WithArg
<1>(Invoke([tags
](Tags
*out_tags
) {
336 WithArg
<2>(Invoke([this, r
](Context
*on_finish
) {
337 m_threads
->work_queue
->queue(on_finish
, r
);
341 void expect_journaler_register_client(::journal::MockJournaler
&mock_journaler
,
342 const librbd::journal::ClientData
&client_data
,
345 encode(client_data
, bl
);
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
);
353 void expect_journaler_unregister_client(::journal::MockJournaler
&mock_journaler
,
355 EXPECT_CALL(mock_journaler
, unregister_client(_
))
356 .WillOnce(Invoke([this, r
](Context
*on_finish
) {
357 m_threads
->work_queue
->queue(on_finish
, r
);
361 void expect_journaler_update_client(::journal::MockJournaler
&mock_journaler
,
362 const librbd::journal::ClientData
&client_data
,
365 encode(client_data
, bl
);
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
);
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
);
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
,
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
);
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
);
416 void expect_journal_get_tag_tid(librbd::MockJournal
&mock_journal
,
418 EXPECT_CALL(mock_journal
, get_tag_tid()).WillOnce(Return(tag_tid
));
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
));
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
),
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
);
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
);
448 EXPECT_CALL(mock_image_sync
, put());
451 bufferlist
encode_tag_data(const librbd::journal::TagData
&tag_data
) {
453 encode(tag_data
, bl
);
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
,
470 mock_instance_watcher
,
471 &m_local_test_image_ctx
,
478 client_state
, mirror_peer_client_meta
,
479 on_finish
, &m_do_resync
);
482 librbd::ImageCtx
*m_remote_image_ctx
;
483 librbd::ImageCtx
*m_local_image_ctx
= nullptr;
484 librbd::MockTestImageCtx
*m_local_test_image_ctx
= nullptr;
488 TEST_F(TestMockImageReplayerBootstrapRequest
, NonPrimaryRemoteSyncingState
) {
489 create_local_image();
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
,
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);
510 // test if remote image is primary
511 MockIsPrimaryRequest mock_is_primary_request
;
512 expect_is_primary(mock_is_primary_request
, false, 0);
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);
522 MockCloseImageRequest mock_close_image_request
;
523 expect_close_image(mock_close_image_request
, mock_remote_image_ctx
, 0);
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
);
536 ASSERT_EQ(-EREMOTEIO
, ctx
.wait());
539 TEST_F(TestMockImageReplayerBootstrapRequest
, NonPrimaryRemoteNotTagOwner
) {
540 create_local_image();
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
,
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);
561 // test if remote image is primary
562 MockIsPrimaryRequest mock_is_primary_request
;
563 expect_is_primary(mock_is_primary_request
, false, 0);
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);
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
,
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);
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
);
595 ASSERT_EQ(-EREMOTEIO
, ctx
.wait());
598 TEST_F(TestMockImageReplayerBootstrapRequest
, RemoteDemotePromote
) {
599 create_local_image();
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
,
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);
620 // test if remote image is primary
621 MockIsPrimaryRequest mock_is_primary_request
;
622 expect_is_primary(mock_is_primary_request
, false, 0);
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);
632 expect_journal_get_tag_tid(mock_journal
, 345);
633 expect_journal_get_tag_data(mock_journal
, {"remote mirror uuid"});
635 // remote demotion / promotion event
637 {2, 123, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
638 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
640 {3, 123, encode_tag_data({librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
641 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
643 {4, 123, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
644 librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
646 {5, 123, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
647 librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
650 expect_journaler_get_tags(mock_journaler
, 123, tags
, 0);
652 MockCloseImageRequest mock_close_image_request
;
653 expect_close_image(mock_close_image_request
, mock_remote_image_ctx
, 0);
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
);
668 ASSERT_EQ(0, ctx
.wait());
671 TEST_F(TestMockImageReplayerBootstrapRequest
, MultipleRemoteDemotePromotes
) {
672 create_local_image();
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
,
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);
693 // test if remote image is primary
694 MockIsPrimaryRequest mock_is_primary_request
;
695 expect_is_primary(mock_is_primary_request
, true, 0);
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);
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});
709 // remote demotion / promotion event
711 {2, 123, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
712 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
714 {3, 123, encode_tag_data({librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
715 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
717 {4, 123, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
718 librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
720 {5, 123, encode_tag_data({librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
721 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
723 {6, 123, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
724 librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
726 {7, 123, encode_tag_data({librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
727 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
729 {8, 123, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
730 librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
733 expect_journaler_get_tags(mock_journaler
, 123, tags
, 0);
735 MockCloseImageRequest mock_close_image_request
;
736 expect_close_image(mock_close_image_request
, mock_remote_image_ctx
, 0);
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
);
751 ASSERT_EQ(0, ctx
.wait());
754 TEST_F(TestMockImageReplayerBootstrapRequest
, LocalDemoteRemotePromote
) {
755 create_local_image();
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
,
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);
776 // test if remote image is primary
777 MockIsPrimaryRequest mock_is_primary_request
;
778 expect_is_primary(mock_is_primary_request
, true, 0);
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);
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
,
794 // remote demotion / promotion event
796 {2, 123, encode_tag_data({"local mirror uuid", "local mirror uuid",
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
,
804 expect_journaler_get_tags(mock_journaler
, 123, tags
, 0);
806 MockCloseImageRequest mock_close_image_request
;
807 expect_close_image(mock_close_image_request
, mock_remote_image_ctx
, 0);
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
);
822 ASSERT_EQ(0, ctx
.wait());
825 TEST_F(TestMockImageReplayerBootstrapRequest
, SplitBrainForcePromote
) {
826 create_local_image();
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
,
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);
847 // test if remote image is primary
848 MockIsPrimaryRequest mock_is_primary_request
;
849 expect_is_primary(mock_is_primary_request
, true, 0);
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);
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
,
864 // remote demotion / promotion event
866 {2, 123, encode_tag_data({librbd::Journal
<>::LOCAL_MIRROR_UUID
,
867 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
869 {3, 123, encode_tag_data({librbd::Journal
<>::ORPHAN_MIRROR_UUID
,
870 librbd::Journal
<>::LOCAL_MIRROR_UUID
,
873 expect_journaler_get_tags(mock_journaler
, 123, tags
, 0);
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);
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
);
892 ASSERT_EQ(-EEXIST
, ctx
.wait());
893 ASSERT_EQ(NULL
, m_local_test_image_ctx
);
896 TEST_F(TestMockImageReplayerBootstrapRequest
, ResyncRequested
) {
897 create_local_image();
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
,
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);
918 // test if remote image is primary
919 MockIsPrimaryRequest mock_is_primary_request
;
920 expect_is_primary(mock_is_primary_request
, true, 0);
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);
929 // resync is requested
930 expect_is_resync_requested(mock_journal
, true, 0);
932 expect_journal_get_tag_tid(mock_journal
, 345);
933 expect_journal_get_tag_data(mock_journal
, {"remote mirror uuid"});
935 MockCloseImageRequest mock_close_image_request
;
936 expect_close_image(mock_close_image_request
, mock_remote_image_ctx
, 0);
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
);
952 ASSERT_EQ(0, ctx
.wait());
953 ASSERT_TRUE(m_do_resync
);
956 TEST_F(TestMockImageReplayerBootstrapRequest
, PrimaryRemote
) {
957 create_local_image();
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
,
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);
978 // test if remote image is primary
979 MockIsPrimaryRequest mock_is_primary_request
;
980 expect_is_primary(mock_is_primary_request
, true, 0);
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
;
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
;
992 encode(client_data
, client
.data
);
993 expect_journaler_update_client(mock_journaler
, client_data
, 0);
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);
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);
1005 expect_journal_get_tag_tid(mock_journal
, 345);
1006 expect_journal_get_tag_data(mock_journal
, {"remote mirror uuid"});
1008 // sync the remote image to the local image
1009 MockImageSync mock_image_sync
;
1010 expect_image_sync(mock_image_sync
, 0);
1012 MockCloseImageRequest mock_close_image_request
;
1013 expect_close_image(mock_close_image_request
, mock_remote_image_ctx
, 0);
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
);
1026 ASSERT_EQ(0, ctx
.wait());
1029 TEST_F(TestMockImageReplayerBootstrapRequest
, PrimaryRemoteLocalDeleted
) {
1030 create_local_image();
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
,
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);
1051 // test if remote image is primary
1052 MockIsPrimaryRequest mock_is_primary_request
;
1053 expect_is_primary(mock_is_primary_request
, true, 0);
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
);
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);
1068 // test if remote image is primary
1069 expect_is_primary(mock_is_primary_request
, true, 0);
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
;
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);
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);
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);
1092 expect_journal_get_tag_tid(mock_journal
, 345);
1093 expect_journal_get_tag_data(mock_journal
, {"remote mirror uuid"});
1095 // sync the remote image to the local image
1096 MockImageSync mock_image_sync
;
1097 expect_image_sync(mock_image_sync
, 0);
1099 MockCloseImageRequest mock_close_image_request
;
1100 expect_close_image(mock_close_image_request
, mock_remote_image_ctx
, 0);
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
);
1113 ASSERT_EQ(0, ctx
.wait());
1116 TEST_F(TestMockImageReplayerBootstrapRequest
, LocalImageIdCollision
) {
1117 create_local_image();
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
,
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);
1138 // test if remote image is primary
1139 MockIsPrimaryRequest mock_is_primary_request
;
1140 expect_is_primary(mock_is_primary_request
, true, 0);
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
;
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);
1155 // create the local image
1156 MockCreateImageRequest mock_create_image_request
;
1157 expect_create_image(mock_create_image_request
, mock_local_image_ctx
.id
,
1160 expect_journaler_update_client(mock_journaler
, client_data
, 0);
1161 expect_create_image(mock_create_image_request
, mock_local_image_ctx
.id
, 0);
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);
1169 expect_journal_get_tag_tid(mock_journal
, 345);
1170 expect_journal_get_tag_data(mock_journal
, {"remote mirror uuid"});
1172 // sync the remote image to the local image
1173 MockImageSync mock_image_sync
;
1174 expect_image_sync(mock_image_sync
, 0);
1176 MockCloseImageRequest mock_close_image_request
;
1177 expect_close_image(mock_close_image_request
, mock_remote_image_ctx
, 0);
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
);
1190 ASSERT_EQ(0, ctx
.wait());
1193 } // namespace image_replayer
1194 } // namespace mirror