qa/rgw: add teuthology support for target_by_bucket cloud transition

Add cloud_target_by_bucket and cloud_target_by_bucket_prefix options
to rgw_cloudtier.py and s3tests.py. Create new test suite to run
target_by_bucket-specific s3-tests.

Signed-off-by: Matthew N. Heler <matthew.heler@hotmail.com>
This commit is contained in:
Matthew N. Heler 2025-12-16 20:53:20 -06:00
parent 3ba0aba593
commit c3f7797a01
4 changed files with 67 additions and 0 deletions

View File

@ -0,0 +1 @@
../.qa/

View File

@ -0,0 +1,33 @@
tasks:
- install:
- ceph:
- rgw:
client.0:
port: 8000
client.1:
port: 8001
- rgw-cloudtier:
client.1:
client.0:
cloud_storage_class: CLOUDTIER-CLIENT0
cloud_client: client.1
cloud_regular_storage_class: LUKEWARM
cloud_target_storage_class: FROZEN
cloud_retain_head_object: "true"
cloud_target_by_bucket: "true"
cloud_target_by_bucket_prefix: "rgwx-${storage_class}-${bucket}"
cloud_allow_read_through: "true"
cloud_read_through_restore_days: "5"
cloudtier_user:
cloud_secret: "abcefgh"
cloud_access_key: "12345678"
- tox: [client.0]
- s3tests:
client.0:
rgw_server: client.0
extra_attrs: ["target_by_bucket"]
lc_debug_interval: 10
rgw_restore_debug_interval: 20
rgw_restore_processor_period: 10
lifecycle_tests: True
cloudtier_tests: True

View File

@ -30,6 +30,8 @@ class RGWCloudTier(Task):
cloud_target_path:
cloud_allow_read_through:
cloud_read_through_restore_days:
cloud_target_by_bucket:
cloud_target_by_bucket_prefix:
cloudtier_user:
cloud_secret:
cloud_access_key:
@ -38,6 +40,24 @@ class RGWCloudTier(Task):
def __init__(self, ctx, config):
super(RGWCloudTier, self).__init__(ctx, config)
@staticmethod
def _normalize_bool_option(value, option_name):
"""
Normalize a boolean option to 'true' or 'false' string.
RGW parses these as case-sensitive s == "true".
"""
if value is None:
return None
if isinstance(value, bool):
return "true" if value else "false"
if isinstance(value, str):
normalized = value.strip().lower()
if normalized not in ("true", "false"):
raise ConfigError(
f"rgw-cloudtier: {option_name} must be 'true' or 'false', got '{value}'")
return normalized
raise ConfigError(f"rgw-cloudtier: {option_name} must be a boolean or string, got {type(value)}")
def setup(self):
super(RGWCloudTier, self).setup()
@ -66,6 +86,9 @@ class RGWCloudTier(Task):
cloud_retain_head_object = client_config.get('cloud_retain_head_object')
cloud_allow_read_through = client_config.get('cloud_allow_read_through')
cloud_read_through_restore_days = client_config.get('cloud_read_through_restore_days')
cloud_target_by_bucket = self._normalize_bool_option(
client_config.get('cloud_target_by_bucket'), 'cloud_target_by_bucket')
cloud_target_by_bucket_prefix = client_config.get('cloud_target_by_bucket_prefix')
cloudtier_user = client_config.get('cloudtier_user')
cloud_access_key = cloudtier_user.get('cloud_access_key')
@ -91,6 +114,10 @@ class RGWCloudTier(Task):
tier_config_params += ",allow_read_through=" + cloud_allow_read_through
if (cloud_read_through_restore_days != None):
tier_config_params += ",read_through_restore_days=" + cloud_read_through_restore_days
if (cloud_target_by_bucket != None):
tier_config_params += ",target_by_bucket=" + cloud_target_by_bucket
if (cloud_target_by_bucket_prefix != None):
tier_config_params += ",target_by_bucket_prefix=" + cloud_target_by_bucket_prefix
log.info('Configuring cloud-s3 tier storage class type = %s', cloud_storage_class)

View File

@ -403,6 +403,12 @@ def configure(ctx, config):
cloud_read_through_restore_days = client_rgw_config.get('cloud_read_through_restore_days')
if (cloud_read_through_restore_days != None):
s3tests_conf['s3 cloud']['read_through_restore_days'] = cloud_read_through_restore_days
cloud_target_by_bucket = client_rgw_config.get('cloud_target_by_bucket')
if (cloud_target_by_bucket != None):
s3tests_conf['s3 cloud']['target_by_bucket'] = cloud_target_by_bucket
cloud_target_by_bucket_prefix = client_rgw_config.get('cloud_target_by_bucket_prefix')
if (cloud_target_by_bucket_prefix != None):
s3tests_conf['s3 cloud']['target_by_bucket_prefix'] = cloud_target_by_bucket_prefix
(remote,) = ctx.cluster.only(client).remotes.keys()
conf_fp = BytesIO()