]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: fix mirror image status summary in a namespace
authorIlya Dryomov <idryomov@gmail.com>
Tue, 11 Feb 2025 16:44:51 +0000 (17:44 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Fri, 14 Feb 2025 14:09:03 +0000 (15:09 +0100)
For the purposes of the summary with image counts, "rbd mirror pool
status" command is supposed to count each image only once.  To this
end, for unidirectional mirroring the status of the receiving site
should be taken while for bidirectional mirroring the statuses should
be combined/reduced.  For example, if mirroring is enabled on a single
image and everything is in order, the summary is expected to be

  image health: OK
  images: 1 total
      1 replaying

on both clusters even though on the primary the local status is
MIRROR_IMAGE_STATUS_STATE_STOPPED and only on the secondary it's
MIRROR_IMAGE_STATUS_STATE_REPLAYING.

Currently this isn't the case for custom namespaces.  In the same
scenario the primary ends up reporting

  image health: OK
  images: 1 total
      1 stopped

based solely on the local status in a namespace.

Fixes: https://tracker.ceph.com/issues/69911
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
(cherry picked from commit f5eadfff807a84ff6561da3239ee804e735d64b0)

Conflicts:
qa/workunits/rbd/rbd_mirror_bootstrap.sh [ commits 3fd8a0388735
  ("qa/workunits/rbd: merge journal and snapshot test scripts")
  and 3fdbc160bb21 ("rbd-mirror: allow mirroring to a different
  namespace") not in reef ]

qa/workunits/rbd/rbd_mirror_bootstrap.sh
qa/workunits/rbd/rbd_mirror_helpers.sh
src/librbd/api/Mirror.cc

index 28f9d7c80f1199ec4084d9ab51cb58e0aaa4111e..4c3c1ccd2bd750ba86e3ccbc40f94f9cfb1fe7c7 100755 (executable)
@@ -35,12 +35,28 @@ done
 rbd --cluster ${CLUSTER1} --pool ${POOL} mirror pool info --format json | jq -e '.peers[0].direction == "tx-only"'
 
 create_image_and_enable_mirror ${CLUSTER1} ${POOL} image1
+create_image_and_enable_mirror ${CLUSTER1} ${POOL}/${NS1} image1
 
 wait_for_image_replay_started ${CLUSTER2} ${POOL} image1
 write_image ${CLUSTER1} ${POOL} image1 100
 wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${POOL} image1
 wait_for_status_in_pool_dir ${CLUSTER2} ${POOL} image1 'up+replaying'
 
+POOL_STATUS=$(get_pool_status_json ${CLUSTER1} ${POOL})
+jq -e '.summary.states == {"replaying": 1}' <<< ${POOL_STATUS}
+POOL_STATUS=$(get_pool_status_json ${CLUSTER2} ${POOL})
+jq -e '.summary.states == {"replaying": 1}' <<< ${POOL_STATUS}
+
+wait_for_image_replay_started ${CLUSTER2} ${POOL}/${NS1} image1
+write_image ${CLUSTER1} ${POOL}/${NS1} image1 100
+wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${POOL}/${NS1} image1
+wait_for_status_in_pool_dir ${CLUSTER2} ${POOL}/${NS1} image1 'up+replaying'
+
+POOL_STATUS=$(get_pool_status_json ${CLUSTER1} ${POOL}/${NS1})
+jq -e '.summary.states == {"replaying": 1}' <<< ${POOL_STATUS}
+POOL_STATUS=$(get_pool_status_json ${CLUSTER2} ${POOL}/${NS1})
+jq -e '.summary.states == {"replaying": 1}' <<< ${POOL_STATUS}
+
 testlog "TEST: verify rx-tx direction"
 # both rx-tx peers are added immediately by "rbd mirror pool peer bootstrap import"
 rbd --cluster ${CLUSTER1} --pool ${PARENT_POOL} mirror pool info --format json | jq -e '.peers[0].direction == "rx-tx"'
@@ -52,6 +68,9 @@ create_image ${CLUSTER2} ${PARENT_POOL} image2
 enable_mirror ${CLUSTER1} ${PARENT_POOL} image1
 enable_mirror ${CLUSTER2} ${PARENT_POOL} image2
 
+create_image_and_enable_mirror ${CLUSTER1} ${PARENT_POOL}/${NS1} image1
+create_image_and_enable_mirror ${CLUSTER2} ${PARENT_POOL}/${NS1} image2
+
 wait_for_image_replay_started ${CLUSTER2} ${PARENT_POOL} image1
 write_image ${CLUSTER1} ${PARENT_POOL} image1 100
 wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${PARENT_POOL} image1
@@ -62,6 +81,26 @@ write_image ${CLUSTER2} ${PARENT_POOL} image2 100
 wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${PARENT_POOL} image2
 wait_for_status_in_pool_dir ${CLUSTER1} ${PARENT_POOL} image2 'up+replaying'
 
+POOL_STATUS=$(get_pool_status_json ${CLUSTER1} ${PARENT_POOL})
+jq -e '.summary.states == {"replaying": 2}' <<< ${POOL_STATUS}
+POOL_STATUS=$(get_pool_status_json ${CLUSTER2} ${PARENT_POOL})
+jq -e '.summary.states == {"replaying": 2}' <<< ${POOL_STATUS}
+
+wait_for_image_replay_started ${CLUSTER2} ${PARENT_POOL}/${NS1} image1
+write_image ${CLUSTER1} ${PARENT_POOL}/${NS1} image1 100
+wait_for_replay_complete ${CLUSTER2} ${CLUSTER1} ${PARENT_POOL}/${NS1} image1
+wait_for_status_in_pool_dir ${CLUSTER2} ${PARENT_POOL}/${NS1} image1 'up+replaying'
+
+wait_for_image_replay_started ${CLUSTER1} ${PARENT_POOL}/${NS1} image2
+write_image ${CLUSTER2} ${PARENT_POOL}/${NS1} image2 100
+wait_for_replay_complete ${CLUSTER1} ${CLUSTER2} ${PARENT_POOL}/${NS1} image2
+wait_for_status_in_pool_dir ${CLUSTER1} ${PARENT_POOL}/${NS1} image2 'up+replaying'
+
+POOL_STATUS=$(get_pool_status_json ${CLUSTER1} ${PARENT_POOL}/${NS1})
+jq -e '.summary.states == {"replaying": 2}' <<< ${POOL_STATUS}
+POOL_STATUS=$(get_pool_status_json ${CLUSTER2} ${PARENT_POOL}/${NS1})
+jq -e '.summary.states == {"replaying": 2}' <<< ${POOL_STATUS}
+
 testlog "TEST: pool replayer and callout cleanup when peer is updated"
 test_health_state ${CLUSTER1} ${PARENT_POOL} 'OK'
 test_health_state ${CLUSTER2} ${PARENT_POOL} 'OK'
index 2dfee5181d528841c46bed9d7a3721385f4eaf07..96ba1c7ba93015f9448e3cab695ba53bd4cdf31f 100755 (executable)
@@ -299,9 +299,11 @@ setup_pools()
 
     rbd --cluster ${cluster} namespace create ${POOL}/${NS1}
     rbd --cluster ${cluster} namespace create ${POOL}/${NS2}
+    rbd --cluster ${cluster} namespace create ${PARENT_POOL}/${NS1}
 
     rbd --cluster ${cluster} mirror pool enable ${POOL}/${NS1} ${MIRROR_POOL_MODE}
     rbd --cluster ${cluster} mirror pool enable ${POOL}/${NS2} image
+    rbd --cluster ${cluster} mirror pool enable ${PARENT_POOL}/${NS1} ${MIRROR_POOL_MODE}
 
     if [ -z ${RBD_MIRROR_MANUAL_PEERS} ]; then
       if [ -z ${RBD_MIRROR_CONFIG_KEY} ]; then
index 2cfad0d32753220c276dba1a1ecec72d99a811c8..5e4efe14eab5a9ce39dc297f7f240806e149fabe 100644 (file)
@@ -1945,8 +1945,11 @@ int Mirror<I>::image_status_summary(librados::IoCtx& io_ctx,
                                     MirrorImageStatusStates *states) {
   CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
 
+  librados::IoCtx default_ns_io_ctx;
+  default_ns_io_ctx.dup(io_ctx);
+  default_ns_io_ctx.set_namespace("");
   std::vector<cls::rbd::MirrorPeer> mirror_peers;
-  int r = cls_client::mirror_peer_list(&io_ctx, &mirror_peers);
+  int r = cls_client::mirror_peer_list(&default_ns_io_ctx, &mirror_peers);
   if (r < 0 && r != -ENOENT) {
     lderr(cct) << "failed to list mirror peers: " << cpp_strerror(r) << dendl;
     return r;