rbd-mirror: allow mirroring to a different namespace

Allows a namespace in a pool to be mirrored to a differently named
namespace in the secondary cluster.

Signed-off-by: N Balachandran <nibalach@redhat.com>
This commit is contained in:
N Balachandran 2024-08-23 17:39:16 +05:30
parent a71318b738
commit 3fdbc160bb
27 changed files with 601 additions and 146 deletions

View File

@ -543,8 +543,9 @@ Commands
:command:`mirror pool info` [*pool-name*] :command:`mirror pool info` [*pool-name*]
Show information about the pool or namespace mirroring configuration. Show information about the pool or namespace mirroring configuration.
For a pool, it includes mirroring mode, peer UUID, remote cluster name, For both pools and namespaces, it includes the mirroring mode
and remote client name. For a namespace, it includes only mirroring mode. and remote namespace. For pools, it additionally includes the site name,
peer UUID, mirror UUID, remote cluster name, and remote client name.
:command:`mirror pool peer add` [*pool-name*] *remote-cluster-spec* :command:`mirror pool peer add` [*pool-name*] *remote-cluster-spec*
Add a mirroring peer to a pool. Add a mirroring peer to a pool.
@ -555,7 +556,7 @@ Commands
This requires mirroring to be enabled on the pool. This requires mirroring to be enabled on the pool.
:command:`mirror pool peer remove` [*pool-name*] *uuid* :command:`mirror pool peer remove` [*pool-name*] *uuid*
Remove a mirroring peer from a pool. The peer uuid is available Remove a mirroring peer from a pool. The peer UUID is available
from ``mirror pool info`` command. from ``mirror pool info`` command.
:command:`mirror pool peer set` [*pool-name*] *uuid* *key* *value* :command:`mirror pool peer set` [*pool-name*] *uuid* *key* *value*

View File

