From f099a10596a6eb7f053a062be2351a757c327f5c Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Sat, 27 Aug 2022 11:09:00 +0200 Subject: [PATCH] librbd: use actual monitor addresses when creating a peer bootstrap token 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 (cherry picked from commit de0ba80b37bf3df22bb2976871332344a4fb141e) --- qa/workunits/rbd/cli_generic.sh | 47 +++++++++++++++++++++++++++++++++ src/librbd/api/Mirror.cc | 25 +++++++++++++++--- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/qa/workunits/rbd/cli_generic.sh b/qa/workunits/rbd/cli_generic.sh index 2f6f7a944add0..042d67faddaf7 100755 --- a/qa/workunits/rbd/cli_generic.sh +++ b/qa/workunits/rbd/cli_generic.sh @@ -1413,6 +1413,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 @@ -1436,5 +1482,6 @@ test_namespace test_trash_purge_schedule test_mirror_snapshot_schedule test_perf_image_iostat +test_mirror_pool_peer_bootstrap_create echo OK diff --git a/src/librbd/api/Mirror.cc b/src/librbd/api/Mirror.cc index 51716ff369879..8a0e8f8251dd3 100644 --- a/src/librbd/api/Mirror.cc +++ b/src/librbd/api/Mirror.cc @@ -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("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::peer_bootstrap_create(librados::IoCtx& io_ctx, return r; } - std::string mon_host = cct->_conf.get_val("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::peer_bootstrap_import(librados::IoCtx& io_ctx, return r; } - std::string local_mon_host = cct->_conf.get_val("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, -- 2.39.5