]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: use actual monitor addresses when creating a peer bootstrap token 47911/head
authorIlya Dryomov <idryomov@gmail.com>
Sat, 27 Aug 2022 09:09:00 +0000 (11:09 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Thu, 1 Sep 2022 18:15:21 +0000 (20:15 +0200)
Relying on mon_host config option is fragile, as the user may confuse
v1 and v2 addresses, group them incorrectly, etc.  Get mon_host value
only as a fallback.

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

qa/workunits/rbd/cli_generic.sh
src/librbd/api/Mirror.cc

index 2b3de518af637eae07b96743032a6a90cde662ca..41f721f61829612c7b1ff72e9b5c0e185f7514a4 100755 (executable)
@@ -1407,6 +1407,52 @@ test_perf_image_iostat() {
     ceph osd pool rm rbd1 rbd1 --yes-i-really-really-mean-it
 }
 
+test_mirror_pool_peer_bootstrap_create() {
+    echo "testing mirror pool peer bootstrap create..."
+    remove_images
+
+    ceph osd pool create rbd1 8
+    rbd pool init rbd1
+    rbd mirror pool enable rbd1 image
+    ceph osd pool create rbd2 8
+    rbd pool init rbd2
+    rbd mirror pool enable rbd2 pool
+
+    readarray -t MON_ADDRS < <(ceph mon dump |
+        sed -n 's/^[0-9]: \(.*\) mon\.[a-z]$/\1/p')
+
+    # check that all monitors make it to the token even if only one
+    # valid monitor is specified
+    BAD_MON_ADDR="1.2.3.4:6789"
+    MON_HOST="${MON_ADDRS[0]},$BAD_MON_ADDR"
+    TOKEN="$(rbd mirror pool peer bootstrap create \
+        --mon-host "$MON_HOST" rbd1 | base64 -d)"
+    TOKEN_FSID="$(jq -r '.fsid' <<< "$TOKEN")"
+    TOKEN_CLIENT_ID="$(jq -r '.client_id' <<< "$TOKEN")"
+    TOKEN_KEY="$(jq -r '.key' <<< "$TOKEN")"
+    TOKEN_MON_HOST="$(jq -r '.mon_host' <<< "$TOKEN")"
+
+    test "$TOKEN_FSID" = "$(ceph fsid)"
+    test "$TOKEN_KEY" = "$(ceph auth get-key client.$TOKEN_CLIENT_ID)"
+    for addr in "${MON_ADDRS[@]}"; do
+        fgrep "$addr" <<< "$TOKEN_MON_HOST"
+    done
+    expect_fail fgrep "$BAD_MON_ADDR" <<< "$TOKEN_MON_HOST"
+
+    # check that the token does not change, including across pools
+    test "$(rbd mirror pool peer bootstrap create \
+        --mon-host "$MON_HOST" rbd1 | base64 -d)" = "$TOKEN"
+    test "$(rbd mirror pool peer bootstrap create \
+        rbd1 | base64 -d)" = "$TOKEN"
+    test "$(rbd mirror pool peer bootstrap create \
+        --mon-host "$MON_HOST" rbd2 | base64 -d)" = "$TOKEN"
+    test "$(rbd mirror pool peer bootstrap create \
+        rbd2 | base64 -d)" = "$TOKEN"
+
+    ceph osd pool rm rbd2 rbd2 --yes-i-really-really-mean-it
+    ceph osd pool rm rbd1 rbd1 --yes-i-really-really-mean-it
+}
+
 test_pool_image_args
 test_rename
 test_ls
@@ -1430,5 +1476,6 @@ test_namespace
 test_trash_purge_schedule
 test_mirror_snapshot_schedule
 test_perf_image_iostat
+test_mirror_pool_peer_bootstrap_create
 
 echo OK
index 825d430bc05b8d4ba1d1ef33c3afaa10bbb10956..bbaa4eff7bb17d258a0806d3bb5f30f8970f0eb6 100644 (file)
@@ -115,6 +115,26 @@ int remove_peer_config_key(librados::IoCtx& io_ctx,
   return 0;
 }
 
+std::string get_mon_host(CephContext* cct) {
+  std::string mon_host;
+  if (auto mon_addrs = cct->get_mon_addrs();
+      mon_addrs != nullptr && !mon_addrs->empty()) {
+    CachedStackStringStream css;
+    for (auto it = mon_addrs->begin(); it != mon_addrs->end(); ++it) {
+      if (it != mon_addrs->begin()) {
+        *css << ",";
+      }
+      *css << *it;
+    }
+    mon_host = css->str();
+  } else {
+    ldout(cct, 20) << "falling back to mon_host in conf" << dendl;
+    mon_host = cct->_conf.get_val<std::string>("mon_host");
+  }
+  ldout(cct, 20) << "mon_host=" << mon_host << dendl;
+  return mon_host;
+}
+
 int create_bootstrap_user(CephContext* cct, librados::Rados& rados,
                           std::string* peer_client_id, std::string* cephx_key) {
   ldout(cct, 20) << dendl;
@@ -1298,8 +1318,7 @@ int Mirror<I>::peer_bootstrap_create(librados::IoCtx& io_ctx,
     return r;
   }
 
-  std::string mon_host = cct->_conf.get_val<std::string>("mon_host");
-  ldout(cct, 20) << "mon_host=" << mon_host << dendl;
+  std::string mon_host = get_mon_host(cct);
 
   // format the token response
   bufferlist token_bl;
@@ -1471,7 +1490,7 @@ int Mirror<I>::peer_bootstrap_import(librados::IoCtx& io_ctx,
       return r;
     }
 
-    std::string local_mon_host = cct->_conf.get_val<std::string>("mon_host");
+    std::string local_mon_host = get_mon_host(cct);
 
     // create local cluster peer in remote cluster
     r = create_bootstrap_peer(cct, remote_io_ctx,