@ -37,12 +37,12 @@ set_image_meta ${CLUSTER2} ${POOL} ${image} "key1" "value1"
set_image_meta ${CLUSTER2} ${POOL} ${image} "key2" "value2" set_image_meta ${CLUSTER2} ${POOL} ${image} "key2" "value2"
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
write_image ${CLUSTER2} ${POOL} ${image} 100 write_image ${CLUSTER2} ${POOL} ${image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'down+unknown' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'down+unknown'
fi fi
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
compare_image_meta ${CLUSTER1} ${POOL} ${image} "key1" "value1" compare_image_meta ${CLUSTER1} ${POOL} ${image} "key1" "value1"
compare_image_meta ${CLUSTER1} ${POOL} ${image} "key2" "value2" compare_image_meta ${CLUSTER1} ${POOL} ${image} "key2" "value2"
@ -53,19 +53,19 @@ create_image_and_enable_mirror ${CLUSTER2} ${POOL} ${image1} ${RBD_MIRROR_MODE}
write_image ${CLUSTER2} ${POOL} ${image1} 100 write_image ${CLUSTER2} ${POOL} ${image1} 100
start_mirrors ${CLUSTER1} start_mirrors ${CLUSTER1}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image1} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image1}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image1} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image1}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image1} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image1}
if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image1} 'down+unknown' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image1} 'down+unknown'
fi fi
compare_images ${POOL} ${image1} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image1}
testlog "TEST: test the first image is replaying after restart" testlog "TEST: test the first image is replaying after restart"
write_image ${CLUSTER2} ${POOL} ${image} 100 write_image ${CLUSTER2} ${POOL} ${image} 100
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then
testlog "TEST: stop/start/restart mirror via admin socket" testlog "TEST: stop/start/restart mirror via admin socket"
@ -173,7 +173,7 @@ wait_for_image_in_omap ${CLUSTER2} ${POOL}
create_image_and_enable_mirror ${CLUSTER2} ${POOL} ${image} ${RBD_MIRROR_MODE} create_image_and_enable_mirror ${CLUSTER2} ${POOL} ${image} ${RBD_MIRROR_MODE}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
write_image ${CLUSTER2} ${POOL} ${image} 100 write_image ${CLUSTER2} ${POOL} ${image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying' wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying'
testlog "TEST: failover and failback" testlog "TEST: failover and failback"
@ -187,10 +187,10 @@ wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
promote_image ${CLUSTER2} ${POOL} ${image} promote_image ${CLUSTER2} ${POOL} ${image}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
write_image ${CLUSTER2} ${POOL} ${image} 100 write_image ${CLUSTER2} ${POOL} ${image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped'
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
# failover (unmodified) # failover (unmodified)
demote_image ${CLUSTER2} ${POOL} ${image} demote_image ${CLUSTER2} ${POOL} ${image}
@ -207,10 +207,10 @@ wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+unknown'
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
promote_image ${CLUSTER2} ${POOL} ${image} promote_image ${CLUSTER2} ${POOL} ${image}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped'
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
# failover # failover
demote_image ${CLUSTER2} ${POOL} ${image} demote_image ${CLUSTER2} ${POOL} ${image}
@ -220,10 +220,10 @@ wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
promote_image ${CLUSTER1} ${POOL} ${image} promote_image ${CLUSTER1} ${POOL} ${image}
wait_for_image_replay_started ${CLUSTER2} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER2} ${POOL} ${image}
write_image ${CLUSTER1} ${POOL} ${image} 100 write_image ${CLUSTER1} ${POOL} ${image} 100
wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${POOL} ${image} wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${POOL} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+stopped' wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+stopped'
wait_for_replaying_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER2} ${POOL} ${image}
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
# failback # failback
demote_image ${CLUSTER1} ${POOL} ${image} demote_image ${CLUSTER1} ${POOL} ${image}
@ -233,10 +233,10 @@ wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
promote_image ${CLUSTER2} ${POOL} ${image} promote_image ${CLUSTER2} ${POOL} ${image}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
write_image ${CLUSTER2} ${POOL} ${image} 100 write_image ${CLUSTER2} ${POOL} ${image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped'
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
testlog "TEST: failover / failback loop" testlog "TEST: failover / failback loop"
for i in `seq 1 20`; do for i in `seq 1 20`; do
@ -246,7 +246,7 @@ for i in `seq 1 20`; do
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
promote_image ${CLUSTER1} ${POOL} ${image} promote_image ${CLUSTER1} ${POOL} ${image}
wait_for_image_replay_started ${CLUSTER2} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER2} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${POOL} ${image} wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${POOL} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+stopped' wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+stopped'
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+replaying' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+replaying'
demote_image ${CLUSTER1} ${POOL} ${image} demote_image ${CLUSTER1} ${POOL} ${image}
@ -255,7 +255,7 @@ for i in `seq 1 20`; do
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+unknown'
promote_image ${CLUSTER2} ${POOL} ${image} promote_image ${CLUSTER2} ${POOL} ${image}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} 'up+stopped'
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying' wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying'
done done
@ -271,7 +271,7 @@ create_image_and_enable_mirror ${CLUSTER2} ${POOL} ${force_promote_image} ${RBD_
write_image ${CLUSTER2} ${POOL} ${force_promote_image} 100 write_image ${CLUSTER2} ${POOL} ${force_promote_image} 100
wait_for_image_replay_stopped ${CLUSTER2} ${POOL} ${force_promote_image} wait_for_image_replay_stopped ${CLUSTER2} ${POOL} ${force_promote_image}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${force_promote_image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${force_promote_image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${force_promote_image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${force_promote_image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${force_promote_image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${force_promote_image}
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${force_promote_image} 'up+stopped' wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${force_promote_image} 'up+stopped'
promote_image ${CLUSTER1} ${POOL} ${force_promote_image} '--force' promote_image ${CLUSTER1} ${POOL} ${force_promote_image} '--force'
@ -302,14 +302,14 @@ else
enable_mirror ${CLUSTER2} ${PARENT_POOL} ${parent_image} ${RBD_MIRROR_MODE} enable_mirror ${CLUSTER2} ${PARENT_POOL} ${parent_image} ${RBD_MIRROR_MODE}
fi fi
wait_for_image_replay_started ${CLUSTER1} ${PARENT_POOL} ${parent_image} wait_for_image_replay_started ${CLUSTER1} ${PARENT_POOL} ${parent_image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${PARENT_POOL} ${parent_image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${PARENT_POOL} ${PARENT_POOL} ${parent_image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${PARENT_POOL} ${parent_image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${PARENT_POOL} ${parent_image}
compare_images ${PARENT_POOL} ${parent_image} compare_images ${CLUSTER1} ${CLUSTER2} ${PARENT_POOL} ${PARENT_POOL} ${parent_image}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${clone_image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${clone_image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${clone_image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${clone_image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${clone_image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${clone_image}
compare_images ${POOL} ${clone_image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${clone_image}
remove_image_retry ${CLUSTER2} ${POOL} ${clone_image} remove_image_retry ${CLUSTER2} ${POOL} ${clone_image}
testlog " - clone v1" testlog " - clone v1"
@ -383,11 +383,11 @@ create_snapshot ${CLUSTER2} ${POOL} ${dp_image} 'snap1'
write_image ${CLUSTER2} ${POOL} ${dp_image} 100 write_image ${CLUSTER2} ${POOL} ${dp_image} 100
create_snapshot ${CLUSTER2} ${POOL} ${dp_image} 'snap2' create_snapshot ${CLUSTER2} ${POOL} ${dp_image} 'snap2'
write_image ${CLUSTER2} ${POOL} ${dp_image} 100 write_image ${CLUSTER2} ${POOL} ${dp_image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${dp_image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${dp_image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${dp_image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${dp_image}
compare_images ${POOL} ${dp_image}@snap1 compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${dp_image}@snap1
compare_images ${POOL} ${dp_image}@snap2 compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${dp_image}@snap2
compare_images ${POOL} ${dp_image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${dp_image}
remove_image_retry ${CLUSTER2} ${POOL} ${dp_image} remove_image_retry ${CLUSTER2} ${POOL} ${dp_image}
testlog "TEST: disable mirroring / delete non-primary image" testlog "TEST: disable mirroring / delete non-primary image"
@ -436,8 +436,8 @@ if [ "${RBD_MIRROR_MODE}" = "journal" ]; then
wait_for_image_present ${CLUSTER1} ${POOL} ${i} 'present' wait_for_image_present ${CLUSTER1} ${POOL} ${i} 'present'
wait_for_snap_present ${CLUSTER1} ${POOL} ${i} 'snap2' wait_for_snap_present ${CLUSTER1} ${POOL} ${i} 'snap2'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${i} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${i}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${i} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${i}
compare_images ${POOL} ${i} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${i}
done done
testlog "TEST: remove mirroring pool" testlog "TEST: remove mirroring pool"
@ -454,9 +454,9 @@ if [ "${RBD_MIRROR_MODE}" = "journal" ]; then
create_image ${CLUSTER2} ${POOL} ${rdp_image} 128 --data-pool ${pool} create_image ${CLUSTER2} ${POOL} ${rdp_image} 128 --data-pool ${pool}
write_image ${CLUSTER2} ${pool} ${image} 100 write_image ${CLUSTER2} ${pool} ${image} 100
write_image ${CLUSTER2} ${POOL} ${rdp_image} 100 write_image ${CLUSTER2} ${POOL} ${rdp_image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${pool} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${pool} ${pool} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${pool} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${pool} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${rdp_image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${rdp_image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${rdp_image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${rdp_image}
for cluster in ${CLUSTER1} ${CLUSTER2}; do for cluster in ${CLUSTER1} ${CLUSTER2}; do
CEPH_ARGS='' ceph --cluster ${cluster} osd pool rm ${pool} ${pool} --yes-i-really-really-mean-it CEPH_ARGS='' ceph --cluster ${cluster} osd pool rm ${pool} ${pool} --yes-i-really-really-mean-it
@ -519,12 +519,12 @@ wait_for_image_replay_started ${CLUSTER1} ${POOL}/${NS1} ${image}
wait_for_image_replay_started ${CLUSTER1} ${POOL}/${NS2} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL}/${NS2} ${image}
write_image ${CLUSTER2} ${POOL}/${NS1} ${image} 100 write_image ${CLUSTER2} ${POOL}/${NS1} ${image} 100
write_image ${CLUSTER2} ${POOL}/${NS2} ${image} 100 write_image ${CLUSTER2} ${POOL}/${NS2} ${image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS1} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS1} ${POOL}/${NS1} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS2} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS2} ${POOL}/${NS2} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL}/${NS1} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL}/${NS1} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL}/${NS2} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL}/${NS2} ${image}
compare_images ${POOL}/${NS1} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS1} ${POOL}/${NS1} ${image}
compare_images ${POOL}/${NS2} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS2} ${POOL}/${NS2} ${image}
testlog " - disable mirroring / delete image" testlog " - disable mirroring / delete image"
remove_image_retry ${CLUSTER2} ${POOL}/${NS1} ${image} remove_image_retry ${CLUSTER2} ${POOL}/${NS1} ${image}
@ -533,6 +533,40 @@ wait_for_image_present ${CLUSTER1} ${POOL}/${NS1} ${image} 'deleted'
wait_for_image_present ${CLUSTER1} ${POOL}/${NS2} ${image} 'deleted' wait_for_image_present ${CLUSTER1} ${POOL}/${NS2} ${image} 'deleted'
remove_image_retry ${CLUSTER2} ${POOL}/${NS2} ${image} remove_image_retry ${CLUSTER2} ${POOL}/${NS2} ${image}
testlog "TEST: mirror to a different remote namespace"
testlog " - replay"
NS3=ns3
NS4=ns4
rbd --cluster ${CLUSTER1} namespace create ${POOL}/${NS3}
rbd --cluster ${CLUSTER2} namespace create ${POOL}/${NS4}
rbd --cluster ${CLUSTER1} mirror pool enable ${POOL}/${NS3} ${MIRROR_POOL_MODE} --remote-namespace ${NS4}
rbd --cluster ${CLUSTER2} mirror pool enable ${POOL}/${NS4} ${MIRROR_POOL_MODE} --remote-namespace ${NS3}
create_image_and_enable_mirror ${CLUSTER2} ${POOL}/${NS4} ${image} ${RBD_MIRROR_MODE}
wait_for_image_replay_started ${CLUSTER1} ${POOL}/${NS3} ${image}
write_image ${CLUSTER2} ${POOL}/${NS4} ${image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS3} ${POOL}/${NS4} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL}/${NS3} ${image}
compare_images ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS3} ${POOL}/${NS4} ${image}
testlog " - disable mirroring and re-enable without remote-namespace"
remove_image_retry ${CLUSTER2} ${POOL}/${NS4} ${image}
wait_for_image_present ${CLUSTER1} ${POOL}/${NS3} ${image} 'deleted'
rbd --cluster ${CLUSTER1} mirror pool disable ${POOL}/${NS3}
rbd --cluster ${CLUSTER2} mirror pool disable ${POOL}/${NS4}
rbd --cluster ${CLUSTER2} namespace create ${POOL}/${NS3}
rbd --cluster ${CLUSTER2} mirror pool enable ${POOL}/${NS3} ${MIRROR_POOL_MODE}
rbd --cluster ${CLUSTER1} mirror pool enable ${POOL}/${NS3} ${MIRROR_POOL_MODE}
create_image_and_enable_mirror ${CLUSTER2} ${POOL}/${NS3} ${image} ${RBD_MIRROR_MODE}
wait_for_image_replay_started ${CLUSTER1} ${POOL}/${NS3} ${image}
write_image ${CLUSTER2} ${POOL}/${NS3} ${image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS3} ${POOL}/${NS3} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL}/${NS3} ${image}
compare_images ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS3} ${POOL}/${NS3} ${image}
remove_image_retry ${CLUSTER2} ${POOL}/${NS3} ${image}
wait_for_image_present ${CLUSTER1} ${POOL}/${NS3} ${image} 'deleted'
rbd --cluster ${CLUSTER1} mirror pool disable ${POOL}/${NS3}
rbd --cluster ${CLUSTER2} mirror pool disable ${POOL}/${NS3}
testlog " - data pool" testlog " - data pool"
dp_image=test_data_pool dp_image=test_data_pool
create_image_and_enable_mirror ${CLUSTER2} ${POOL}/${NS1} ${dp_image} ${RBD_MIRROR_MODE} 128 --data-pool ${PARENT_POOL} create_image_and_enable_mirror ${CLUSTER2} ${POOL}/${NS1} ${dp_image} ${RBD_MIRROR_MODE} 128 --data-pool ${PARENT_POOL}
@ -542,9 +576,9 @@ wait_for_image_replay_started ${CLUSTER1} ${POOL}/${NS1} ${dp_image}
data_pool=$(get_image_data_pool ${CLUSTER1} ${POOL}/${NS1} ${dp_image}) data_pool=$(get_image_data_pool ${CLUSTER1} ${POOL}/${NS1} ${dp_image})
test "${data_pool}" = "${PARENT_POOL}" test "${data_pool}" = "${PARENT_POOL}"
write_image ${CLUSTER2} ${POOL}/${NS1} ${dp_image} 100 write_image ${CLUSTER2} ${POOL}/${NS1} ${dp_image} 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS1} ${dp_image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS1} ${POOL}/${NS1} ${dp_image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL}/${NS1} ${dp_image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL}/${NS1} ${dp_image}
compare_images ${POOL}/${NS1} ${dp_image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL}/${NS1} ${POOL}/${NS1} ${dp_image}
remove_image_retry ${CLUSTER2} ${POOL}/${NS1} ${dp_image} remove_image_retry ${CLUSTER2} ${POOL}/${NS1} ${dp_image}
testlog "TEST: simple image resync" testlog "TEST: simple image resync"
@ -553,7 +587,7 @@ wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted' ${image_id}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present' wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then
testlog "TEST: image resync while replayer is stopped" testlog "TEST: image resync while replayer is stopped"
@ -566,7 +600,7 @@ if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present' wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
fi fi
testlog "TEST: request image resync while daemon is offline" testlog "TEST: request image resync while daemon is offline"
@ -577,7 +611,7 @@ wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted' ${image_id}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present' wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${POOL} ${image}
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
remove_image_retry ${CLUSTER2} ${POOL} ${image} remove_image_retry ${CLUSTER2} ${POOL} ${image}
if [ "${RBD_MIRROR_MODE}" = "journal" ]; then if [ "${RBD_MIRROR_MODE}" = "journal" ]; then
@ -588,7 +622,7 @@ if [ "${RBD_MIRROR_MODE}" = "journal" ]; then
testlog " - replay stopped after disconnect" testlog " - replay stopped after disconnect"
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
test -n "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})" test -n "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})"
disconnect_image ${CLUSTER2} ${POOL} ${image} disconnect_image ${CLUSTER2} ${POOL} ${image}
test -z "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})" test -z "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})"
@ -600,9 +634,9 @@ if [ "${RBD_MIRROR_MODE}" = "journal" ]; then
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted' ${image_id} wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted' ${image_id}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present' wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
test -n "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})" test -n "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})"
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
testlog " - disconnected after max_concurrent_object_sets reached" testlog " - disconnected after max_concurrent_object_sets reached"
if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then if [ -z "${RBD_MIRROR_USE_RBD_MIRROR}" ]; then
@ -628,25 +662,25 @@ if [ "${RBD_MIRROR_MODE}" = "journal" ]; then
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted' ${image_id} wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted' ${image_id}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present' wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
test -n "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})" test -n "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})"
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
testlog " - rbd_mirroring_resync_after_disconnect config option" testlog " - rbd_mirroring_resync_after_disconnect config option"
set_image_meta ${CLUSTER2} ${POOL} ${image} \ set_image_meta ${CLUSTER2} ${POOL} ${image} \
conf_rbd_mirroring_resync_after_disconnect true conf_rbd_mirroring_resync_after_disconnect true
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
image_id=$(get_image_id ${CLUSTER1} ${POOL} ${image}) image_id=$(get_image_id ${CLUSTER1} ${POOL} ${image})
disconnect_image ${CLUSTER2} ${POOL} ${image} disconnect_image ${CLUSTER2} ${POOL} ${image}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted' ${image_id} wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'deleted' ${image_id}
wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present' wait_for_image_present ${CLUSTER1} ${POOL} ${image} 'present'
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
test -n "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})" test -n "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})"
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
set_image_meta ${CLUSTER2} ${POOL} ${image} \ set_image_meta ${CLUSTER2} ${POOL} ${image} \
conf_rbd_mirroring_resync_after_disconnect false conf_rbd_mirroring_resync_after_disconnect false
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
disconnect_image ${CLUSTER2} ${POOL} ${image} disconnect_image ${CLUSTER2} ${POOL} ${image}
test -z "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})" test -z "$(get_mirror_journal_position ${CLUSTER2} ${POOL} ${image})"
wait_for_image_replay_stopped ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_stopped ${CLUSTER1} ${POOL} ${image}

View File

@ -38,7 +38,7 @@ create_image_and_enable_mirror ${CLUSTER1} ${POOL} image1
wait_for_image_replay_started ${CLUSTER2} ${POOL} image1 wait_for_image_replay_started ${CLUSTER2} ${POOL} image1
write_image ${CLUSTER1} ${POOL} image1 100 write_image ${CLUSTER1} ${POOL} image1 100
wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${POOL} image1 wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${POOL} ${POOL} image1
wait_for_replaying_status_in_pool_dir ${CLUSTER2} ${POOL} image1 wait_for_replaying_status_in_pool_dir ${CLUSTER2} ${POOL} image1
testlog "TEST: verify rx-tx direction" testlog "TEST: verify rx-tx direction"
@ -54,12 +54,12 @@ enable_mirror ${CLUSTER2} ${PARENT_POOL} image2
wait_for_image_replay_started ${CLUSTER2} ${PARENT_POOL} image1 wait_for_image_replay_started ${CLUSTER2} ${PARENT_POOL} image1
write_image ${CLUSTER1} ${PARENT_POOL} image1 100 write_image ${CLUSTER1} ${PARENT_POOL} image1 100
wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${PARENT_POOL} image1 wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${PARENT_POOL} ${PARENT_POOL} image1
wait_for_replaying_status_in_pool_dir ${CLUSTER2} ${PARENT_POOL} image1 wait_for_replaying_status_in_pool_dir ${CLUSTER2} ${PARENT_POOL} image1
wait_for_image_replay_started ${CLUSTER1} ${PARENT_POOL} image2 wait_for_image_replay_started ${CLUSTER1} ${PARENT_POOL} image2
write_image ${CLUSTER2} ${PARENT_POOL} image2 100 write_image ${CLUSTER2} ${PARENT_POOL} image2 100
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${PARENT_POOL} image2 wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${PARENT_POOL} ${PARENT_POOL} image2
wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${PARENT_POOL} image2 wait_for_replaying_status_in_pool_dir ${CLUSTER1} ${PARENT_POOL} image2
testlog "TEST: pool replayer and callout cleanup when peer is updated" testlog "TEST: pool replayer and callout cleanup when peer is updated"

View File

@ -71,7 +71,7 @@ test_replay()
wait_for_image_replay_started ${CLUSTER1}:${LEADER} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1}:${LEADER} ${POOL} ${image}
write_image ${CLUSTER2} ${POOL} ${image} 100 write_image ${CLUSTER2} ${POOL} ${image} 100
wait_for_replay_complete ${CLUSTER1}:${LEADER} ${CLUSTER2} ${POOL} \ wait_for_replay_complete ${CLUSTER1}:${LEADER} ${CLUSTER2} ${POOL} \
${image} ${POOL} ${image}
wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying' \ wait_for_status_in_pool_dir ${CLUSTER1} ${POOL} ${image} 'up+replaying' \
'primary_position' \ 'primary_position' \
"${MIRROR_USER_ID_PREFIX}${LEADER} on $(hostname -s)" "${MIRROR_USER_ID_PREFIX}${LEADER} on $(hostname -s)"
@ -79,7 +79,7 @@ test_replay()
wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} \ wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} ${image} \
'down+unknown' 'down+unknown'
fi fi
compare_images ${POOL} ${image} compare_images ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
done done
} }

View File

@ -743,17 +743,18 @@ wait_for_journal_replay_complete()
{ {
local local_cluster=$1 local local_cluster=$1
local cluster=$2 local cluster=$2
local pool=$3 local local_pool=$3
local image=$4 local remote_pool=$4
local image=$5
local s master_pos mirror_pos last_mirror_pos local s master_pos mirror_pos last_mirror_pos
local master_tag master_entry mirror_tag mirror_entry local master_tag master_entry mirror_tag mirror_entry
while true; do while true; do
for s in 0.2 0.4 0.8 1.6 2 2 4 4 8 8 16 16 32 32; do for s in 0.2 0.4 0.8 1.6 2 2 4 4 8 8 16 16 32 32; do
sleep ${s} sleep ${s}
flush "${local_cluster}" "${pool}" "${image}" flush "${local_cluster}" "${local_pool}" "${image}"
master_pos=$(get_master_journal_position "${cluster}" "${pool}" "${image}") master_pos=$(get_master_journal_position "${cluster}" "${remote_pool}" "${image}")
mirror_pos=$(get_mirror_journal_position "${cluster}" "${pool}" "${image}") mirror_pos=$(get_mirror_journal_position "${cluster}" "${remote_pool}" "${image}")
test -n "${master_pos}" -a "${master_pos}" = "${mirror_pos}" && return 0 test -n "${master_pos}" -a "${master_pos}" = "${mirror_pos}" && return 0
test "${mirror_pos}" != "${last_mirror_pos}" && break test "${mirror_pos}" != "${last_mirror_pos}" && break
done done
@ -796,21 +797,22 @@ wait_for_snapshot_sync_complete()
{ {
local local_cluster=$1 local local_cluster=$1
local cluster=$2 local cluster=$2
local pool=$3 local local_pool=$3
local image=$4 local remote_pool=$4
local image=$5
local status_log=${TEMPDIR}/$(mkfname ${cluster}-${pool}-${image}.status) local status_log=${TEMPDIR}/$(mkfname ${cluster}-${remote_pool}-${image}.status)
local local_status_log=${TEMPDIR}/$(mkfname ${local_cluster}-${pool}-${image}.status) local local_status_log=${TEMPDIR}/$(mkfname ${local_cluster}-${local_pool}-${image}.status)
mirror_image_snapshot "${cluster}" "${pool}" "${image}" mirror_image_snapshot "${cluster}" "${remote_pool}" "${image}"
get_newest_mirror_snapshot "${cluster}" "${pool}" "${image}" "${status_log}" get_newest_mirror_snapshot "${cluster}" "${remote_pool}" "${image}" "${status_log}"
local snapshot_id=$(xmlstarlet sel -t -v "//snapshot/id" < ${status_log}) local snapshot_id=$(xmlstarlet sel -t -v "//snapshot/id" < ${status_log})
while true; do while true; do
for s in 0.2 0.4 0.8 1.6 2 2 4 4 8 8 16 16 32 32; do for s in 0.2 0.4 0.8 1.6 2 2 4 4 8 8 16 16 32 32; do
sleep ${s} sleep ${s}
get_newest_mirror_snapshot "${local_cluster}" "${pool}" "${image}" "${local_status_log}" get_newest_mirror_snapshot "${local_cluster}" "${local_pool}" "${image}" "${local_status_log}"
local primary_snapshot_id=$(xmlstarlet sel -t -v "//snapshot/namespace/primary_snap_id" < ${local_status_log}) local primary_snapshot_id=$(xmlstarlet sel -t -v "//snapshot/namespace/primary_snap_id" < ${local_status_log})
test "${snapshot_id}" = "${primary_snapshot_id}" && return 0 test "${snapshot_id}" = "${primary_snapshot_id}" && return 0
@ -825,13 +827,14 @@ wait_for_replay_complete()
{ {
local local_cluster=$1 local local_cluster=$1
local cluster=$2 local cluster=$2
local pool=$3 local local_pool=$3
local image=$4 local remote_pool=$4
local image=$5
if [ "${RBD_MIRROR_MODE}" = "journal" ]; then if [ "${RBD_MIRROR_MODE}" = "journal" ]; then
wait_for_journal_replay_complete ${local_cluster} ${cluster} ${pool} ${image} wait_for_journal_replay_complete ${local_cluster} ${cluster} ${local_pool} ${remote_pool} ${image}
elif [ "${RBD_MIRROR_MODE}" = "snapshot" ]; then elif [ "${RBD_MIRROR_MODE}" = "snapshot" ]; then
wait_for_snapshot_sync_complete ${local_cluster} ${cluster} ${pool} ${image} wait_for_snapshot_sync_complete ${local_cluster} ${cluster} ${local_pool} ${remote_pool} ${image}
else else
return 1 return 1
fi fi
@ -1298,16 +1301,19 @@ show_diff()
compare_images() compare_images()
{ {
local pool=$1
local image=$2
local ret=0 local ret=0
local local_cluster=$1
local cluster=$2
local local_pool=$3
local remote_pool=$4
local image=$5
local rmt_export=${TEMPDIR}/$(mkfname ${CLUSTER2}-${pool}-${image}.export) local rmt_export=${TEMPDIR}/$(mkfname ${cluster}-${remote_pool}-${image}.export)
local loc_export=${TEMPDIR}/$(mkfname ${CLUSTER1}-${pool}-${image}.export) local loc_export=${TEMPDIR}/$(mkfname ${local_cluster}-${local_pool}-${image}.export)
rm -f ${rmt_export} ${loc_export} rm -f ${rmt_export} ${loc_export}
rbd --cluster ${CLUSTER2} export ${pool}/${image} ${rmt_export} rbd --cluster ${cluster} export ${remote_pool}/${image} ${rmt_export}
rbd --cluster ${CLUSTER1} export ${pool}/${image} ${loc_export} rbd --cluster ${local_cluster} export ${local_pool}/${image} ${loc_export}
if ! cmp ${rmt_export} ${loc_export} if ! cmp ${rmt_export} ${loc_export}
then then
show_diff ${rmt_export} ${loc_export} show_diff ${rmt_export} ${loc_export}

View File

@ -111,7 +111,7 @@ do
snap_name="snap${i}" snap_name="snap${i}"
create_snap ${CLUSTER2} ${POOL} ${image} ${snap_name} create_snap ${CLUSTER2} ${POOL} ${image} ${snap_name}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_snap_present ${CLUSTER1} ${POOL} ${image} ${snap_name} wait_for_snap_present ${CLUSTER1} ${POOL} ${image} ${snap_name}
if [ -n "${clean_snap_name}" ]; then if [ -n "${clean_snap_name}" ]; then
@ -124,7 +124,7 @@ do
done done
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_snap_present ${CLUSTER1} ${POOL} ${image} ${clean_snap_name} wait_for_snap_present ${CLUSTER1} ${POOL} ${image} ${clean_snap_name}
for i in `seq 1 10` for i in `seq 1 10`
@ -173,7 +173,7 @@ do
image="image_${i}" image="image_${i}"
create_snap ${CLUSTER2} ${POOL} ${image} ${snap_name} create_snap ${CLUSTER2} ${POOL} ${image} ${snap_name}
wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image} wait_for_image_replay_started ${CLUSTER1} ${POOL} ${image}
wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${image} wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${POOL} ${POOL} ${image}
wait_for_snap_present ${CLUSTER1} ${POOL} ${image} ${snap_name} wait_for_snap_present ${CLUSTER1} ${POOL} ${image} ${snap_name}
compare_image_snaps ${POOL} ${image} ${snap_name} compare_image_snaps ${POOL} ${image} ${snap_name}
done done

View File

@ -4624,6 +4624,7 @@ static const std::string STATUS_GLOBAL_KEY_PREFIX("status_global_");
static const std::string REMOTE_STATUS_GLOBAL_KEY_PREFIX("remote_status_global_"); static const std::string REMOTE_STATUS_GLOBAL_KEY_PREFIX("remote_status_global_");
static const std::string INSTANCE_KEY_PREFIX("instance_"); static const std::string INSTANCE_KEY_PREFIX("instance_");
static const std::string MIRROR_IMAGE_MAP_KEY_PREFIX("image_map_"); static const std::string MIRROR_IMAGE_MAP_KEY_PREFIX("image_map_");
static const std::string REMOTE_NAMESPACE("remote_namespace");
std::string peer_key(const std::string &uuid) { std::string peer_key(const std::string &uuid) {
return PEER_KEY_PREFIX + uuid; return PEER_KEY_PREFIX + uuid;
@ -5920,6 +5921,56 @@ int mirror_mode_set(cls_method_context_t hctx, bufferlist *in,
if (r < 0) { if (r < 0) {
return r; return r;
} }
r = remove_key(hctx, mirror::REMOTE_NAMESPACE);
if (r < 0) {
return r;
}
}
return 0;
}
int mirror_remote_namespace_get(cls_method_context_t hctx, bufferlist *in,
bufferlist *out) {
std::string mirror_ns_decode;
int r = read_key(hctx, mirror::REMOTE_NAMESPACE, &mirror_ns_decode);
if (r < 0) {
CLS_ERR("error getting mirror remote namespace: %s",
cpp_strerror(r).c_str());
return r;
}
encode(mirror_ns_decode, *out);
return 0;
}
int mirror_remote_namespace_set(cls_method_context_t hctx, bufferlist *in,
bufferlist *out) {
std::string mirror_namespace;
try {
auto bl_it = in->cbegin();
decode(mirror_namespace, bl_it);
} catch (const ceph::buffer::error &err) {
return -EINVAL;
}
uint32_t mirror_mode;
int r = read_key(hctx, mirror::MODE, &mirror_mode);
if (r < 0 && r != -ENOENT) {
return r;
} else if (r == 0 && mirror_mode != cls::rbd::MIRROR_MODE_DISABLED) {
CLS_ERR("cannot set mirror remote namespace while mirroring enabled");
return -EINVAL;
}
bufferlist bl;
encode(mirror_namespace, bl);
r = cls_cxx_map_set_val(hctx, mirror::REMOTE_NAMESPACE, &bl);
if (r < 0) {
CLS_ERR("error setting mirror remote namespace: %s",
cpp_strerror(r).c_str());
return r;
} }
return 0; return 0;
} }
@ -8278,6 +8329,8 @@ CLS_INIT(rbd)
cls_method_handle_t h_mirror_uuid_set; cls_method_handle_t h_mirror_uuid_set;
cls_method_handle_t h_mirror_mode_get; cls_method_handle_t h_mirror_mode_get;
cls_method_handle_t h_mirror_mode_set; cls_method_handle_t h_mirror_mode_set;
cls_method_handle_t h_mirror_remote_namespace_get;
cls_method_handle_t h_mirror_remote_namespace_set;
cls_method_handle_t h_mirror_peer_ping; cls_method_handle_t h_mirror_peer_ping;
cls_method_handle_t h_mirror_peer_list; cls_method_handle_t h_mirror_peer_list;
cls_method_handle_t h_mirror_peer_add; cls_method_handle_t h_mirror_peer_add;
@ -8575,6 +8628,13 @@ CLS_INIT(rbd)
cls_register_cxx_method(h_class, "mirror_mode_set", cls_register_cxx_method(h_class, "mirror_mode_set",
CLS_METHOD_RD | CLS_METHOD_WR, CLS_METHOD_RD | CLS_METHOD_WR,
mirror_mode_set, &h_mirror_mode_set); mirror_mode_set, &h_mirror_mode_set);
cls_register_cxx_method(h_class, "mirror_remote_namespace_get",
CLS_METHOD_RD, mirror_remote_namespace_get,
&h_mirror_remote_namespace_get);
cls_register_cxx_method(h_class, "mirror_remote_namespace_set",
CLS_METHOD_RD | CLS_METHOD_WR,
mirror_remote_namespace_set,
&h_mirror_remote_namespace_set);
cls_register_cxx_method(h_class, "mirror_peer_ping", cls_register_cxx_method(h_class, "mirror_peer_ping",
CLS_METHOD_RD | CLS_METHOD_WR, CLS_METHOD_RD | CLS_METHOD_WR,
mirror_peer_ping, &h_mirror_peer_ping); mirror_peer_ping, &h_mirror_peer_ping);

View File

@ -1882,6 +1882,40 @@ int mirror_mode_set(librados::IoCtx *ioctx,
return 0; return 0;
} }
int mirror_remote_namespace_get(librados::IoCtx *ioctx,
std::string *mirror_namespace) {
bufferlist in_bl;
bufferlist out_bl;
int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_remote_namespace_get",
in_bl, out_bl);
if (r < 0) {
return r;
}
auto it = out_bl.cbegin();
try {
decode(*mirror_namespace, it);
} catch (const ceph::buffer::error &err) {
return -EBADMSG;
}
return 0;
}
int mirror_remote_namespace_set(librados::IoCtx *ioctx,
const std::string &mirror_namespace) {
bufferlist in_bl;
encode(mirror_namespace, in_bl);
bufferlist out_bl;
int r = ioctx->exec(RBD_MIRRORING, "rbd", "mirror_remote_namespace_set",
in_bl, out_bl);
if (r < 0) {
return r;
}
return 0;
}
void mirror_peer_list_start(librados::ObjectReadOperation *op) { void mirror_peer_list_start(librados::ObjectReadOperation *op) {
bufferlist bl; bufferlist bl;
op->exec("rbd", "mirror_peer_list", bl); op->exec("rbd", "mirror_peer_list", bl);

View File

@ -389,6 +389,11 @@ int mirror_mode_get(librados::IoCtx *ioctx,
int mirror_mode_set(librados::IoCtx *ioctx, int mirror_mode_set(librados::IoCtx *ioctx,
cls::rbd::MirrorMode mirror_mode); cls::rbd::MirrorMode mirror_mode);
int mirror_remote_namespace_get(librados::IoCtx *ioctx,
std::string *mirror_namespace);
int mirror_remote_namespace_set(librados::IoCtx *ioctx,
const std::string &mirror_namespace);
int mirror_peer_ping(librados::IoCtx *ioctx, int mirror_peer_ping(librados::IoCtx *ioctx,
const std::string& site_name, const std::string& site_name,
const std::string& fsid); const std::string& fsid);

View File

@ -577,6 +577,16 @@ CEPH_RBD_API int rbd_mirror_mode_get(rados_ioctx_t io_ctx,
rbd_mirror_mode_t *mirror_mode); rbd_mirror_mode_t *mirror_mode);
CEPH_RBD_API int rbd_mirror_mode_set(rados_ioctx_t io_ctx, CEPH_RBD_API int rbd_mirror_mode_set(rados_ioctx_t io_ctx,
rbd_mirror_mode_t mirror_mode); rbd_mirror_mode_t mirror_mode);
CEPH_RBD_API int rbd_mirror_remote_namespace_get(rados_ioctx_t io_ctx,
char *remote_namespace,
size_t *max_len);
/**
* The value can be set only if mirroring on io_ctx is disabled. The previously
* set value will be automatically reset to io_ctx's namespace when mirroring on
* io_ctx is disabled.
*/
CEPH_RBD_API int rbd_mirror_remote_namespace_set(rados_ioctx_t io_ctx,
const char *remote_namespace);
CEPH_RBD_API int rbd_mirror_uuid_get(rados_ioctx_t io_ctx, CEPH_RBD_API int rbd_mirror_uuid_get(rados_ioctx_t io_ctx,
char *uuid, size_t *max_len); char *uuid, size_t *max_len);

View File

@ -357,6 +357,16 @@ public:
int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode); int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode);
int mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode); int mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode);
int mirror_remote_namespace_get(IoCtx& io_ctx,
std::string* remote_namespace);
/**
* The value can be set only if mirroring on io_ctx is disabled. The
* previously set value will be automatically reset to io_ctx's namespace when
* mirroring on io_ctx is disabled.
*/
int mirror_remote_namespace_set(IoCtx& io_ctx,
const std::string& remote_namespace);
int mirror_uuid_get(IoCtx& io_ctx, std::string* mirror_uuid); int mirror_uuid_get(IoCtx& io_ctx, std::string* mirror_uuid);
int mirror_peer_bootstrap_create(IoCtx& io_ctx, std::string* token); int mirror_peer_bootstrap_create(IoCtx& io_ctx, std::string* token);

View File

@ -1115,9 +1115,8 @@ int Mirror<I>::mode_set(librados::IoCtx& io_ctx,
<< dendl; << dendl;
return r; return r;
} }
if (current_mirror_mode == next_mirror_mode) { if (current_mirror_mode == next_mirror_mode) {
return 0; return 0; // Nothing more to be done
} else if (current_mirror_mode == cls::rbd::MIRROR_MODE_DISABLED) { } else if (current_mirror_mode == cls::rbd::MIRROR_MODE_DISABLED) {
uuid_d uuid_gen; uuid_d uuid_gen;
uuid_gen.generate_random(); uuid_gen.generate_random();
@ -1271,6 +1270,55 @@ int Mirror<I>::mode_set(librados::IoCtx& io_ctx,
return 0; return 0;
} }
template <typename I>
int Mirror<I>::remote_namespace_get(librados::IoCtx& io_ctx,
std::string* remote_namespace) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
ldout(cct, 20) << dendl;
int r = cls_client::mirror_remote_namespace_get(&io_ctx, remote_namespace);
if (r < 0) {
if (r != -ENOENT && r != -EOPNOTSUPP) {
lderr(cct) << "failed to retrieve remote mirror namespace: "
<< cpp_strerror(r) << dendl;
return r;
}
*remote_namespace = io_ctx.get_namespace();
}
return 0;
}
template <typename I>
int Mirror<I>::remote_namespace_set(librados::IoCtx& io_ctx,
const std::string& remote_namespace) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
ldout(cct, 20) << dendl;
std::string local_namespace = io_ctx.get_namespace();
if (local_namespace.empty() && !remote_namespace.empty()) {
lderr(cct) << "cannot mirror the default namespace to a "
<< "non-default namespace." << dendl;
return -EINVAL;
}
if (!local_namespace.empty() && remote_namespace.empty()) {
lderr(cct) << "cannot mirror a non-default namespace to the default "
<< "namespace." << dendl;
return -EINVAL;
}
int r = cls_client::mirror_remote_namespace_set(&io_ctx, remote_namespace);
if (r < 0) {
lderr(cct) << "failed to set remote mirror namespace: "
<< cpp_strerror(r) << dendl;
return r;
}
return 0;
}
template <typename I> template <typename I>
int Mirror<I>::uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid) { int Mirror<I>::uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid) {
CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct()); CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());

View File

@ -31,6 +31,11 @@ struct Mirror {
static int mode_get(librados::IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode); static int mode_get(librados::IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode);
static int mode_set(librados::IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode); static int mode_set(librados::IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode);
static int remote_namespace_get(librados::IoCtx& io_ctx,
std::string* remote_namespace);
static int remote_namespace_set(librados::IoCtx& io_ctx,
const std::string& remote_namespace);
static int uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid); static int uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid);
static void uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid, static void uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid,
Context* on_finish); Context* on_finish);

