Replace request-aws by awscurl

use awscurl instead of request-aws(deprecated and unmaintained upstream)
use either service_type/service_name to get object-store endpoint

Also, use the service_name to target the endpoint.

Change-Id: Ice6c1bf9463c71aab55be8c1c1c932609f5f8191
Signed-off-by: Wissem Mimouna <ceph-users@ik.me>
Signed-off-by: Thomas Goirand <zigo@debian.org>
This commit is contained in:
Wissem MIMOUNA
2025-10-24 11:41:54 +02:00
committed by Thomas Goirand
parent dd5c5eb3cc
commit b7c27f7fc9
4 changed files with 62 additions and 20 deletions

View File

@@ -44,6 +44,11 @@ CLIENT_OPTS = [
cfg.BoolOpt('implicit_tenants',
default=False,
help='Whether RGW uses implicit tenants or not.'),
cfg.StrOpt('rgw_service_name',
default=None,
sample_default='ceph',
help='Service name for object store endpoint. '
'If left to None, will use [service_types]/radosgw.'),
]
@@ -68,9 +73,21 @@ class _Base(plugin_base.PollsterBase):
@staticmethod
def _get_endpoint(conf, ksclient):
# we store the endpoint as a base class attribute, so keystone is
# only ever called once, also we assume that in a single deployment
# we may be only deploying `radosgw` or `swift` as the object-store
if _Base._ENDPOINT is None and conf.service_types.radosgw:
# only ever called once.
if _Base._ENDPOINT is None and conf.rgw_client.rgw_service_name:
try:
creds = conf.service_credentials
# Use the service_name to target the endpoint.
# There are cases where both 'radosgw' and 'swift' are used.
rgw_url = keystone_client.get_service_catalog(
ksclient).url_for(
service_name=conf.rgw_client.rgw_service_name,
interface=creds.interface,
region_name=creds.region_name)
_Base._ENDPOINT = urlparse.urljoin(rgw_url, '/admin')
except exceptions.EndpointNotFound:
LOG.debug("Radosgw endpoint not found")
elif _Base._ENDPOINT is None and conf.service_types.radosgw:
try:
creds = conf.service_credentials
rgw_url = keystone_client.get_service_catalog(
@@ -81,6 +98,7 @@ class _Base(plugin_base.PollsterBase):
_Base._ENDPOINT = urlparse.urljoin(rgw_url, '/admin')
except exceptions.EndpointNotFound:
LOG.debug("Radosgw endpoint not found")
LOG.debug(f"Using endpoint {_Base._ENDPOINT} for radosgw connections")
return _Base._ENDPOINT
def _iter_accounts(self, ksclient, cache, tenants):

View File

@@ -16,8 +16,7 @@
from collections import namedtuple
from awsauth import S3Auth
import requests
from awscurl import awscurl
from urllib import parse as urlparse
@@ -40,15 +39,37 @@ class RGWAdminClient:
def _make_request(self, path, req_params):
uri = f"{self.endpoint}/{path}"
r = requests.get(uri, params=req_params,
auth=S3Auth(self.access_key, self.secret,
self.hostname)
)
if req_params:
uri = f"{uri}?"
# Append req_params content to the uri
for i, (key, value) in enumerate(req_params.items()):
if i == len(req_params) - 1:
uri = uri + key + "=" + value
else:
uri = uri + key + "=" + value + "&"
# Data to be sent with request POST type,
# otherwise provide an empty string
data = ""
service = "s3"
method = "GET"
# Default region, in the case of radosgw either set
# the value to your zonegroup name or keep the default region.
# With a single Ceph zone-group, there's no need to customize
# this value.
region = "us-east-1"
headers = {'Accept': 'application/json'}
r = awscurl.make_request(method, service, region, uri, headers, data,
self.access_key, self.secret, None, False,
False)
if r.status_code != 200:
raise RGWAdminAPIFailed(
_('RGW AdminOps API returned %(status)s %(reason)s') %
{'status': r.status_code, 'reason': r.reason})
if not r.text:
return {}
return r.json()

View File

@@ -154,7 +154,7 @@ class TestRGWAdminClient(base.BaseTestCase):
self.client = rgw_client.RGWAdminClient('http://127.0.0.1:8080/admin',
'abcde', 'secret', False)
self.get_resp = mock.MagicMock()
self.get = mock.patch('requests.get',
self.get = mock.patch('requests.request',
return_value=self.get_resp).start()
def test_make_request_exception(self):
@@ -180,8 +180,9 @@ class TestRGWAdminClient(base.BaseTestCase):
'buckets': bucket_list}
self.assertEqual(expected, actual)
self.assertEqual(1, len(self.get.call_args_list))
self.assertEqual('foo',
self.get.call_args_list[0][1]['params']['uid'])
self.assertEqual('http://127.0.0.1:8080/admin/bucket?'
'uid=foo&stats=true',
self.get.call_args_list[0][0][1])
def test_get_buckets_implicit_tenants(self):
self.get_resp.status_code = 200
@@ -195,8 +196,9 @@ class TestRGWAdminClient(base.BaseTestCase):
'buckets': bucket_list}
self.assertEqual(expected, actual)
self.assertEqual(1, len(self.get.call_args_list))
self.assertEqual('foo$foo',
self.get.call_args_list[0][1]['params']['uid'])
self.assertEqual('http://127.0.0.1:8080/admin/bucket?'
'uid=foo$foo&stats=true',
self.get.call_args_list[0][0][1])
def test_get_usage(self):
self.get_resp.status_code = 200
@@ -205,8 +207,8 @@ class TestRGWAdminClient(base.BaseTestCase):
expected = 7
self.assertEqual(expected, actual)
self.assertEqual(1, len(self.get.call_args_list))
self.assertEqual('foo',
self.get.call_args_list[0][1]['params']['uid'])
self.assertEqual('http://127.0.0.1:8080/admin/usage?uid=foo',
self.get.call_args_list[0][0][1])
def test_get_usage_implicit_tenants(self):
self.get_resp.status_code = 200
@@ -216,5 +218,5 @@ class TestRGWAdminClient(base.BaseTestCase):
expected = 7
self.assertEqual(expected, actual)
self.assertEqual(1, len(self.get.call_args_list))
self.assertEqual('foo$foo',
self.get.call_args_list[0][1]['params']['uid'])
self.assertEqual('http://127.0.0.1:8080/admin/usage?uid=foo$foo',
self.get.call_args_list[0][0][1])

View File

@@ -35,6 +35,7 @@ tooz>=1.47.0 # Apache-2.0
oslo.cache>=1.26.0 # Apache-2.0
gnocchiclient>=7.0.0 # Apache-2.0
python-zaqarclient>=1.3.0 # Apache-2.0
prometheus_client>=0.20.0 # Apache-2.0
requests-aws>=0.1.4 # BSD License (3 clause)
prometheus-client>=0.20.0 # Apache-2.0
aodhclient>=3.8.0 # Apache-2.0
awscurl>=0.36 # MIT
botocore>=1.20.0 # Apache-2.0