void expect_unlink_peer(MockTestImageCtx &mock_image_ctx,
MockUnlinkPeerRequest &mock_unlink_peer_request,
uint64_t snap_id, const std::string &peer_uuid,
- int r) {
+ bool is_linked, int r) {
EXPECT_CALL(mock_unlink_peer_request, send())
- .WillOnce(Invoke([&mock_image_ctx, &mock_unlink_peer_request, snap_id,
- peer_uuid, r]() {
+ .WillOnce(Invoke([&mock_image_ctx, &mock_unlink_peer_request,
+ snap_id, peer_uuid, is_linked, r]() {
ASSERT_EQ(mock_unlink_peer_request.mirror_peer_uuid,
peer_uuid);
ASSERT_EQ(mock_unlink_peer_request.snap_id, snap_id);
boost::get<cls::rbd::MirrorSnapshotNamespace>(
&it->second.snap_namespace);
ASSERT_NE(nullptr, info);
- ASSERT_NE(0, info->mirror_peer_uuids.erase(
- peer_uuid));
+ ASSERT_EQ(is_linked, info->mirror_peer_uuids.erase(
+ peer_uuid));
if (info->mirror_peer_uuids.empty()) {
mock_image_ctx.snap_info.erase(it);
}
auto it = mock_image_ctx.snap_info.rbegin();
auto snap_id = it->first;
expect_unlink_peer(mock_image_ctx, mock_unlink_peer_request, snap_id, "uuid",
- 0);
+ true, 0);
+ C_SaferCond ctx;
+ auto req = new MockCreatePrimaryRequest(&mock_image_ctx, "gid", CEPH_NOSNAP,
+ 0U, nullptr, &ctx);
+ req->send();
+ ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest, SuccessUnlinkNoPeer) {
+ REQUIRE_FORMAT_V2();
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+ ictx->config.set_val("conf_rbd_mirroring_max_mirroring_snapshots", "3");
+
+ MockTestImageCtx mock_image_ctx(*ictx);
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {}, "", CEPH_NOSNAP};
+ snap_create(mock_image_ctx, ns, "mirror_snap");
+
+ InSequence seq;
+
+ expect_clone_md_ctx(mock_image_ctx);
+ MockUtils mock_utils;
+ expect_can_create_primary_snapshot(mock_utils, false, false, true);
+ expect_get_mirror_peers(mock_image_ctx,
+ {{"uuid", cls::rbd::MIRROR_PEER_DIRECTION_TX, "ceph",
+ "mirror", "mirror uuid"}}, 0);
+ expect_create_snapshot(mock_image_ctx, 0);
+ MockUnlinkPeerRequest mock_unlink_peer_request;
+ auto it = mock_image_ctx.snap_info.rbegin();
+ auto snap_id = it->first;
+ std::list<string> peer_uuids = {"uuid"};
+ expect_unlink_peer(mock_image_ctx, mock_unlink_peer_request, snap_id, "uuid",
+ false, 0);
+
+ C_SaferCond ctx;
+ auto req = new MockCreatePrimaryRequest(&mock_image_ctx, "gid", CEPH_NOSNAP,
+ 0U, nullptr, &ctx);
+ req->send();
+ ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockMirrorSnapshotCreatePrimaryRequest, SuccessUnlinkMultiplePeers) {
+ REQUIRE_FORMAT_V2();
+
+ librbd::ImageCtx *ictx;
+ ASSERT_EQ(0, open_image(m_image_name, &ictx));
+ ictx->config.set_val("conf_rbd_mirroring_max_mirroring_snapshots", "3");
+
+ MockTestImageCtx mock_image_ctx(*ictx);
+ for (int i = 0; i < 3; i++) {
+ cls::rbd::MirrorSnapshotNamespace ns{
+ cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"uuid1", "uuid2"}, "",
+ CEPH_NOSNAP};
+ snap_create(mock_image_ctx, ns, "mirror_snap");
+ }
+
+ InSequence seq;
+
+ expect_clone_md_ctx(mock_image_ctx);
+ MockUtils mock_utils;
+ expect_can_create_primary_snapshot(mock_utils, false, false, true);
+ expect_get_mirror_peers(mock_image_ctx,
+ {{"uuid1", cls::rbd::MIRROR_PEER_DIRECTION_TX, "ceph",
+ "mirror", "mirror uuid"},
+ {"uuid2", cls::rbd::MIRROR_PEER_DIRECTION_TX, "ceph",
+ "mirror", "mirror uuid"}}, 0);
+ expect_create_snapshot(mock_image_ctx, 0);
+ MockUnlinkPeerRequest mock_unlink_peer_request;
+ auto it = mock_image_ctx.snap_info.rbegin();
+ auto snap_id = it->first;
+ expect_unlink_peer(mock_image_ctx, mock_unlink_peer_request, snap_id, "uuid1",
+ true, 0);
+ expect_unlink_peer(mock_image_ctx, mock_unlink_peer_request, snap_id, "uuid2",
+ true, 0);
C_SaferCond ctx;
auto req = new MockCreatePrimaryRequest(&mock_image_ctx, "gid", CEPH_NOSNAP,
0U, nullptr, &ctx);
ASSERT_EQ(0, m_rbd.mirror_peer_site_add(m_ioctx, &peer_uuid,
RBD_MIRROR_PEER_DIRECTION_RX_TX,
"cluster", "client"));
+ // The mirroring was enabled when no peer was configured. Therefore, the
+ // initial snapshot has no peers linked and will be removed after the
+ // creation of a new mirror snapshot.
ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
vector<librbd::snap_info_t> snaps;
ASSERT_EQ(0, image.snap_list(snaps));
- ASSERT_EQ(2U, snaps.size());
- ASSERT_EQ(snaps[1].id, snap_id);
+ ASSERT_EQ(1U, snaps.size());
+ ASSERT_EQ(snaps[0].id, snap_id);
+ ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id));
snaps.clear();