mirror of
https://github.com/ceph/ceph
synced 2026-08-01 22:45:39 +00:00
rbd-mirror: prune obsolete primary mirror snapshots after relocation
Previously, obsolete primary and demoted primary snapshots on the secondary cluster were not cleaned up immediately after relocation. Instead, old primary snapshots remained until a subsequent promote operation triggered their cleanup, while old demoted primary snapshots persisted until a later demote operation removed them. Adding changes for proactive cleanup of obsolete primary and demoted primary snapshots that are no longer required after relocation. Also adding test coverage to validate the cleanup behavior. Fixes: https://tracker.ceph.com/issues/76154 Signed-off-by: Miki Patel <miki.patel132@gmail.com>
This commit is contained in:
parent
e98037a639
commit
a10f58df8c
@ -274,6 +274,60 @@ wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
|
||||
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped'
|
||||
compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
|
||||
|
||||
if [ "${RBD_MIRROR_MODE}" = "snapshot" ]; then
|
||||
testlog "TEST: failover / failback loop with snapshot presence checks"
|
||||
snap_id_1=""
|
||||
demote_snap_id_1=""
|
||||
snap_id_2=""
|
||||
demote_snap_id_2=""
|
||||
get_newest_complete_mirror_snapshot_id ${CLUSTER2} ${POOL} ${image} snap_id_2
|
||||
for i in `seq 1 5`; do
|
||||
demote_image ${CLUSTER2} ${POOL} ${image}
|
||||
wait_for_image_replay_stopped ${CLUSTER1} ${POOL} ${image}
|
||||
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+unknown'
|
||||
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
|
||||
get_newest_complete_mirror_snapshot_id ${CLUSTER2} ${POOL} ${image} demote_snap_id_2
|
||||
wait_for_non_primary_snap_present ${CLUSTER1} ${POOL} ${image} ${demote_snap_id_2}
|
||||
wait_for_non_primary_snap_not_present ${CLUSTER1} ${POOL} ${image} ${snap_id_2}
|
||||
|
||||
promote_image ${CLUSTER1} ${POOL} ${image}
|
||||
wait_for_image_replay_started ${CLUSTER2} ${POOL} ${image}
|
||||
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+stopped'
|
||||
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+replaying'
|
||||
get_newest_complete_mirror_snapshot_id ${CLUSTER1} ${POOL} ${image} snap_id_1
|
||||
wait_for_non_primary_snap_present ${CLUSTER2} ${POOL} ${image} ${snap_id_1}
|
||||
wait_for_snap_not_present ${CLUSTER2} ${POOL} ${image} ${snap_id_2}
|
||||
wait_for_snap_not_present ${CLUSTER2} ${POOL} ${image} ${demote_snap_id_2}
|
||||
|
||||
demote_image ${CLUSTER1} ${POOL} ${image}
|
||||
wait_for_non_primary_snap_not_present ${CLUSTER1} ${POOL} ${image} ${demote_snap_id_2}
|
||||
wait_for_image_replay_stopped ${CLUSTER2} ${POOL} ${image}
|
||||
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+unknown'
|
||||
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
|
||||
get_newest_complete_mirror_snapshot_id ${CLUSTER1} ${POOL} ${image} demote_snap_id_1
|
||||
wait_for_non_primary_snap_present ${CLUSTER2} ${POOL} ${image} ${demote_snap_id_1}
|
||||
wait_for_non_primary_snap_not_present ${CLUSTER2} ${POOL} ${image} ${snap_id_1}
|
||||
|
||||
promote_image ${CLUSTER2} ${POOL} ${image}
|
||||
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
|
||||
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped'
|
||||
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying'
|
||||
get_newest_complete_mirror_snapshot_id ${CLUSTER2} ${POOL} ${image} snap_id_2
|
||||
wait_for_non_primary_snap_present ${CLUSTER1} ${POOL} ${image} ${snap_id_2}
|
||||
wait_for_snap_not_present ${CLUSTER1} ${POOL} ${image} ${snap_id_1}
|
||||
wait_for_snap_not_present ${CLUSTER1} ${POOL} ${image} ${demote_snap_id_1}
|
||||
done
|
||||
# expected snapshot in non-primary image: non-primary
|
||||
SNAPS=$(get_snaps_json ${CLUSTER1} ${POOL} ${image})
|
||||
jq -e 'length == 1' <<< ${SNAPS}
|
||||
jq -e '.[0].namespace["type"] == "mirror" and .[0].namespace["state"] == "non-primary"' <<< ${SNAPS}
|
||||
# expected snapshots in primary image: non-primary demoted, primary
|
||||
SNAPS=$(get_snaps_json ${CLUSTER2} ${POOL} ${image})
|
||||
jq -e 'length == 2' <<< ${SNAPS}
|
||||
jq -e '.[0].namespace["type"] == "mirror" and .[0].namespace["state"] == "demoted" and (.[0]["name"] | startswith(".mirror.non_primary"))' <<< ${SNAPS}
|
||||
jq -e '.[1].namespace["type"] == "mirror" and .[1].namespace["state"] == "primary"' <<< ${SNAPS}
|
||||
fi
|
||||
|
||||
testlog "TEST: failover / failback loop"
|
||||
for i in `seq 1 20`; do
|
||||
demote_image ${CLUSTER2} ${POOL} ${image}
|
||||
|
||||
@ -826,6 +826,43 @@ wait_for_non_primary_snap_present()
|
||||
return 1
|
||||
}
|
||||
|
||||
wait_for_snap_not_present()
|
||||
{
|
||||
local cluster=$1
|
||||
local pool=$2
|
||||
local image=$3
|
||||
local snap_id=$4
|
||||
local snap_count
|
||||
local s
|
||||
|
||||
for s in 0.1 1 2 4 8 8 8 8 8 8 8 8 16 16 32 32; do
|
||||
sleep ${s}
|
||||
snap_count=$(rbd --cluster ${cluster} snap list --all ${pool}/${image} --format xml | \
|
||||
xmlstarlet sel -t -v "count(//snapshots/snapshot[id='${snap_id}'])")
|
||||
[ "${snap_count}" = "0" ] && return 0
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
wait_for_non_primary_snap_not_present()
|
||||
{
|
||||
local cluster=$1
|
||||
local pool=$2
|
||||
local image=$3
|
||||
local primary_snap_id=$4
|
||||
local snap_count
|
||||
local s
|
||||
|
||||
for s in 0.1 1 2 4 8 8 8 8 8 8 8 8 16 16 32 32; do
|
||||
sleep ${s}
|
||||
snap_count=$(rbd --cluster ${cluster} snap list --all ${pool}/${image} --format xml | \
|
||||
xmlstarlet sel -t -v "count(//snapshots/snapshot/namespace[primary_snap_id='${primary_snap_id}'])")
|
||||
[ "${snap_count}" = "0" ] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
wait_for_snapshot_sync_complete()
|
||||
{
|
||||
local local_cluster=$1
|
||||
|
||||
@ -495,8 +495,8 @@ public:
|
||||
}));
|
||||
}
|
||||
|
||||
void expect_prune_non_primary_snapshot(librbd::MockTestImageCtx& mock_image_ctx,
|
||||
uint64_t snap_id, int r) {
|
||||
void expect_prune_mirror_snapshot(librbd::MockTestImageCtx& mock_image_ctx,
|
||||
uint64_t snap_id, int r) {
|
||||
EXPECT_CALL(mock_image_ctx, get_snap_info(snap_id))
|
||||
.WillOnce(Invoke([&mock_image_ctx](uint64_t snap_id) -> librbd::SnapInfo* {
|
||||
auto it = mock_image_ctx.snap_info.find(snap_id);
|
||||
@ -734,8 +734,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InitShutDown) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -788,8 +789,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -913,7 +915,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SyncSnapshot) {
|
||||
4, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
expect_prune_non_primary_snapshot(mock_local_image_ctx, 11, 0);
|
||||
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
|
||||
|
||||
// idle
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
@ -966,8 +968,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncInitial) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1051,8 +1054,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDelta) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1129,7 +1133,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDelta) {
|
||||
2, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
expect_prune_non_primary_snapshot(mock_local_image_ctx, 11, 0);
|
||||
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
|
||||
|
||||
// idle
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
@ -1172,8 +1176,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDeltaDemote) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1201,7 +1206,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDeltaDemote) {
|
||||
mock_local_image_ctx.snap_info = {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
|
||||
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
|
||||
@ -1229,7 +1234,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDeltaDemote) {
|
||||
false, 0);
|
||||
expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
|
||||
|
||||
// idle
|
||||
// prune primary demotion snap1
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
expect_is_refresh_required(mock_remote_image_ctx, true);
|
||||
expect_refresh(
|
||||
@ -1244,13 +1249,26 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedSyncDeltaDemote) {
|
||||
mock_local_image_ctx, {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
|
||||
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
|
||||
2, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
|
||||
|
||||
// idle
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
expect_is_refresh_required(mock_remote_image_ctx, false);
|
||||
expect_is_refresh_required(mock_local_image_ctx, true);
|
||||
expect_refresh(
|
||||
mock_local_image_ctx, {
|
||||
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
|
||||
2, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
|
||||
// wake-up replayer
|
||||
update_watch_ctx->handle_notify();
|
||||
@ -1281,8 +1299,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncInitial) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1365,8 +1384,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDelta) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1404,7 +1424,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDelta) {
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
expect_is_refresh_required(mock_remote_image_ctx, false);
|
||||
expect_is_refresh_required(mock_local_image_ctx, false);
|
||||
expect_prune_non_primary_snapshot(mock_local_image_ctx, 12, 0);
|
||||
expect_prune_mirror_snapshot(mock_local_image_ctx, 12, 0);
|
||||
|
||||
// sync snap2
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
@ -1462,7 +1482,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDelta) {
|
||||
2, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
expect_prune_non_primary_snapshot(mock_local_image_ctx, 11, 0);
|
||||
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
|
||||
|
||||
// idle
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
@ -1505,8 +1525,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1534,7 +1555,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
|
||||
mock_local_image_ctx.snap_info = {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
|
||||
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
|
||||
@ -1545,7 +1566,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
expect_is_refresh_required(mock_remote_image_ctx, false);
|
||||
expect_is_refresh_required(mock_local_image_ctx, false);
|
||||
expect_prune_non_primary_snapshot(mock_local_image_ctx, 12, 0);
|
||||
expect_prune_mirror_snapshot(mock_local_image_ctx, 12, 0);
|
||||
|
||||
// sync snap2
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
@ -1555,7 +1576,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
|
||||
mock_local_image_ctx, {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
|
||||
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
MockSnapshotCopyRequest mock_snapshot_copy_request;
|
||||
@ -1581,7 +1602,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
|
||||
false, 0);
|
||||
expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
|
||||
|
||||
// idle
|
||||
// prune primary demotion snap1
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
expect_is_refresh_required(mock_remote_image_ctx, true);
|
||||
expect_refresh(
|
||||
@ -1596,13 +1617,26 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, InterruptedPendingSyncDeltaDemote)
|
||||
mock_local_image_ctx, {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
|
||||
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
{13U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
|
||||
2, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
expect_prune_mirror_snapshot(mock_local_image_ctx, 11, 0);
|
||||
|
||||
// idle
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
expect_is_refresh_required(mock_remote_image_ctx, false);
|
||||
expect_is_refresh_required(mock_local_image_ctx, true);
|
||||
expect_refresh(
|
||||
mock_local_image_ctx, {
|
||||
{13U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
|
||||
2, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
|
||||
// wake-up replayer
|
||||
update_watch_ctx->handle_notify();
|
||||
@ -1633,8 +1667,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1687,8 +1722,8 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteImageDemoted) {
|
||||
expect_refresh(
|
||||
mock_local_image_ctx, {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {}, "remote mirror uuid",
|
||||
1, true, 0, {}},
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
|
||||
{"local mirror peer uuid"}, "remote mirror uuid", 1, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
|
||||
@ -1722,8 +1757,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1740,7 +1776,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LocalImagePromoted) {
|
||||
mock_local_image_ctx.snap_info = {
|
||||
{1U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY,
|
||||
{"remote mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}}};
|
||||
|
||||
// idle
|
||||
@ -1778,8 +1814,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ResyncRequested) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1834,8 +1871,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ResyncRequestedRemoteNotPrimary) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1890,8 +1928,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ResyncRequestedRemoteNotPrimary) {
|
||||
expect_refresh(
|
||||
mock_local_image_ctx, {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED, {"uuid"},
|
||||
"remote mirror uuid", 1, true, 0, {{1, CEPH_NOSNAP}}},
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
|
||||
{"local mirror peer uuid"}, "remote mirror uuid", 1, true, 0,
|
||||
{{1, CEPH_NOSNAP}}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
|
||||
@ -1923,8 +1962,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterLocalUpdateWatcherError) {
|
||||
mock_image_meta);
|
||||
MockReplayerListener mock_replayer_listener;
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1956,8 +1996,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RegisterRemoteUpdateWatcherError)
|
||||
mock_image_meta);
|
||||
MockReplayerListener mock_replayer_listener;
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -1995,8 +2036,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterRemoteUpdateWatcherError
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2037,8 +2079,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnregisterLocalUpdateWatcherError)
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2079,8 +2122,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, LoadImageMetaError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2127,8 +2171,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshLocalImageError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2178,8 +2223,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RefreshRemoteImageError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2228,8 +2274,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopySnapshotsError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2288,8 +2335,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, GetImageStateError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2350,8 +2398,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CreateNonPrimarySnapshotError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2416,8 +2465,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateMirrorImageStateError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2484,8 +2534,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RequestSyncError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2554,8 +2605,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, CopyImageError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2627,8 +2679,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UpdateNonPrimarySnapshotError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2704,8 +2757,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkPeerError) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2792,8 +2846,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SplitBrain) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2855,8 +2910,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteSnapshotMissingSplitBrain) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2923,8 +2979,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -2956,8 +3013,8 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
|
||||
0, {}, 0, 0, {}}},
|
||||
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {}, "", CEPH_NOSNAP,
|
||||
true, 0, {}},
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
|
||||
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}}};
|
||||
|
||||
// attach to promoted remote image
|
||||
@ -2988,7 +3045,7 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
|
||||
false, 0);
|
||||
expect_notify_sync_complete(mock_instance_watcher, mock_local_image_ctx.id);
|
||||
|
||||
// idle
|
||||
// prune primary demotion snap2
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
expect_is_refresh_required(mock_remote_image_ctx, true);
|
||||
expect_refresh(
|
||||
@ -2997,11 +3054,11 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
|
||||
0, {}, 0, 0, {}}},
|
||||
{2U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY_DEMOTED,
|
||||
{"remote mirror peer uuid"}, "local mirror uuid", 12U, true, 0, {}},
|
||||
{}, "local mirror uuid", 12U, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
{3U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {}, "", CEPH_NOSNAP, true, 0,
|
||||
{}},
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY, {"remote mirror peer uuid"},
|
||||
"", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}}
|
||||
}, 0);
|
||||
expect_is_refresh_required(mock_local_image_ctx, true);
|
||||
@ -3010,8 +3067,8 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
|
||||
0, {}, 0, 0, {}}},
|
||||
{12U, librbd::SnapInfo{"snap2", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED, {}, "", CEPH_NOSNAP,
|
||||
true, 0, {}},
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED,
|
||||
{"local mirror peer uuid"}, "", CEPH_NOSNAP, true, 0, {}},
|
||||
0, {}, 0, 0, {}}},
|
||||
{13U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {},
|
||||
@ -3019,6 +3076,22 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, RemoteFailover) {
|
||||
{{1, 11}, {2, 12}, {3, CEPH_NOSNAP}}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
expect_prune_mirror_snapshot(mock_local_image_ctx, 12, 0);
|
||||
|
||||
// idle
|
||||
expect_load_image_meta(mock_image_meta, false, 0);
|
||||
expect_is_refresh_required(mock_remote_image_ctx, false);
|
||||
expect_is_refresh_required(mock_local_image_ctx, true);
|
||||
expect_refresh(
|
||||
mock_local_image_ctx, {
|
||||
{11U, librbd::SnapInfo{"snap1", cls::rbd::UserSnapshotNamespace{},
|
||||
0, {}, 0, 0, {}}},
|
||||
{13U, librbd::SnapInfo{"snap3", cls::rbd::MirrorSnapshotNamespace{
|
||||
cls::rbd::MIRROR_SNAPSHOT_STATE_NON_PRIMARY, {},
|
||||
"remote mirror uuid", 3, true, 0,
|
||||
{{1, 11}, {2, 12}, {3, CEPH_NOSNAP}}},
|
||||
0, {}, 0, 0, {}}},
|
||||
}, 0);
|
||||
|
||||
// wake-up replayer
|
||||
update_watch_ctx->handle_notify();
|
||||
@ -3065,8 +3138,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, UnlinkRemoteSnapshot) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -3143,8 +3217,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, SkipImageSync) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -3222,8 +3297,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ImageNameUpdated) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
{"remote mirror uuid", "remote mirror peer uuid"});
|
||||
@ -3284,8 +3360,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ApplyImageStatePendingShutdown) {
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
C_SaferCond shutdown_ctx;
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
@ -3371,8 +3448,9 @@ TEST_F(TestMockImageReplayerSnapshotReplayer, ApplyImageStateErrorPendingShutdow
|
||||
mock_remote_image_ctx,
|
||||
mock_image_meta);
|
||||
MockReplayer mock_replayer{&mock_threads, &mock_instance_watcher,
|
||||
"local mirror uuid", &m_pool_meta_cache,
|
||||
&mock_state_builder, &mock_replayer_listener};
|
||||
"local mirror uuid", "local mirror peer uuid",
|
||||
&m_pool_meta_cache, &mock_state_builder,
|
||||
&mock_replayer_listener};
|
||||
C_SaferCond shutdown_ctx;
|
||||
m_pool_meta_cache.set_remote_pool_meta(
|
||||
m_remote_fsid, m_remote_io_ctx.get_id(),
|
||||
|
||||
@ -178,9 +178,11 @@ struct StateBuilder<librbd::MockTestImageCtx> {
|
||||
}
|
||||
|
||||
MOCK_METHOD1(close, void(Context*));
|
||||
MOCK_METHOD5(create_replayer, Replayer*(Threads<librbd::MockTestImageCtx>*,
|
||||
MOCK_METHOD6(create_replayer, Replayer*(Threads<librbd::MockTestImageCtx>*,
|
||||
InstanceWatcher<librbd::MockTestImageCtx>*,
|
||||
const std::string&, PoolMetaCache*,
|
||||
const std::string&,
|
||||
const std::string&,
|
||||
PoolMetaCache*,
|
||||
ReplayerListener*));
|
||||
|
||||
StateBuilder() {
|
||||
@ -312,8 +314,8 @@ public:
|
||||
|
||||
void expect_create_replayer(MockStateBuilder& mock_state_builder,
|
||||
MockReplayer& mock_replayer) {
|
||||
EXPECT_CALL(mock_state_builder, create_replayer(_, _, _, _, _))
|
||||
.WillOnce(WithArg<4>(
|
||||
EXPECT_CALL(mock_state_builder, create_replayer(_, _, _, _, _, _))
|
||||
.WillOnce(WithArg<5>(
|
||||
Invoke([&mock_replayer]
|
||||
(image_replayer::ReplayerListener* replayer_listener) {
|
||||
mock_replayer.replayer_listener = replayer_listener;
|
||||
|
||||
@ -431,6 +431,7 @@ void ImageReplayer<I>::start_replay() {
|
||||
ceph_assert(m_replayer == nullptr);
|
||||
m_replayer = m_state_builder->create_replayer(m_threads, m_instance_watcher,
|
||||
m_local_mirror_uuid,
|
||||
m_remote_image_peer.uuid,
|
||||
m_pool_meta_cache,
|
||||
m_replayer_listener);
|
||||
|
||||
|
||||
@ -116,7 +116,7 @@ struct Peer {
|
||||
|
||||
template <typename I>
|
||||
std::ostream& operator<<(std::ostream& os, const Peer<I>& peer) {
|
||||
return os << "uuid=" << peer.uuid << ", "
|
||||
return os << "uuid=" << peer.uuid << ", remote_pool_meta="
|
||||
<< peer.remote_pool_meta;
|
||||
}
|
||||
|
||||
|
||||
@ -75,6 +75,7 @@ public:
|
||||
Threads<ImageCtxT>* threads,
|
||||
InstanceWatcher<ImageCtxT>* instance_watcher,
|
||||
const std::string& local_mirror_uuid,
|
||||
const std::string& local_mirror_peer_uuid,
|
||||
PoolMetaCache* pool_meta_cache,
|
||||
ReplayerListener* replayer_listener) = 0;
|
||||
|
||||
|
||||
@ -106,6 +106,7 @@ image_replayer::Replayer* StateBuilder<I>::create_replayer(
|
||||
Threads<I>* threads,
|
||||
InstanceWatcher<I>* instance_watcher,
|
||||
const std::string& local_mirror_uuid,
|
||||
const std::string& local_mirror_peer_uuid,
|
||||
PoolMetaCache* pool_meta_cache,
|
||||
ReplayerListener* replayer_listener) {
|
||||
return Replayer<I>::create(
|
||||
|
||||
@ -65,6 +65,7 @@ public:
|
||||
Threads<ImageCtxT>* threads,
|
||||
InstanceWatcher<ImageCtxT>* instance_watcher,
|
||||
const std::string& local_mirror_uuid,
|
||||
const std::string& local_mirror_peer_uuid,
|
||||
PoolMetaCache* pool_meta_cache,
|
||||
ReplayerListener* replayer_listener) override;
|
||||
|
||||
|
||||
@ -116,12 +116,14 @@ Replayer<I>::Replayer(
|
||||
Threads<I>* threads,
|
||||
InstanceWatcher<I>* instance_watcher,
|
||||
const std::string& local_mirror_uuid,
|
||||
const std::string& local_mirror_peer_uuid,
|
||||
PoolMetaCache* pool_meta_cache,
|
||||
StateBuilder<I>* state_builder,
|
||||
ReplayerListener* replayer_listener)
|
||||
: m_threads(threads),
|
||||
m_instance_watcher(instance_watcher),
|
||||
m_local_mirror_uuid(local_mirror_uuid),
|
||||
m_local_mirror_peer_uuid(local_mirror_peer_uuid),
|
||||
m_pool_meta_cache(pool_meta_cache),
|
||||
m_state_builder(state_builder),
|
||||
m_replayer_listener(replayer_listener),
|
||||
@ -171,7 +173,9 @@ void Replayer<I>::init(Context* on_finish) {
|
||||
}
|
||||
|
||||
m_remote_mirror_peer_uuid = remote_pool_meta.mirror_peer_uuid;
|
||||
dout(10) << "remote_mirror_peer_uuid=" << m_remote_mirror_peer_uuid << dendl;
|
||||
dout(10) << "local_mirror_peer_uuid=" << m_local_mirror_peer_uuid
|
||||
<< ", remote_mirror_peer_uuid=" << m_remote_mirror_peer_uuid
|
||||
<< dendl;
|
||||
|
||||
{
|
||||
auto local_image_ctx = m_state_builder->local_image_ctx;
|
||||
@ -539,6 +543,18 @@ void Replayer<I>::scan_local_mirror_snapshots(
|
||||
}
|
||||
} else if (mirror_ns->is_primary()) {
|
||||
if (mirror_ns->complete) {
|
||||
const auto& peer_uuids = mirror_ns->mirror_peer_uuids;
|
||||
if (peer_uuids.empty() ||
|
||||
(mirror_ns->state == cls::rbd::MIRROR_SNAPSHOT_STATE_PRIMARY_DEMOTED &&
|
||||
peer_uuids.size() == 1 &&
|
||||
peer_uuids.count(m_local_mirror_peer_uuid) == 1)) {
|
||||
// After relocation, the primary snapshots on the new secondary become
|
||||
// obsolete snapshots. They can be pruned if they are already unlinked.
|
||||
// Additionally, in this case, a demoted primary snapshot that is linked
|
||||
// to only a single remote (current primary) peer is safe to prune,
|
||||
// because no other peer depends on it waiting for sync.
|
||||
prune_snap_ids.insert(local_snap_id);
|
||||
}
|
||||
m_local_snap_id_start = local_snap_id;
|
||||
ceph_assert(m_local_snap_id_end == CEPH_NOSNAP);
|
||||
} else {
|
||||
@ -564,8 +580,8 @@ void Replayer<I>::scan_local_mirror_snapshots(
|
||||
locker->unlock();
|
||||
|
||||
auto prune_snap_id = *prune_snap_ids.begin();
|
||||
dout(5) << "pruning unused non-primary snapshot " << prune_snap_id << dendl;
|
||||
prune_non_primary_snapshot(prune_snap_id);
|
||||
dout(5) << "pruning unused mirror snapshot " << prune_snap_id << dendl;
|
||||
prune_mirror_snapshot(prune_snap_id);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -798,7 +814,7 @@ void Replayer<I>::scan_remote_mirror_snapshots(
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
void Replayer<I>::prune_non_primary_snapshot(uint64_t snap_id) {
|
||||
void Replayer<I>::prune_mirror_snapshot(uint64_t snap_id) {
|
||||
dout(10) << "snap_id=" << snap_id << dendl;
|
||||
|
||||
auto local_image_ctx = m_state_builder->local_image_ctx;
|
||||
@ -825,18 +841,18 @@ void Replayer<I>::prune_non_primary_snapshot(uint64_t snap_id) {
|
||||
}
|
||||
|
||||
auto ctx = create_context_callback<
|
||||
Replayer<I>, &Replayer<I>::handle_prune_non_primary_snapshot>(this);
|
||||
Replayer<I>, &Replayer<I>::handle_prune_mirror_snapshot>(this);
|
||||
local_image_ctx->operations->snap_remove(snap_namespace, snap_name, ctx);
|
||||
}
|
||||
|
||||
template <typename I>
|
||||
void Replayer<I>::handle_prune_non_primary_snapshot(int r) {
|
||||
void Replayer<I>::handle_prune_mirror_snapshot(int r) {
|
||||
dout(10) << "r=" << r << dendl;
|
||||
|
||||
if (r < 0 && r != -ENOENT) {
|
||||
derr << "failed to prune non-primary snapshot: " << cpp_strerror(r)
|
||||
derr << "failed to prune mirror snapshot: " << cpp_strerror(r)
|
||||
<< dendl;
|
||||
handle_replay_complete(r, "failed to prune non-primary snapshot");
|
||||
handle_replay_complete(r, "failed to prune mirror snapshot");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -47,17 +47,20 @@ public:
|
||||
Threads<ImageCtxT>* threads,
|
||||
InstanceWatcher<ImageCtxT>* instance_watcher,
|
||||
const std::string& local_mirror_uuid,
|
||||
const std::string& local_mirror_peer_uuid,
|
||||
PoolMetaCache* pool_meta_cache,
|
||||
StateBuilder<ImageCtxT>* state_builder,
|
||||
ReplayerListener* replayer_listener) {
|
||||
return new Replayer(threads, instance_watcher, local_mirror_uuid,
|
||||
pool_meta_cache, state_builder, replayer_listener);
|
||||
local_mirror_peer_uuid, pool_meta_cache, state_builder,
|
||||
replayer_listener);
|
||||
}
|
||||
|
||||
Replayer(
|
||||
Threads<ImageCtxT>* threads,
|
||||
InstanceWatcher<ImageCtxT>* instance_watcher,
|
||||
const std::string& local_mirror_uuid,
|
||||
const std::string& local_mirror_peer_uuid,
|
||||
PoolMetaCache* pool_meta_cache,
|
||||
StateBuilder<ImageCtxT>* state_builder,
|
||||
ReplayerListener* replayer_listener);
|
||||
@ -202,6 +205,7 @@ private:
|
||||
Threads<ImageCtxT>* m_threads;
|
||||
InstanceWatcher<ImageCtxT>* m_instance_watcher;
|
||||
std::string m_local_mirror_uuid;
|
||||
std::string m_local_mirror_peer_uuid;
|
||||
PoolMetaCache* m_pool_meta_cache;
|
||||
StateBuilder<ImageCtxT>* m_state_builder;
|
||||
ReplayerListener* m_replayer_listener;
|
||||
@ -271,8 +275,8 @@ private:
|
||||
void scan_local_mirror_snapshots(std::unique_lock<ceph::mutex>* locker);
|
||||
void scan_remote_mirror_snapshots(std::unique_lock<ceph::mutex>* locker);
|
||||
|
||||
void prune_non_primary_snapshot(uint64_t snap_id);
|
||||
void handle_prune_non_primary_snapshot(int r);
|
||||
void prune_mirror_snapshot(uint64_t snap_id);
|
||||
void handle_prune_mirror_snapshot(int r);
|
||||
|
||||
void copy_snapshots();
|
||||
void handle_copy_snapshots(int r);
|
||||
|
||||
@ -105,11 +105,12 @@ image_replayer::Replayer* StateBuilder<I>::create_replayer(
|
||||
Threads<I>* threads,
|
||||
InstanceWatcher<I>* instance_watcher,
|
||||
const std::string& local_mirror_uuid,
|
||||
const std::string& local_mirror_peer_uuid,
|
||||
PoolMetaCache* pool_meta_cache,
|
||||
ReplayerListener* replayer_listener) {
|
||||
return Replayer<I>::create(
|
||||
threads, instance_watcher, local_mirror_uuid, pool_meta_cache, this,
|
||||
replayer_listener);
|
||||
threads, instance_watcher, local_mirror_uuid, local_mirror_peer_uuid,
|
||||
pool_meta_cache, this, replayer_listener);
|
||||
}
|
||||
|
||||
} // namespace snapshot
|
||||
|
||||
@ -70,6 +70,7 @@ public:
|
||||
Threads<ImageCtxT>* threads,
|
||||
InstanceWatcher<ImageCtxT>* instance_watcher,
|
||||
const std::string& local_mirror_uuid,
|
||||
const std::string& local_mirror_peer_uuid,
|
||||
PoolMetaCache* pool_meta_cache,
|
||||
ReplayerListener* replayer_listener) override;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user