1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "include/stringify.h"
5 #include "test/librbd/test_mock_fixture.h"
6 #include "test/librbd/test_support.h"
7 #include "test/librbd/mock/MockImageCtx.h"
8 #include "test/librbd/mock/MockOperations.h"
9 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
10 #include "test/librados_test_stub/MockTestMemRadosClient.h"
11 #include "librbd/mirror/snapshot/CreatePrimaryRequest.h"
12 #include "librbd/mirror/snapshot/UnlinkPeerRequest.h"
13 #include "librbd/mirror/snapshot/Utils.h"
19 struct MockTestImageCtx
: public MockImageCtx
{
20 explicit MockTestImageCtx(librbd::ImageCtx
& image_ctx
) : MockImageCtx(image_ctx
) {
24 } // anonymous namespace
33 static Mock
* s_instance
;
39 MOCK_METHOD4(can_create_primary_snapshot
,
40 bool(librbd::MockTestImageCtx
*, bool, bool, uint64_t *));
43 Mock
*Mock::s_instance
= nullptr;
45 } // anonymous namespace
47 template<> bool can_create_primary_snapshot(librbd::MockTestImageCtx
*image_ctx
,
48 bool demoted
, bool force
,
49 bool* requires_orphan
,
50 uint64_t *rollback_snap_id
) {
51 return Mock::s_instance
->can_create_primary_snapshot(image_ctx
, demoted
,
52 force
, rollback_snap_id
);
58 struct UnlinkPeerRequest
<MockTestImageCtx
> {
59 uint64_t snap_id
= CEPH_NOSNAP
;
60 std::string mirror_peer_uuid
;
62 Context
* on_finish
= nullptr;
63 static UnlinkPeerRequest
* s_instance
;
64 static UnlinkPeerRequest
*create(MockTestImageCtx
*image_ctx
,
66 const std::string
&mirror_peer_uuid
,
69 ceph_assert(s_instance
!= nullptr);
70 s_instance
->snap_id
= snap_id
;
71 s_instance
->mirror_peer_uuid
= mirror_peer_uuid
;
72 s_instance
->allow_remove
= allow_remove
;
73 s_instance
->on_finish
= on_finish
;
77 MOCK_METHOD0(send
, void());
84 UnlinkPeerRequest
<MockTestImageCtx
>* UnlinkPeerRequest
<MockTestImageCtx
>::s_instance
= nullptr;
86 } // namespace snapshot
90 // template definitions
91 #include "librbd/mirror/snapshot/CreatePrimaryRequest.cc"
92 template class librbd::mirror::snapshot::CreatePrimaryRequest
<librbd::MockTestImageCtx
>;
99 using ::testing::DoAll
;
100 using ::testing::InSequence
;
101 using ::testing::Invoke
;
102 using ::testing::Return
;
103 using ::testing::StrEq
;
104 using ::testing::WithArg
;
106 class TestMockMirrorSnapshotCreatePrimaryRequest
: public TestMockFixture
{
108 typedef CreatePrimaryRequest
<MockTestImageCtx
> MockCreatePrimaryRequest
;
109 typedef UnlinkPeerRequest
<MockTestImageCtx
> MockUnlinkPeerRequest
;
110 typedef util::Mock MockUtils
;
112 uint64_t m_snap_seq
= 0;
114 void snap_create(MockTestImageCtx
&mock_image_ctx
,
115 const cls::rbd::SnapshotNamespace
&ns
,
116 const std::string
& snap_name
) {
117 ASSERT_TRUE(mock_image_ctx
.snap_info
.insert(
119 SnapInfo
{snap_name
, ns
, 0, {}, 0, 0, {}}}).second
);
122 void expect_clone_md_ctx(MockTestImageCtx
&mock_image_ctx
) {
123 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
), clone())
124 .WillOnce(Invoke([&mock_image_ctx
]() {
125 get_mock_io_ctx(mock_image_ctx
.md_ctx
).get();
126 return &get_mock_io_ctx(mock_image_ctx
.md_ctx
);
130 void expect_can_create_primary_snapshot(MockUtils
&mock_utils
, bool demoted
,
131 bool force
, bool result
) {
132 EXPECT_CALL(mock_utils
,
133 can_create_primary_snapshot(_
, demoted
, force
, nullptr))
134 .WillOnce(Return(result
));
137 void expect_get_mirror_peers(MockTestImageCtx
&mock_image_ctx
,
138 const std::vector
<cls::rbd::MirrorPeer
> &peers
,
144 EXPECT_CALL(get_mock_io_ctx(mock_image_ctx
.md_ctx
),
145 exec(RBD_MIRRORING
, _
, StrEq("rbd"), StrEq("mirror_peer_list"),
147 .WillOnce(DoAll(WithArg
<5>(CopyInBufferlist(bl
)),
151 void expect_create_snapshot(MockTestImageCtx
&mock_image_ctx
, int r
) {
152 EXPECT_CALL(*mock_image_ctx
.operations
, snap_create(_
, _
, _
, _
, _
))
154 Invoke([this, &mock_image_ctx
, r
](
155 const cls::rbd::SnapshotNamespace
&ns
,
156 const std::string
& snap_name
,
158 ProgressContext
&prog_ctx
,
159 Context
*on_finish
) {
164 std::get
<cls::rbd::MirrorSnapshotNamespace
>(ns
);
165 mirror_ns
.complete
= true;
166 snap_create(mock_image_ctx
, mirror_ns
, snap_name
);
168 WithArg
<4>(CompleteContext(
169 r
, mock_image_ctx
.image_ctx
->op_work_queue
))
173 void expect_refresh_image(MockTestImageCtx
&mock_image_ctx
, int r
) {
174 EXPECT_CALL(*mock_image_ctx
.state
, refresh(_
))
175 .WillOnce(CompleteContext(r
, mock_image_ctx
.image_ctx
->op_work_queue
));
178 void expect_unlink_peer(MockTestImageCtx
&mock_image_ctx
,
179 MockUnlinkPeerRequest
&mock_unlink_peer_request
,
180 uint64_t snap_id
, const std::string
&peer_uuid
,
181 bool is_linked
, bool complete
, bool allow_remove
,
183 EXPECT_CALL(mock_unlink_peer_request
, send())
184 .WillOnce(Invoke([&mock_image_ctx
, &mock_unlink_peer_request
,
185 snap_id
, peer_uuid
, is_linked
, complete
, allow_remove
, r
]() {
186 ASSERT_EQ(mock_unlink_peer_request
.mirror_peer_uuid
,
188 ASSERT_EQ(mock_unlink_peer_request
.snap_id
, snap_id
);
189 ASSERT_EQ(mock_unlink_peer_request
.allow_remove
, allow_remove
);
191 auto it
= mock_image_ctx
.snap_info
.find(snap_id
);
192 ASSERT_NE(it
, mock_image_ctx
.snap_info
.end());
194 std::get_if
<cls::rbd::MirrorSnapshotNamespace
>(
195 &it
->second
.snap_namespace
);
196 ASSERT_NE(nullptr, info
);
197 ASSERT_EQ(complete
, info
->complete
);
198 ASSERT_EQ(is_linked
, info
->mirror_peer_uuids
.erase(
200 if (info
->mirror_peer_uuids
.empty()) {
201 mock_image_ctx
.snap_info
.erase(it
);
204 mock_image_ctx
.image_ctx
->op_work_queue
->queue(
205 mock_unlink_peer_request
.on_finish
, r
);
210 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, Success
) {
213 librbd::ImageCtx
*ictx
;
214 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
216 MockTestImageCtx
mock_image_ctx(*ictx
);
220 expect_clone_md_ctx(mock_image_ctx
);
221 MockUtils mock_utils
;
222 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
223 expect_get_mirror_peers(mock_image_ctx
,
224 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
225 "mirror", "mirror uuid"}}, 0);
226 expect_create_snapshot(mock_image_ctx
, 0);
227 expect_refresh_image(mock_image_ctx
, 0);
230 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
231 0U, 0U, nullptr, &ctx
);
233 ASSERT_EQ(0, ctx
.wait());
236 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessPrimary
) {
239 librbd::ImageCtx
*ictx
;
240 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
242 MockTestImageCtx
mock_image_ctx(*ictx
);
243 cls::rbd::MirrorSnapshotNamespace ns
{
244 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"uuid"}, "", CEPH_NOSNAP
};
246 snap_create(mock_image_ctx
, ns
, "mirror_snap");
250 expect_clone_md_ctx(mock_image_ctx
);
251 MockUtils mock_utils
;
252 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
253 expect_get_mirror_peers(mock_image_ctx
,
254 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
255 "mirror", "mirror uuid"}}, 0);
256 expect_create_snapshot(mock_image_ctx
, 0);
257 expect_refresh_image(mock_image_ctx
, 0);
260 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
261 0U, 0U, nullptr, &ctx
);
263 ASSERT_EQ(0, ctx
.wait());
266 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessPrimaryDemoted
) {
269 librbd::ImageCtx
*ictx
;
270 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
272 MockTestImageCtx
mock_image_ctx(*ictx
);
273 cls::rbd::MirrorSnapshotNamespace ns
{
274 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {"uuid"}, "", CEPH_NOSNAP
};
276 snap_create(mock_image_ctx
, ns
, "mirror_snap");
280 expect_clone_md_ctx(mock_image_ctx
);
281 MockUtils mock_utils
;
282 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
283 expect_get_mirror_peers(mock_image_ctx
,
284 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
285 "mirror", "mirror uuid"}}, 0);
286 expect_create_snapshot(mock_image_ctx
, 0);
287 expect_refresh_image(mock_image_ctx
, 0);
290 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
291 0U, 0U, nullptr, &ctx
);
293 ASSERT_EQ(0, ctx
.wait());
296 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessNonPrimaryDemoted
) {
299 librbd::ImageCtx
*ictx
;
300 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
302 MockTestImageCtx
mock_image_ctx(*ictx
);
303 cls::rbd::MirrorSnapshotNamespace ns
{
304 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED
, {"uuid"},
307 snap_create(mock_image_ctx
, ns
, "mirror_snap");
311 expect_clone_md_ctx(mock_image_ctx
);
312 MockUtils mock_utils
;
313 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
314 expect_get_mirror_peers(mock_image_ctx
,
315 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
316 "mirror", "mirror uuid"}}, 0);
317 expect_create_snapshot(mock_image_ctx
, 0);
318 expect_refresh_image(mock_image_ctx
, 0);
321 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
322 0U, 0U, nullptr, &ctx
);
324 ASSERT_EQ(0, ctx
.wait());
327 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessPrimaryBelowMaxSnapshots
) {
330 librbd::ImageCtx
*ictx
;
331 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
332 ictx
->config
.set_val("rbd_mirroring_max_mirroring_snapshots", "3");
334 MockTestImageCtx
mock_image_ctx(*ictx
);
335 for (int i
= 0; i
< 2; i
++) {
336 cls::rbd::MirrorSnapshotNamespace ns
{
337 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"uuid"}, "", CEPH_NOSNAP
};
339 snap_create(mock_image_ctx
, ns
, "mirror_snap");
344 expect_clone_md_ctx(mock_image_ctx
);
345 MockUtils mock_utils
;
346 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
347 expect_get_mirror_peers(mock_image_ctx
,
348 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
349 "mirror", "mirror uuid"}}, 0);
350 expect_create_snapshot(mock_image_ctx
, 0);
351 expect_refresh_image(mock_image_ctx
, 0);
354 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
355 0U, 0U, nullptr, &ctx
);
357 ASSERT_EQ(0, ctx
.wait());
360 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessPrimaryBelowMaxSnapshotsReset
) {
363 librbd::ImageCtx
*ictx
;
364 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
365 ictx
->config
.set_val("rbd_mirroring_max_mirroring_snapshots", "3");
367 MockTestImageCtx
mock_image_ctx(*ictx
);
368 for (int i
= 0; i
< 6; i
++) {
369 cls::rbd::MirrorSnapshotNamespace ns
{
370 (i
== 3 ? cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
:
371 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
),
372 {"uuid"}, "", CEPH_NOSNAP
};
374 snap_create(mock_image_ctx
, ns
, "mirror_snap");
379 expect_clone_md_ctx(mock_image_ctx
);
380 MockUtils mock_utils
;
381 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
382 expect_get_mirror_peers(mock_image_ctx
,
383 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
384 "mirror", "mirror uuid"}}, 0);
385 expect_create_snapshot(mock_image_ctx
, 0);
386 expect_refresh_image(mock_image_ctx
, 0);
389 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
390 0U, 0U, nullptr, &ctx
);
392 ASSERT_EQ(0, ctx
.wait());
395 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, CanNotError
) {
398 librbd::ImageCtx
*ictx
;
399 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
401 MockTestImageCtx
mock_image_ctx(*ictx
);
405 expect_clone_md_ctx(mock_image_ctx
);
406 MockUtils mock_utils
;
407 expect_can_create_primary_snapshot(mock_utils
, false, false, false);
410 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
411 0U, 0U, nullptr, &ctx
);
413 ASSERT_EQ(-EINVAL
, ctx
.wait());
416 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, GetMirrorPeersError
) {
419 librbd::ImageCtx
*ictx
;
420 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
422 MockTestImageCtx
mock_image_ctx(*ictx
);
426 expect_clone_md_ctx(mock_image_ctx
);
427 MockUtils mock_utils
;
428 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
429 expect_get_mirror_peers(mock_image_ctx
,
430 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
431 "mirror", "mirror uuid"}}, -EINVAL
);
434 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
435 0U, 0U, nullptr, &ctx
);
437 ASSERT_EQ(-EINVAL
, ctx
.wait());
440 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, CreateSnapshotError
) {
443 librbd::ImageCtx
*ictx
;
444 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
446 MockTestImageCtx
mock_image_ctx(*ictx
);
450 expect_clone_md_ctx(mock_image_ctx
);
451 MockUtils mock_utils
;
452 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
453 expect_get_mirror_peers(mock_image_ctx
,
454 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
455 "mirror", "mirror uuid"}}, 0);
456 expect_create_snapshot(mock_image_ctx
, -EINVAL
);
459 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
460 0U, 0U, nullptr, &ctx
);
462 ASSERT_EQ(-EINVAL
, ctx
.wait());
465 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkPrimaryNoPeer
) {
468 librbd::ImageCtx
*ictx
;
469 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
471 MockTestImageCtx
mock_image_ctx(*ictx
);
472 cls::rbd::MirrorSnapshotNamespace ns
{
473 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {}, "", CEPH_NOSNAP
};
475 snap_create(mock_image_ctx
, ns
, "mirror_snap");
479 expect_clone_md_ctx(mock_image_ctx
);
480 MockUtils mock_utils
;
481 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
482 expect_get_mirror_peers(mock_image_ctx
,
483 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
484 "mirror", "mirror uuid"}}, 0);
485 expect_create_snapshot(mock_image_ctx
, 0);
486 expect_refresh_image(mock_image_ctx
, 0);
487 MockUnlinkPeerRequest mock_unlink_peer_request
;
488 auto it
= mock_image_ctx
.snap_info
.rbegin();
489 auto snap_id
= it
->first
;
490 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
491 false, true, true, 0);
494 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
495 0U, 0U, nullptr, &ctx
);
497 ASSERT_EQ(0, ctx
.wait());
500 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkPrimaryDemotedNoPeer
) {
503 librbd::ImageCtx
*ictx
;
504 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
506 MockTestImageCtx
mock_image_ctx(*ictx
);
507 cls::rbd::MirrorSnapshotNamespace ns
{
508 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", CEPH_NOSNAP
};
510 snap_create(mock_image_ctx
, ns
, "mirror_snap");
514 expect_clone_md_ctx(mock_image_ctx
);
515 MockUtils mock_utils
;
516 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
517 expect_get_mirror_peers(mock_image_ctx
,
518 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
519 "mirror", "mirror uuid"}}, 0);
520 expect_create_snapshot(mock_image_ctx
, 0);
521 expect_refresh_image(mock_image_ctx
, 0);
522 MockUnlinkPeerRequest mock_unlink_peer_request
;
523 auto it
= mock_image_ctx
.snap_info
.rbegin();
524 auto snap_id
= it
->first
;
525 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
526 false, true, true, 0);
529 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
530 0U, 0U, nullptr, &ctx
);
532 ASSERT_EQ(0, ctx
.wait());
535 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkNonPrimaryDemotedNoPeer
) {
538 librbd::ImageCtx
*ictx
;
539 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
541 MockTestImageCtx
mock_image_ctx(*ictx
);
542 cls::rbd::MirrorSnapshotNamespace ns
{
543 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED
, {},
546 snap_create(mock_image_ctx
, ns
, "mirror_snap");
550 expect_clone_md_ctx(mock_image_ctx
);
551 MockUtils mock_utils
;
552 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
553 expect_get_mirror_peers(mock_image_ctx
,
554 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
555 "mirror", "mirror uuid"}}, 0);
556 expect_create_snapshot(mock_image_ctx
, 0);
557 expect_refresh_image(mock_image_ctx
, 0);
558 MockUnlinkPeerRequest mock_unlink_peer_request
;
559 auto it
= mock_image_ctx
.snap_info
.rbegin();
560 auto snap_id
= it
->first
;
561 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
562 false, true, true, 0);
565 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
566 0U, 0U, nullptr, &ctx
);
568 ASSERT_EQ(0, ctx
.wait());
571 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkOrphanNoPeer
) {
574 librbd::ImageCtx
*ictx
;
575 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
577 MockTestImageCtx
mock_image_ctx(*ictx
);
578 cls::rbd::MirrorSnapshotNamespace ns
{
579 cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY
, {}, "", CEPH_NOSNAP
};
581 snap_create(mock_image_ctx
, ns
, "mirror_snap");
585 expect_clone_md_ctx(mock_image_ctx
);
586 MockUtils mock_utils
;
587 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
588 expect_get_mirror_peers(mock_image_ctx
,
589 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
590 "mirror", "mirror uuid"}}, 0);
591 expect_create_snapshot(mock_image_ctx
, 0);
592 expect_refresh_image(mock_image_ctx
, 0);
593 MockUnlinkPeerRequest mock_unlink_peer_request
;
594 auto it
= mock_image_ctx
.snap_info
.rbegin();
595 auto snap_id
= it
->first
;
596 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
597 false, true, true, 0);
600 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
601 0U, 0U, nullptr, &ctx
);
603 ASSERT_EQ(0, ctx
.wait());
606 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkPrimaryIncomplete
) {
609 librbd::ImageCtx
*ictx
;
610 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
612 MockTestImageCtx
mock_image_ctx(*ictx
);
613 cls::rbd::MirrorSnapshotNamespace ns
{
614 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"uuid"}, "", CEPH_NOSNAP
};
616 snap_create(mock_image_ctx
, ns
, "mirror_snap");
620 expect_clone_md_ctx(mock_image_ctx
);
621 MockUtils mock_utils
;
622 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
623 expect_get_mirror_peers(mock_image_ctx
,
624 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
625 "mirror", "mirror uuid"}}, 0);
626 expect_create_snapshot(mock_image_ctx
, 0);
627 expect_refresh_image(mock_image_ctx
, 0);
628 MockUnlinkPeerRequest mock_unlink_peer_request
;
629 auto it
= mock_image_ctx
.snap_info
.rbegin();
630 auto snap_id
= it
->first
;
631 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
632 true, false, true, 0);
635 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
636 0U, 0U, nullptr, &ctx
);
638 ASSERT_EQ(0, ctx
.wait());
641 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkPrimaryMaxSnapshots
) {
644 librbd::ImageCtx
*ictx
;
645 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
646 ictx
->config
.set_val("rbd_mirroring_max_mirroring_snapshots", "3");
648 MockTestImageCtx
mock_image_ctx(*ictx
);
649 for (int i
= 0; i
< 3; i
++) {
650 cls::rbd::MirrorSnapshotNamespace ns
{
651 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"uuid"}, "", CEPH_NOSNAP
};
653 snap_create(mock_image_ctx
, ns
, "mirror_snap");
658 expect_clone_md_ctx(mock_image_ctx
);
659 MockUtils mock_utils
;
660 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
661 expect_get_mirror_peers(mock_image_ctx
,
662 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
663 "mirror", "mirror uuid"}}, 0);
664 expect_create_snapshot(mock_image_ctx
, 0);
665 expect_refresh_image(mock_image_ctx
, 0);
666 MockUnlinkPeerRequest mock_unlink_peer_request
;
667 auto it
= mock_image_ctx
.snap_info
.rbegin();
668 auto snap_id
= it
->first
;
669 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
670 true, true, true, 0);
673 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
674 0U, 0U, nullptr, &ctx
);
676 ASSERT_EQ(0, ctx
.wait());
679 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkPrimaryMaxSnapshotsReset
) {
682 librbd::ImageCtx
*ictx
;
683 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
684 ictx
->config
.set_val("rbd_mirroring_max_mirroring_snapshots", "3");
686 MockTestImageCtx
mock_image_ctx(*ictx
);
687 for (int i
= 0; i
< 7; i
++) {
688 cls::rbd::MirrorSnapshotNamespace ns
{
689 (i
== 3 ? cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
:
690 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
),
691 {"uuid"}, "", CEPH_NOSNAP
};
693 snap_create(mock_image_ctx
, ns
, "mirror_snap");
698 expect_clone_md_ctx(mock_image_ctx
);
699 MockUtils mock_utils
;
700 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
701 expect_get_mirror_peers(mock_image_ctx
,
702 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
703 "mirror", "mirror uuid"}}, 0);
704 expect_create_snapshot(mock_image_ctx
, 0);
705 expect_refresh_image(mock_image_ctx
, 0);
706 MockUnlinkPeerRequest mock_unlink_peer_request
;
707 auto it
= mock_image_ctx
.snap_info
.rbegin();
708 auto snap_id
= it
->first
;
709 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
710 true, true, true, 0);
713 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
714 0U, 0U, nullptr, &ctx
);
716 ASSERT_EQ(0, ctx
.wait());
719 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkMultiplePeers
) {
722 librbd::ImageCtx
*ictx
;
723 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
724 ictx
->config
.set_val("rbd_mirroring_max_mirroring_snapshots", "3");
726 MockTestImageCtx
mock_image_ctx(*ictx
);
727 for (int i
= 0; i
< 3; i
++) {
728 cls::rbd::MirrorSnapshotNamespace ns
{
729 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {"uuid1", "uuid2"}, "",
732 snap_create(mock_image_ctx
, ns
, "mirror_snap");
737 expect_clone_md_ctx(mock_image_ctx
);
738 MockUtils mock_utils
;
739 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
740 expect_get_mirror_peers(mock_image_ctx
,
741 {{"uuid1", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
742 "mirror", "mirror uuid"},
743 {"uuid2", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
744 "mirror", "mirror uuid"}}, 0);
745 expect_create_snapshot(mock_image_ctx
, 0);
746 expect_refresh_image(mock_image_ctx
, 0);
747 MockUnlinkPeerRequest mock_unlink_peer_request
;
748 auto it
= mock_image_ctx
.snap_info
.rbegin();
749 auto snap_id
= it
->first
;
750 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid1",
751 true, true, true, 0);
752 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid2",
753 true, true, true, 0);
756 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
757 0U, 0U, nullptr, &ctx
);
759 ASSERT_EQ(0, ctx
.wait());
762 TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest
, SuccessUnlinkMultipleSnapshots
) {
765 librbd::ImageCtx
*ictx
;
766 ASSERT_EQ(0, open_image(m_image_name
, &ictx
));
768 MockTestImageCtx
mock_image_ctx(*ictx
);
769 cls::rbd::MirrorSnapshotNamespace ns1
{
770 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY
, {}, "", CEPH_NOSNAP
};
772 snap_create(mock_image_ctx
, ns1
, "mirror_snap");
773 cls::rbd::MirrorSnapshotNamespace ns2
{
774 cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED
, {}, "", CEPH_NOSNAP
};
776 snap_create(mock_image_ctx
, ns2
, "mirror_snap");
780 expect_clone_md_ctx(mock_image_ctx
);
781 MockUtils mock_utils
;
782 expect_can_create_primary_snapshot(mock_utils
, false, false, true);
783 expect_get_mirror_peers(mock_image_ctx
,
784 {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX
, "ceph",
785 "mirror", "mirror uuid"}}, 0);
786 expect_create_snapshot(mock_image_ctx
, 0);
787 expect_refresh_image(mock_image_ctx
, 0);
788 MockUnlinkPeerRequest mock_unlink_peer_request
;
789 auto it
= mock_image_ctx
.snap_info
.begin();
790 auto snap_id
= it
->first
;
791 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
792 false, true, true, 0);
793 snap_id
= (++it
)->first
;
794 expect_unlink_peer(mock_image_ctx
, mock_unlink_peer_request
, snap_id
, "uuid",
795 false, true, true, 0);
798 auto req
= new MockCreatePrimaryRequest(&mock_image_ctx
, "gid", CEPH_NOSNAP
,
799 0U, 0U, nullptr, &ctx
);
801 ASSERT_EQ(0, ctx
.wait());
804 } // namespace snapshot
805 } // namespace mirror
806 } // namespace librbd