View File

@ -1101,6 +1101,18 @@ namespace librbd {
return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode); return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
} }
int RBD::mirror_remote_namespace_get(IoCtx& io_ctx,
std::string* remote_namespace) {
return librbd::api::Mirror<>::remote_namespace_get(io_ctx,
remote_namespace);
}
int RBD::mirror_remote_namespace_set(IoCtx& io_ctx,
const std::string& remote_namespace) {
return librbd::api::Mirror<>::remote_namespace_set(io_ctx,
remote_namespace);
}
int RBD::mirror_uuid_get(IoCtx& io_ctx, std::string* mirror_uuid) { int RBD::mirror_uuid_get(IoCtx& io_ctx, std::string* mirror_uuid) {
return librbd::api::Mirror<>::uuid_get(io_ctx, mirror_uuid); return librbd::api::Mirror<>::uuid_get(io_ctx, mirror_uuid);
} }
@ -3395,6 +3407,37 @@ extern "C" int rbd_mirror_mode_set(rados_ioctx_t p,
return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode); return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode);
} }
extern "C" int rbd_mirror_remote_namespace_get(rados_ioctx_t p,
char *remote_namespace,
size_t *max_len) {
librados::IoCtx io_ctx;
librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
std::string remote_namespace_str;
int r = librbd::api::Mirror<>::remote_namespace_get(io_ctx,
&remote_namespace_str);
if (r < 0) {
return r;
}
auto total_len = remote_namespace_str.size() + 1;
if (*max_len < total_len) {
*max_len = total_len;
return -ERANGE;
}
*max_len = total_len;
strcpy(remote_namespace, remote_namespace_str.c_str());
return 0;
}
extern "C" int rbd_mirror_remote_namespace_set(rados_ioctx_t p,
const char *remote_namespace) {
librados::IoCtx io_ctx;
librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
return librbd::api::Mirror<>::remote_namespace_set(io_ctx, remote_namespace);
}
extern "C" int rbd_mirror_uuid_get(rados_ioctx_t p, extern "C" int rbd_mirror_uuid_get(rados_ioctx_t p,
char *mirror_uuid, size_t *max_len) { char *mirror_uuid, size_t *max_len) {
librados::IoCtx io_ctx; librados::IoCtx io_ctx;

View File

@ -394,6 +394,12 @@ cdef extern from "rbd/librbd.h" nogil:
int rbd_mirror_mode_get(rados_ioctx_t io, rbd_mirror_mode_t *mirror_mode) int rbd_mirror_mode_get(rados_ioctx_t io, rbd_mirror_mode_t *mirror_mode)
int rbd_mirror_mode_set(rados_ioctx_t io, rbd_mirror_mode_t mirror_mode) int rbd_mirror_mode_set(rados_ioctx_t io, rbd_mirror_mode_t mirror_mode)
int rbd_mirror_remote_namespace_get(rados_ioctx_t io_ctx,
char *remote_namespace,
size_t *max_len)
int rbd_mirror_remote_namespace_set(rados_ioctx_t io_ctx,
const char *remote_namespace)
int rbd_mirror_uuid_get(rados_ioctx_t io_ctx, char *mirror_uuid, int rbd_mirror_uuid_get(rados_ioctx_t io_ctx, char *mirror_uuid,
size_t *max_len) size_t *max_len)

View File

@ -437,6 +437,14 @@ cdef nogil:
int rbd_mirror_mode_set(rados_ioctx_t io, rbd_mirror_mode_t mirror_mode): int rbd_mirror_mode_set(rados_ioctx_t io, rbd_mirror_mode_t mirror_mode):
pass pass
int rbd_mirror_remote_namespace_get(rados_ioctx_t io_ctx,
char *remote_namespace,
size_t *max_len):
pass
int rbd_mirror_remote_namespace_set(rados_ioctx_t io_ctx,
const char *remote_namespace):
pass
int rbd_mirror_uuid_get(rados_ioctx_t io_ctx, char *mirror_uuid, int rbd_mirror_uuid_get(rados_ioctx_t io_ctx, char *mirror_uuid,
size_t *max_len): size_t *max_len):
pass pass

View File

@ -1330,6 +1330,52 @@ class RBD(object):
if ret != 0: if ret != 0:
raise make_ex(ret, 'error setting mirror mode') raise make_ex(ret, 'error setting mirror mode')
def mirror_remote_namespace_get(self, ioctx):
"""
Get mirror remote namespace
:param ioctx: determines which RADOS pool is read
:type ioctx: :class:`rados.Ioctx`
:returns: str - mirror remote namespace
"""
cdef:
rados_ioctx_t _ioctx = convert_ioctx(ioctx)
char *_remote_namespace = NULL
size_t _max_size = 512
try:
while True:
_remote_namespace = <char *>realloc_chk(_remote_namespace,
_max_size)
with nogil:
ret = rbd_mirror_remote_namespace_get(_ioctx,
_remote_namespace,
&_max_size)
if ret >= 0:
break
elif ret != -errno.ERANGE:
raise make_ex(ret, 'error retrieving remote namespace')
return decode_cstr(_remote_namespace)
finally:
free(_remote_namespace)
def mirror_remote_namespace_set(self, ioctx, remote_namespace):
"""
Set mirror remote namespace
:param ioctx: determines which RADOS pool is written
:type ioctx: :class:`rados.Ioctx`
:param remote_namespace: the remote cluster namespace to mirror to
:type str:
"""
remote_namespace = cstr(remote_namespace, 'remote_namespace')
cdef:
rados_ioctx_t _ioctx = convert_ioctx(ioctx)
char *_remote_namespace = remote_namespace
with nogil:
ret = rbd_mirror_remote_namespace_set(_ioctx, _remote_namespace)
if ret != 0:
raise make_ex(ret, 'error setting remote namespace')
def mirror_uuid_get(self, ioctx): def mirror_uuid_get(self, ioctx):
""" """
Get pool mirror uuid Get pool mirror uuid

View File

@ -1832,19 +1832,21 @@
rbd help mirror pool enable rbd help mirror pool enable
usage: rbd mirror pool enable [--pool <pool>] [--namespace <namespace>] usage: rbd mirror pool enable [--pool <pool>] [--namespace <namespace>]
[--site-name <site-name>] [--site-name <site-name>]
[--remote-namespace <remote-namespace>]
<pool-spec> <mode> <pool-spec> <mode>
Enable RBD mirroring in a pool or namespace. Enable RBD mirroring in a pool or namespace.
Positional arguments Positional arguments
<pool-spec> pool specification <pool-spec> pool specification
(example: <pool-name>[/<namespace>] (example: <pool-name>[/<namespace>]
<mode> mirror mode [image or pool] <mode> mirror mode [image or pool]
Optional arguments Optional arguments
-p [ --pool ] arg pool name -p [ --pool ] arg pool name
--namespace arg namespace name --namespace arg namespace name
--site-name arg local site name --site-name arg local site name
--remote-namespace arg remote namespace name
rbd help mirror pool info rbd help mirror pool info
usage: rbd mirror pool info [--pool <pool>] [--namespace <namespace>] usage: rbd mirror pool info [--pool <pool>] [--namespace <namespace>]
@ -2712,3 +2714,4 @@
--image arg image name --image arg image name

View File

@ -1606,7 +1606,9 @@ TEST_F(TestClsRbd, mirror) {
ASSERT_EQ(-ENOENT, mirror_peer_list(&ioctx, &peers)); ASSERT_EQ(-ENOENT, mirror_peer_list(&ioctx, &peers));
std::string uuid; std::string uuid;
std::string remote_ns;
ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid)); ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid));
ASSERT_EQ(-ENOENT, mirror_remote_namespace_get(&ioctx, &remote_ns));
ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, {"uuid1", MIRROR_PEER_DIRECTION_RX, ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, {"uuid1", MIRROR_PEER_DIRECTION_RX,
"siteA", "client", "siteA", "client",
"mirror uuid"})); "mirror uuid"}));
@ -1622,11 +1624,16 @@ TEST_F(TestClsRbd, mirror) {
ASSERT_EQ(0, mirror_uuid_get(&ioctx, &uuid)); ASSERT_EQ(0, mirror_uuid_get(&ioctx, &uuid));
ASSERT_EQ("mirror-uuid", uuid); ASSERT_EQ("mirror-uuid", uuid);
ASSERT_EQ(0, mirror_remote_namespace_set(&ioctx, "remote-ns"));
ASSERT_EQ(0, mirror_remote_namespace_get(&ioctx, &remote_ns));
ASSERT_EQ("remote-ns", remote_ns);
ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_IMAGE)); ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_IMAGE));
ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode)); ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
ASSERT_EQ(cls::rbd::MIRROR_MODE_IMAGE, mirror_mode); ASSERT_EQ(cls::rbd::MIRROR_MODE_IMAGE, mirror_mode);
ASSERT_EQ(-EINVAL, mirror_uuid_set(&ioctx, "new-mirror-uuid")); ASSERT_EQ(-EINVAL, mirror_uuid_set(&ioctx, "new-mirror-uuid"));
ASSERT_EQ(-EINVAL, mirror_remote_namespace_set(&ioctx, "new-remote-ns"));
ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_POOL)); ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_POOL));
ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode)); ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
@ -1726,6 +1733,7 @@ TEST_F(TestClsRbd, mirror) {
ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode)); ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED, mirror_mode); ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED, mirror_mode);
ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid)); ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid));
ASSERT_EQ(-ENOENT, mirror_remote_namespace_get(&ioctx, &remote_ns));
} }
TEST_F(TestClsRbd, mirror_image) { TEST_F(TestClsRbd, mirror_image) {

View File

@ -2391,6 +2391,27 @@ class TestMirroring(object):
self.rbd.mirror_site_name_set(rados, "") self.rbd.mirror_site_name_set(rados, "")
eq(rados.get_fsid(), self.rbd.mirror_site_name_get(rados)) eq(rados.get_fsid(), self.rbd.mirror_site_name_get(rados))
def test_mirror_remote_namespace(self):
remote_namespace = "remote-ns"
# cannot set remote namespace for the default namespace
assert_raises(InvalidArgument, self.rbd.mirror_remote_namespace_set,
ioctx, remote_namespace)
eq("", self.rbd.mirror_remote_namespace_get(ioctx))
self.rbd.namespace_create(ioctx, "ns1")
ioctx.set_namespace("ns1")
self.rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_IMAGE)
# cannot set remote namespace while mirroring enabled
assert_raises(InvalidArgument, self.rbd.mirror_remote_namespace_set,
ioctx, remote_namespace)
self.rbd.mirror_mode_set(ioctx, RBD_MIRROR_MODE_DISABLED)
# cannot set remote namespace to the default namespace
assert_raises(InvalidArgument, self.rbd.mirror_remote_namespace_set,
ioctx, "")
self.rbd.mirror_remote_namespace_set(ioctx, remote_namespace)
eq(remote_namespace, self.rbd.mirror_remote_namespace_get(ioctx))
ioctx.set_namespace("")
self.rbd.namespace_remove(ioctx, "ns1")
def test_mirror_peer_bootstrap(self): def test_mirror_peer_bootstrap(self):
eq([], list(self.rbd.mirror_peer_list(ioctx))) eq([], list(self.rbd.mirror_peer_list(ioctx)))

View File

@ -409,7 +409,7 @@ TEST_F(TestMockNamespaceReplayer, Init_LocalMirrorStatusUpdaterError) {
expect_mirror_status_updater_init(*mock_local_mirror_status_updater, -EINVAL); expect_mirror_status_updater_init(*mock_local_mirror_status_updater, -EINVAL);
MockNamespaceReplayer namespace_replayer( MockNamespaceReplayer namespace_replayer(
{}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid", {}, {}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid",
"local peer uuid", {"remote mirror uuid", ""}, m_mock_threads, "local peer uuid", {"remote mirror uuid", ""}, m_mock_threads,
nullptr, nullptr, nullptr, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr, nullptr);
@ -432,7 +432,7 @@ TEST_F(TestMockNamespaceReplayer, Init_RemoteMirrorStatusUpdaterError) {
expect_mirror_status_updater_shut_down(*mock_local_mirror_status_updater); expect_mirror_status_updater_shut_down(*mock_local_mirror_status_updater);
MockNamespaceReplayer namespace_replayer( MockNamespaceReplayer namespace_replayer(
{}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid", {}, {}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid",
"local peer uuid", {"remote mirror uuid", ""}, m_mock_threads, "local peer uuid", {"remote mirror uuid", ""}, m_mock_threads,
nullptr, nullptr, nullptr, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr, nullptr);
@ -458,7 +458,7 @@ TEST_F(TestMockNamespaceReplayer, Init_InstanceReplayerError) {
expect_mirror_status_updater_shut_down(*mock_local_mirror_status_updater); expect_mirror_status_updater_shut_down(*mock_local_mirror_status_updater);
MockNamespaceReplayer namespace_replayer( MockNamespaceReplayer namespace_replayer(
{}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid", {}, {}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid",
"local peer uuid", {"remote mirror uuid", ""}, m_mock_threads, "local peer uuid", {"remote mirror uuid", ""}, m_mock_threads,
nullptr, nullptr, nullptr, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr, nullptr);
@ -489,7 +489,7 @@ TEST_F(TestMockNamespaceReplayer, Init_InstanceWatcherError) {
expect_mirror_status_updater_shut_down(*mock_local_mirror_status_updater); expect_mirror_status_updater_shut_down(*mock_local_mirror_status_updater);
MockNamespaceReplayer namespace_replayer( MockNamespaceReplayer namespace_replayer(
{}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid", {}, {}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid",
"local peer uuid", {"remote mirror uuid", ""}, m_mock_threads, "local peer uuid", {"remote mirror uuid", ""}, m_mock_threads,
nullptr, nullptr, nullptr, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr, nullptr);
@ -517,7 +517,7 @@ TEST_F(TestMockNamespaceReplayer, Init) {
MockServiceDaemon mock_service_daemon; MockServiceDaemon mock_service_daemon;
MockNamespaceReplayer namespace_replayer( MockNamespaceReplayer namespace_replayer(
{}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid", {}, {}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid",
"local peer uuid", {"remote mirror uuid", ""}, m_mock_threads, "local peer uuid", {"remote mirror uuid", ""}, m_mock_threads,
nullptr, nullptr, &mock_service_daemon, nullptr, nullptr); nullptr, nullptr, &mock_service_daemon, nullptr, nullptr);
@ -557,7 +557,7 @@ TEST_F(TestMockNamespaceReplayer, AcquireLeader) {
MockServiceDaemon mock_service_daemon; MockServiceDaemon mock_service_daemon;
MockNamespaceReplayer namespace_replayer( MockNamespaceReplayer namespace_replayer(
{}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid", {}, {}, m_local_io_ctx, m_remote_io_ctx, "local mirror uuid",
"local peer uuid", {"remote mirror uuid", ""}, m_mock_threads, "local peer uuid", {"remote mirror uuid", ""}, m_mock_threads,
nullptr, nullptr, &mock_service_daemon, nullptr, nullptr); nullptr, nullptr, &mock_service_daemon, nullptr, nullptr);

View File

@ -129,7 +129,8 @@ struct NamespaceReplayer<librbd::MockTestImageCtx> {
static std::map<std::string, NamespaceReplayer *> s_instances; static std::map<std::string, NamespaceReplayer *> s_instances;
static NamespaceReplayer *create( static NamespaceReplayer *create(
const std::string &name, const std::string &local_name,
const std::string &remote_name,
librados::IoCtx &local_ioctx, librados::IoCtx &local_ioctx,
librados::IoCtx &remote_ioctx, librados::IoCtx &remote_ioctx,
const std::string &local_mirror_uuid, const std::string &local_mirror_uuid,
@ -141,14 +142,15 @@ struct NamespaceReplayer<librbd::MockTestImageCtx> {
ServiceDaemon<librbd::MockTestImageCtx> *service_daemon, ServiceDaemon<librbd::MockTestImageCtx> *service_daemon,
journal::CacheManagerHandler *cache_manager_handler, journal::CacheManagerHandler *cache_manager_handler,
PoolMetaCache* pool_meta_cache) { PoolMetaCache* pool_meta_cache) {
ceph_assert(s_instances.count(name)); ceph_assert(s_instances.count(local_name));
auto namespace_replayer = s_instances[name]; auto namespace_replayer = s_instances[local_name];
s_instances.erase(name); s_instances.erase(local_name);
return namespace_replayer; return namespace_replayer;
} }
MOCK_METHOD0(is_blocklisted, bool()); MOCK_METHOD0(is_blocklisted, bool());
MOCK_METHOD0(get_instance_id, std::string()); MOCK_METHOD0(get_instance_id, std::string());
MOCK_METHOD0(get_remote_namespace, std::string());
MOCK_METHOD1(init, void(Context*)); MOCK_METHOD1(init, void(Context*));
MOCK_METHOD1(shut_down, void(Context*)); MOCK_METHOD1(shut_down, void(Context*));
@ -363,6 +365,18 @@ public:
Return(0))); Return(0)));
} }
void expect_mirror_remote_namespace_get(
librados::MockTestMemIoCtxImpl *io_ctx_impl,
const std::string &remote_namespace, int r) {
EXPECT_CALL(*io_ctx_impl,
exec(RBD_MIRRORING, _, StrEq("rbd"),
StrEq("mirror_remote_namespace_get"), _, _, _, _))
.WillRepeatedly(DoAll(WithArg<5>(Invoke([remote_namespace](bufferlist *bl) {
encode(remote_namespace, *bl);
})),
Return(r)));
}
void expect_clone(librados::MockTestMemIoCtxImpl* mock_io_ctx) { void expect_clone(librados::MockTestMemIoCtxImpl* mock_io_ctx) {
EXPECT_CALL(*mock_io_ctx, clone()) EXPECT_CALL(*mock_io_ctx, clone())
.WillRepeatedly(Invoke([mock_io_ctx]() { .WillRepeatedly(Invoke([mock_io_ctx]() {
@ -510,6 +524,13 @@ public:
EXPECT_CALL(mock_namespace_replayer, handle_instances_removed(_)); EXPECT_CALL(mock_namespace_replayer, handle_instances_removed(_));
} }
void expect_namespace_replayer_get_remote_namespace(
MockNamespaceReplayer &mock_namespace_replayer,
const std::string& remote_namespace) {
EXPECT_CALL(mock_namespace_replayer, get_remote_namespace())
.WillRepeatedly(Return(remote_namespace));
}
void expect_service_daemon_add_namespace( void expect_service_daemon_add_namespace(
MockServiceDaemon &mock_service_daemon, MockServiceDaemon &mock_service_daemon,
const std::string& namespace_name) { const std::string& namespace_name) {
@ -714,10 +735,14 @@ TEST_F(TestMockPoolReplayer, Namespaces) {
auto mock_ns1_namespace_replayer = new MockNamespaceReplayer("ns1"); auto mock_ns1_namespace_replayer = new MockNamespaceReplayer("ns1");
expect_namespace_replayer_is_blocklisted(*mock_ns1_namespace_replayer, expect_namespace_replayer_is_blocklisted(*mock_ns1_namespace_replayer,
false); false);
expect_namespace_replayer_get_remote_namespace(*mock_ns1_namespace_replayer,
"ns1");
auto mock_ns2_namespace_replayer = new MockNamespaceReplayer("ns2"); auto mock_ns2_namespace_replayer = new MockNamespaceReplayer("ns2");
expect_namespace_replayer_is_blocklisted(*mock_ns2_namespace_replayer, expect_namespace_replayer_is_blocklisted(*mock_ns2_namespace_replayer,
false); false);
expect_namespace_replayer_get_remote_namespace(*mock_ns2_namespace_replayer,
"ns2");
MockThreads mock_threads(m_threads); MockThreads mock_threads(m_threads);
expect_work_queue(mock_threads); expect_work_queue(mock_threads);
@ -737,6 +762,7 @@ TEST_F(TestMockPoolReplayer, Namespaces) {
expect_clone(mock_local_io_ctx); expect_clone(mock_local_io_ctx);
expect_mirror_mode_get(mock_local_io_ctx); expect_mirror_mode_get(mock_local_io_ctx);
expect_mirror_remote_namespace_get(mock_local_io_ctx, "", -ENOENT);
InSequence seq; InSequence seq;
@ -856,6 +882,7 @@ TEST_F(TestMockPoolReplayer, NamespacesError) {
expect_clone(mock_local_io_ctx); expect_clone(mock_local_io_ctx);
expect_mirror_mode_get(mock_local_io_ctx); expect_mirror_mode_get(mock_local_io_ctx);
expect_mirror_remote_namespace_get(mock_local_io_ctx, "", -ENOENT);
InSequence seq; InSequence seq;

View File

@ -41,6 +41,7 @@ namespace po = boost::program_options;
static const std::string ALL_NAME("all"); static const std::string ALL_NAME("all");
static const std::string SITE_NAME("site-name"); static const std::string SITE_NAME("site-name");
static const std::string REMOTE_NAMESPACE_NAME("remote-namespace");
namespace { namespace {
@ -1242,6 +1243,10 @@ void get_enable_arguments(po::options_description *positional,
positional->add_options() positional->add_options()
("mode", "mirror mode [image or pool]"); ("mode", "mirror mode [image or pool]");
add_site_name_optional(options); add_site_name_optional(options);
options->add_options()
(REMOTE_NAMESPACE_NAME.c_str(), po::value<std::string>(),
"remote namespace name");
} }
int execute_enable_disable(librados::IoCtx& io_ctx, int execute_enable_disable(librados::IoCtx& io_ctx,
@ -1310,6 +1315,7 @@ int execute_enable(const po::variables_map &vm,
const std::vector<std::string> &ceph_global_init_args) { const std::vector<std::string> &ceph_global_init_args) {
std::string pool_name; std::string pool_name;
std::string namespace_name; std::string namespace_name;
std::string remote_namespace;
size_t arg_index = 0; size_t arg_index = 0;
int r = utils::get_pool_and_namespace_names(vm, true, &pool_name, int r = utils::get_pool_and_namespace_names(vm, true, &pool_name,
&namespace_name, &arg_index); &namespace_name, &arg_index);
@ -1336,15 +1342,36 @@ int execute_enable(const po::variables_map &vm,
return r; return r;
} }
if (vm.count(REMOTE_NAMESPACE_NAME)) {
remote_namespace = vm[REMOTE_NAMESPACE_NAME].as<std::string>();
} else {
remote_namespace = namespace_name;
}
std::string original_remote_namespace;
librbd::RBD rbd;
r = rbd.mirror_remote_namespace_get(io_ctx, &original_remote_namespace);
if (r < 0) {
std::cerr << "rbd: failed to get the current remote namespace."
<< std::endl;
return r;
}
if (original_remote_namespace != remote_namespace) {
r = rbd.mirror_remote_namespace_set(io_ctx, remote_namespace);
if (r < 0) {
std::cerr << "rbd: failed to set the remote namespace."
<< std::endl;
return r;
}
}
bool updated = false; bool updated = false;
if (vm.count(SITE_NAME)) { if (vm.count(SITE_NAME)) {
librbd::RBD rbd;
auto site_name = vm[SITE_NAME].as<std::string>(); auto site_name = vm[SITE_NAME].as<std::string>();
std::string original_site_name; std::string original_site_name;
r = rbd.mirror_site_name_get(rados, &original_site_name); r = rbd.mirror_site_name_get(rados, &original_site_name);
updated = (r >= 0 && site_name != original_site_name); updated = (r >= 0 && site_name != original_site_name);
r = set_site_name(rados, site_name); r = set_site_name(rados, site_name);
if (r < 0) { if (r < 0) {
return r; return r;
@ -1366,6 +1393,8 @@ int execute_info(const po::variables_map &vm,
const std::vector<std::string> &ceph_global_init_args) { const std::vector<std::string> &ceph_global_init_args) {
std::string pool_name; std::string pool_name;
std::string namespace_name; std::string namespace_name;
std::string remote_namespace;
std::string mirror_uuid;
size_t arg_index = 0; size_t arg_index = 0;
int r = utils::get_pool_and_namespace_names(vm, false, &pool_name, int r = utils::get_pool_and_namespace_names(vm, false, &pool_name,
&namespace_name, &arg_index); &namespace_name, &arg_index);
@ -1407,6 +1436,13 @@ int execute_info(const po::variables_map &vm,
} }
} }
if (mirror_mode != RBD_MIRROR_MODE_DISABLED) {
r = rbd.mirror_remote_namespace_get(io_ctx, &remote_namespace);
if (r < 0) {
return r;
}
}
std::string mirror_mode_desc; std::string mirror_mode_desc;
switch (mirror_mode) { switch (mirror_mode) {
case RBD_MIRROR_MODE_DISABLED: case RBD_MIRROR_MODE_DISABLED:
@ -1430,18 +1466,26 @@ int execute_info(const po::variables_map &vm,
std::cout << "Mode: " << mirror_mode_desc << std::endl; std::cout << "Mode: " << mirror_mode_desc << std::endl;
} }
if (mirror_mode != RBD_MIRROR_MODE_DISABLED && namespace_name.empty()) { if (mirror_mode != RBD_MIRROR_MODE_DISABLED) {
if (formatter != nullptr) { if (namespace_name.empty()) {
formatter->dump_string("site_name", site_name); if (formatter != nullptr) {
} else { formatter->dump_string("site_name", site_name);
std::cout << "Site Name: " << site_name << std::endl } else {
<< std::endl; std::cout << "Site Name: " << site_name << std::endl;
}
} }
if (formatter != nullptr) {
r = format_mirror_peers(io_ctx, formatter, mirror_peers, formatter->dump_string("remote_namespace", remote_namespace);
vm[ALL_NAME].as<bool>()); } else {
if (r < 0) { std::cout << "Remote Namespace: " << remote_namespace << std::endl
return r; << std::endl;
}
if (namespace_name.empty()) {
r = format_mirror_peers(io_ctx, formatter, mirror_peers,
vm[ALL_NAME].as<bool>());
if (r < 0) {
return r;
}
} }
} }
if (formatter != nullptr) { if (formatter != nullptr) {

View File

@ -36,7 +36,8 @@ const std::string SERVICE_DAEMON_REMOTE_COUNT_KEY("image_remote_count");
template <typename I> template <typename I>
NamespaceReplayer<I>::NamespaceReplayer( NamespaceReplayer<I>::NamespaceReplayer(
const std::string &name, const std::string &local_name,
const std::string &remote_name,
librados::IoCtx &local_io_ctx, librados::IoCtx &remote_io_ctx, librados::IoCtx &local_io_ctx, librados::IoCtx &remote_io_ctx,
const std::string &local_mirror_uuid, const std::string &local_mirror_uuid,
const std::string& local_mirror_peer_uuid, const std::string& local_mirror_peer_uuid,
@ -47,7 +48,8 @@ NamespaceReplayer<I>::NamespaceReplayer(
ServiceDaemon<I> *service_daemon, ServiceDaemon<I> *service_daemon,
journal::CacheManagerHandler *cache_manager_handler, journal::CacheManagerHandler *cache_manager_handler,
PoolMetaCache* pool_meta_cache) : PoolMetaCache* pool_meta_cache) :
m_namespace_name(name), m_local_namespace_name(local_name),
m_remote_namespace_name(remote_name),
m_local_mirror_uuid(local_mirror_uuid), m_local_mirror_uuid(local_mirror_uuid),
m_local_mirror_peer_uuid(local_mirror_peer_uuid), m_local_mirror_peer_uuid(local_mirror_peer_uuid),
m_remote_pool_meta(remote_pool_meta), m_remote_pool_meta(remote_pool_meta),
@ -57,16 +59,19 @@ NamespaceReplayer<I>::NamespaceReplayer(
m_cache_manager_handler(cache_manager_handler), m_cache_manager_handler(cache_manager_handler),
m_pool_meta_cache(pool_meta_cache), m_pool_meta_cache(pool_meta_cache),
m_lock(ceph::make_mutex(librbd::util::unique_lock_name( m_lock(ceph::make_mutex(librbd::util::unique_lock_name(
"rbd::mirror::NamespaceReplayer " + name, this))), "rbd::mirror::NamespaceReplayer " + local_name, this))),
m_local_pool_watcher_listener(this, true), m_local_pool_watcher_listener(this, true),
m_remote_pool_watcher_listener(this, false), m_remote_pool_watcher_listener(this, false),
m_image_map_listener(this) { m_image_map_listener(this) {
dout(10) << name << dendl; dout(10) << "local_name=" << local_name
<< ", remote_name=" << remote_name
<< ", local_mirror_uuid=" << m_local_mirror_uuid
<< dendl;
m_local_io_ctx.dup(local_io_ctx); m_local_io_ctx.dup(local_io_ctx);
m_local_io_ctx.set_namespace(name); m_local_io_ctx.set_namespace(local_name);
m_remote_io_ctx.dup(remote_io_ctx); m_remote_io_ctx.dup(remote_io_ctx);
m_remote_io_ctx.set_namespace(name); m_remote_io_ctx.set_namespace(remote_name);
} }
template <typename I> template <typename I>
@ -856,6 +861,16 @@ void NamespaceReplayer<I>::handle_remove_image(const std::string &mirror_uuid,
mirror_uuid, on_finish); mirror_uuid, on_finish);
} }
template <typename I>
std::string NamespaceReplayer<I>::get_local_namespace() {
return m_local_namespace_name;
}
template <typename I>
std::string NamespaceReplayer<I>::get_remote_namespace() {
return m_remote_namespace_name;
}
} // namespace mirror } // namespace mirror
} // namespace rbd } // namespace rbd

View File

@ -43,7 +43,8 @@ template <typename ImageCtxT = librbd::ImageCtx>
class NamespaceReplayer { class NamespaceReplayer {
public: public:
static NamespaceReplayer *create( static NamespaceReplayer *create(
const std::string &name, const std::string &local_name,
const std::string &remote_name,
librados::IoCtx &local_ioctx, librados::IoCtx &local_ioctx,
librados::IoCtx &remote_ioctx, librados::IoCtx &remote_ioctx,
const std::string &local_mirror_uuid, const std::string &local_mirror_uuid,
@ -55,7 +56,7 @@ public:
ServiceDaemon<ImageCtxT> *service_daemon, ServiceDaemon<ImageCtxT> *service_daemon,
journal::CacheManagerHandler *cache_manager_handler, journal::CacheManagerHandler *cache_manager_handler,
PoolMetaCache* pool_meta_cache) { PoolMetaCache* pool_meta_cache) {
return new NamespaceReplayer(name, local_ioctx, remote_ioctx, return new NamespaceReplayer(local_name, remote_name, local_ioctx, remote_ioctx,
local_mirror_uuid, local_mirror_peer_uuid, local_mirror_uuid, local_mirror_peer_uuid,
remote_pool_meta, threads, remote_pool_meta, threads,
image_sync_throttler, image_deletion_throttler, image_sync_throttler, image_deletion_throttler,
@ -63,7 +64,8 @@ public:
pool_meta_cache); pool_meta_cache);
} }
NamespaceReplayer(const std::string &name, NamespaceReplayer(const std::string &local_name,
const std::string &remote_name,
librados::IoCtx &local_ioctx, librados::IoCtx &local_ioctx,
librados::IoCtx &remote_ioctx, librados::IoCtx &remote_ioctx,
const std::string &local_mirror_uuid, const std::string &local_mirror_uuid,
@ -95,6 +97,9 @@ public:
void restart(); void restart();
void flush(); void flush();
std::string get_local_namespace();
std::string get_remote_namespace();
private: private:
/** /**
* @verbatim * @verbatim
@ -264,7 +269,8 @@ private:
const std::string &instance_id, const std::string &instance_id,
Context* on_finish); Context* on_finish);
std::string m_namespace_name; std::string m_local_namespace_name;
std::string m_remote_namespace_name;
librados::IoCtx m_local_io_ctx; librados::IoCtx m_local_io_ctx;
librados::IoCtx m_remote_io_ctx; librados::IoCtx m_remote_io_ctx;
std::string m_local_mirror_uuid; std::string m_local_mirror_uuid;

View File

@ -369,7 +369,7 @@ void PoolReplayer<I>::init(const std::string& site_name) {
m_local_io_ctx.get_id(), {m_local_mirror_uuid}); m_local_io_ctx.get_id(), {m_local_mirror_uuid});
m_default_namespace_replayer.reset(NamespaceReplayer<I>::create( m_default_namespace_replayer.reset(NamespaceReplayer<I>::create(
"", m_local_io_ctx, m_remote_io_ctx, m_local_mirror_uuid, m_peer.uuid, "", "", m_local_io_ctx, m_remote_io_ctx, m_local_mirror_uuid, m_peer.uuid,
m_remote_pool_meta, m_threads, m_image_sync_throttler.get(), m_remote_pool_meta, m_threads, m_image_sync_throttler.get(),
m_image_deletion_throttler.get(), m_service_daemon, m_image_deletion_throttler.get(), m_service_daemon,
m_cache_manager_handler, m_pool_meta_cache)); m_cache_manager_handler, m_pool_meta_cache));
@ -638,7 +638,7 @@ void PoolReplayer<I>::update_namespace_replayers() {
ceph_assert(ceph_mutex_is_locked(m_lock)); ceph_assert(ceph_mutex_is_locked(m_lock));
std::set<std::string> mirroring_namespaces; std::map<std::string, std::string> mirroring_namespaces;
if (!m_stopping) { if (!m_stopping) {
int r = list_mirroring_namespaces(&mirroring_namespaces); int r = list_mirroring_namespaces(&mirroring_namespaces);
if (r < 0) { if (r < 0) {
@ -652,7 +652,8 @@ void PoolReplayer<I>::update_namespace_replayers() {
for (auto it = m_namespace_replayers.begin(); for (auto it = m_namespace_replayers.begin();
it != m_namespace_replayers.end(); ) { it != m_namespace_replayers.end(); ) {
auto iter = mirroring_namespaces.find(it->first); auto iter = mirroring_namespaces.find(it->first);
if (iter == mirroring_namespaces.end()) { if (iter == mirroring_namespaces.end() ||
it->second->get_remote_namespace() != iter->second) {
auto namespace_replayer = it->second; auto namespace_replayer = it->second;
auto on_shut_down = new LambdaContext( auto on_shut_down = new LambdaContext(
[namespace_replayer, ctx=gather_ctx->new_sub()](int r) { [namespace_replayer, ctx=gather_ctx->new_sub()](int r) {
@ -668,24 +669,24 @@ void PoolReplayer<I>::update_namespace_replayers() {
} }
} }
for (auto &name : mirroring_namespaces) { for (auto &names : mirroring_namespaces) {
auto namespace_replayer = NamespaceReplayer<I>::create( auto namespace_replayer = NamespaceReplayer<I>::create(
name, m_local_io_ctx, m_remote_io_ctx, m_local_mirror_uuid, m_peer.uuid, names.first, names.second, m_local_io_ctx, m_remote_io_ctx,
m_remote_pool_meta, m_threads, m_image_sync_throttler.get(), m_local_mirror_uuid, m_peer.uuid, m_remote_pool_meta, m_threads,
m_image_deletion_throttler.get(), m_service_daemon, m_image_sync_throttler.get(), m_image_deletion_throttler.get(),
m_cache_manager_handler, m_pool_meta_cache); m_service_daemon, m_cache_manager_handler, m_pool_meta_cache);
auto on_init = new LambdaContext( auto on_init = new LambdaContext(
[this, namespace_replayer, name, &mirroring_namespaces, [this, namespace_replayer, names, &mirroring_namespaces,
ctx=gather_ctx->new_sub()](int r) { ctx=gather_ctx->new_sub()](int r) {
std::lock_guard locker{m_lock}; std::lock_guard locker{m_lock};
if (r < 0) { if (r < 0) {
derr << "failed to initialize namespace replayer for namespace " derr << "failed to initialize namespace replayer for namespace "
<< name << ": " << cpp_strerror(r) << dendl; << names.first << ": " << cpp_strerror(r) << dendl;
delete namespace_replayer; delete namespace_replayer;
mirroring_namespaces.erase(name); mirroring_namespaces.erase(names.first);
} else { } else {
m_namespace_replayers[name] = namespace_replayer; m_namespace_replayers[names.first] = namespace_replayer;
m_service_daemon->add_namespace(m_local_pool_id, name); m_service_daemon->add_namespace(m_local_pool_id, names.first);
} }
ctx->complete(r); ctx->complete(r);
}); });
@ -702,8 +703,8 @@ void PoolReplayer<I>::update_namespace_replayers() {
C_SaferCond acquire_cond; C_SaferCond acquire_cond;
auto acquire_gather_ctx = new C_Gather(cct, &acquire_cond); auto acquire_gather_ctx = new C_Gather(cct, &acquire_cond);
for (auto &name : mirroring_namespaces) { for (auto &names : mirroring_namespaces) {
namespace_replayer_acquire_leader(name, acquire_gather_ctx->new_sub()); namespace_replayer_acquire_leader(names.first, acquire_gather_ctx->new_sub());
} }
acquire_gather_ctx->activate(); acquire_gather_ctx->activate();
@ -714,8 +715,8 @@ void PoolReplayer<I>::update_namespace_replayers() {
std::vector<std::string> instance_ids; std::vector<std::string> instance_ids;
m_leader_watcher->list_instances(&instance_ids); m_leader_watcher->list_instances(&instance_ids);
for (auto &name : mirroring_namespaces) { for (auto &names : mirroring_namespaces) {
auto it = m_namespace_replayers.find(name); auto it = m_namespace_replayers.find(names.first);
if (it == m_namespace_replayers.end()) { if (it == m_namespace_replayers.end()) {
// acquire leader for this namespace replayer failed // acquire leader for this namespace replayer failed
continue; continue;
@ -725,8 +726,8 @@ void PoolReplayer<I>::update_namespace_replayers() {
} else { } else {
std::string leader_instance_id; std::string leader_instance_id;
if (m_leader_watcher->get_leader_instance_id(&leader_instance_id)) { if (m_leader_watcher->get_leader_instance_id(&leader_instance_id)) {
for (auto &name : mirroring_namespaces) { for (auto &names : mirroring_namespaces) {
m_namespace_replayers[name]->handle_update_leader(leader_instance_id); m_namespace_replayers[names.first]->handle_update_leader(leader_instance_id);
} }
} }
} }
@ -734,7 +735,7 @@ void PoolReplayer<I>::update_namespace_replayers() {
template <typename I> template <typename I>
int PoolReplayer<I>::list_mirroring_namespaces( int PoolReplayer<I>::list_mirroring_namespaces(
std::set<std::string> *namespaces) { std::map<std::string, std::string> *namespaces) {
dout(20) << dendl; dout(20) << dendl;
ceph_assert(ceph_mutex_is_locked(m_lock)); ceph_assert(ceph_mutex_is_locked(m_lock));
@ -751,6 +752,7 @@ int PoolReplayer<I>::list_mirroring_namespaces(
ns_ioctx.dup(m_local_io_ctx); ns_ioctx.dup(m_local_io_ctx);
ns_ioctx.set_namespace(name); ns_ioctx.set_namespace(name);
std::string remote_namespace;
cls::rbd::MirrorMode mirror_mode = cls::rbd::MIRROR_MODE_DISABLED; cls::rbd::MirrorMode mirror_mode = cls::rbd::MIRROR_MODE_DISABLED;
int r = librbd::cls_client::mirror_mode_get(&ns_ioctx, &mirror_mode); int r = librbd::cls_client::mirror_mode_get(&ns_ioctx, &mirror_mode);
if (r < 0 && r != -ENOENT) { if (r < 0 && r != -ENOENT) {
@ -763,8 +765,21 @@ int PoolReplayer<I>::list_mirroring_namespaces(
dout(10) << "mirroring is disabled for namespace " << name << dendl; dout(10) << "mirroring is disabled for namespace " << name << dendl;
continue; continue;
} }
r = librbd::cls_client::mirror_remote_namespace_get(&ns_ioctx,
&remote_namespace);
if (r < 0) {
if (r != -ENOENT && r != -EOPNOTSUPP) {
derr << "failed to get remote mirror namespace: " << cpp_strerror(r)
<< dendl;
continue;
} else {
remote_namespace = name;
}
}
namespaces->insert(name); dout(10) << " local namespace=" << name << ", remote namespace="
<< remote_namespace << dendl;
namespaces->insert(std::make_pair(name, remote_namespace));
} }
return 0; return 0;

View File

@ -107,7 +107,7 @@ private:
bool strip_cluster_overrides); bool strip_cluster_overrides);
void update_namespace_replayers(); void update_namespace_replayers();
int list_mirroring_namespaces(std::set<std::string> *namespaces); int list_mirroring_namespaces(std::map<std::string, std::string> *namespaces);
void namespace_replayer_acquire_leader(const std::string &name, void namespace_replayer_acquire_leader(const std::string &name,
Context *on_finish); Context *on_finish);