From 800efa5dba7312e97294ccc3a1730a5ca22b4788 Mon Sep 17 00:00:00 2001 From: Soumya Koduri Date: Thu, 30 Oct 2025 01:30:11 +0530 Subject: [PATCH] rgw/cloud-transition: Include LocationConstraint for non-default regions Add a new tier-config option "location_constraint" to be configured while using AWS non-default regions. Resolves: rhbz#2402662 Signed-off-by: Soumya Koduri (cherry picked from commit 7bca6467c783a7f33209721ea20d728e58daf457) --- doc/radosgw/cloud-restore.rst | 1 + doc/radosgw/cloud-transition.rst | 6 ++++++ src/rgw/driver/rados/rgw_lc_tier.cc | 26 +++++++++++++++++++++++++- src/rgw/driver/rados/rgw_lc_tier.h | 1 + src/rgw/driver/rados/rgw_sal_rados.cc | 2 ++ src/rgw/driver/rados/rgw_zone.cc | 6 ++++++ src/rgw/rgw_zone.cc | 3 ++- src/rgw/rgw_zone_types.h | 11 +++++++++-- 8 files changed, 52 insertions(+), 4 deletions(-) diff --git a/doc/radosgw/cloud-restore.rst b/doc/radosgw/cloud-restore.rst index 234e94e57a6..dc84f41ef58 100644 --- a/doc/radosgw/cloud-restore.rst +++ b/doc/radosgw/cloud-restore.rst @@ -37,6 +37,7 @@ objects as well:: "acls": [ { "type": , "source_id": , "dest_id": } ... ], + "location_constraint": , "target_path": , "target_storage_class": , "multipart_sync_threshold": {object_size}, diff --git a/doc/radosgw/cloud-transition.rst b/doc/radosgw/cloud-transition.rst index d54bca2df51..6c03e159b76 100644 --- a/doc/radosgw/cloud-transition.rst +++ b/doc/radosgw/cloud-transition.rst @@ -47,6 +47,7 @@ Cloud Storage Class Tier Configuration "acls": [ { "type": , "source_id": , "dest_id": } ... ], + "location_constraint": , "target_path": , "target_storage_class": , "multipart_sync_threshold": {object_size}, @@ -111,6 +112,10 @@ Cloud Transition Specific Configurables For example: ``target_path = rgwx-archive-${zonegroup}/`` +* ``location_constraint`` (string) + + Specifies the region where the target bucket will be created on the remote S3 endpoint. For AWS, this location needs to be specified only if the region is other than US East (us-east-1). + * ``target_storage_class`` (string) A string that defines the target storage class to which the object transitions. @@ -196,6 +201,7 @@ For example "access_key": "", "secret": "", "host_style": "path", + "location_constraint": ""; "target_storage_class": "", "target_path": "", "acl_mappings": [], diff --git a/src/rgw/driver/rados/rgw_lc_tier.cc b/src/rgw/driver/rados/rgw_lc_tier.cc index 91ffeb5d2cf..e820bd05c30 100644 --- a/src/rgw/driver/rados/rgw_lc_tier.cc +++ b/src/rgw/driver/rados/rgw_lc_tier.cc @@ -1456,6 +1456,23 @@ static int cloud_tier_create_bucket(RGWLCCloudTierCtx& tier_ctx) { bufferlist out_bl; int ret = 0; pair key(tier_ctx.storage_class, tier_ctx.target_bucket_name); + stringstream ss; + XMLFormatter formatter; + bufferlist bl; + std::string lconstraint; + + struct CreateBucketReq { + std::optional lconstraint; + + explicit CreateBucketReq(std::optional _lconstraint) : lconstraint(_lconstraint) {} + + void dump_xml(Formatter *f) const { + if (lconstraint) { + encode_xml("LocationConstraint", lconstraint, f); + }; + } + } req_enc(lconstraint); + struct CreateBucketResult { std::string code; @@ -1465,9 +1482,16 @@ static int cloud_tier_create_bucket(RGWLCCloudTierCtx& tier_ctx) { } result; ldpp_dout(tier_ctx.dpp, 30) << "Cloud_tier_ctx: creating bucket:" << tier_ctx.target_bucket_name << dendl; - bufferlist bl; string resource = tier_ctx.target_bucket_name; + if (!tier_ctx.location_constraint.empty()) { + req_enc.lconstraint = tier_ctx.location_constraint; + encode_xml("CreateBucketConfiguration", req_enc, &formatter); + + formatter.flush(ss); + bl.append(ss.str()); + } + ret = tier_ctx.conn.send_resource(tier_ctx.dpp, "PUT", resource, nullptr, nullptr, out_bl, &bl, nullptr, null_yield); diff --git a/src/rgw/driver/rados/rgw_lc_tier.h b/src/rgw/driver/rados/rgw_lc_tier.h index 20d6e0675d0..2c7bc89c51f 100644 --- a/src/rgw/driver/rados/rgw_lc_tier.h +++ b/src/rgw/driver/rados/rgw_lc_tier.h @@ -29,6 +29,7 @@ struct RGWLCCloudTierCtx { /* Remote */ RGWRESTConn& conn; + std::string location_constraint; std::string target_bucket_name; std::string target_storage_class; diff --git a/src/rgw/driver/rados/rgw_sal_rados.cc b/src/rgw/driver/rados/rgw_sal_rados.cc index 4fc4dd06e8e..632bb5d8865 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.cc +++ b/src/rgw/driver/rados/rgw_sal_rados.cc @@ -3108,6 +3108,7 @@ int RadosObject::restore_obj_from_cloud(Bucket* bucket, tier_ctx.storage_class = tier->get_storage_class(); tier_ctx.restore_storage_class = rtier->get_rt().restore_storage_class; tier_ctx.tier_type = rtier->get_rt().tier_type; + tier_ctx.location_constraint = rtier->get_rt().t.s3.location_constraint; ldpp_dout(dpp, 20) << "Restoring object(" << get_key() << ") from the cloud endpoint(" << endpoint << ")" << dendl; @@ -3181,6 +3182,7 @@ int RadosObject::transition_to_cloud(Bucket* bucket, tier_ctx.multipart_min_part_size = rtier->get_rt().t.s3.multipart_min_part_size; tier_ctx.multipart_sync_threshold = rtier->get_rt().t.s3.multipart_sync_threshold; tier_ctx.storage_class = tier->get_storage_class(); + tier_ctx.location_constraint = rtier->get_rt().t.s3.location_constraint; ldpp_dout(dpp, 0) << "Transitioning object(" << o.key << ") to the cloud endpoint(" << endpoint << ")" << dendl; diff --git a/src/rgw/driver/rados/rgw_zone.cc b/src/rgw/driver/rados/rgw_zone.cc index 79f97aeb794..34d5fbef41c 100644 --- a/src/rgw/driver/rados/rgw_zone.cc +++ b/src/rgw/driver/rados/rgw_zone.cc @@ -1433,6 +1433,9 @@ int RGWZoneGroupPlacementTierS3::update_params(const JSONFormattable& config) host_style = VirtualStyle; } } + if (config.exists("location_constraint")) { + location_constraint = config["location_constraint"]; + } if (config.exists("target_storage_class")) { target_storage_class = config["target_storage_class"]; } @@ -1492,6 +1495,9 @@ int RGWZoneGroupPlacementTierS3::clear_params(const JSONFormattable& config) /* default */ host_style = PathStyle; } + if (config.exists("location_constraint")) { + location_constraint.clear(); + } if (config.exists("target_storage_class")) { target_storage_class.clear(); } diff --git a/src/rgw/rgw_zone.cc b/src/rgw/rgw_zone.cc index 321ad138526..b1f59c7d873 100644 --- a/src/rgw/rgw_zone.cc +++ b/src/rgw/rgw_zone.cc @@ -962,6 +962,7 @@ void RGWZoneGroupPlacementTierS3::decode_json(JSONObj *obj) } else { host_style = VirtualStyle; } + JSONDecoder::decode_json("location_constraint", location_constraint, obj); JSONDecoder::decode_json("target_storage_class", target_storage_class, obj); JSONDecoder::decode_json("target_path", target_path, obj); JSONDecoder::decode_json("acl_mappings", acl_mappings, obj); @@ -1017,6 +1018,7 @@ void RGWZoneGroupPlacementTierS3::dump(Formatter *f) const encode_json("region", region, f); string s = (host_style == PathStyle ? "path" : "virtual"); encode_json("host_style", s, f); + encode_json("location_constraint", location_constraint, f); encode_json("target_storage_class", target_storage_class, f); encode_json("target_path", target_path, f); encode_json("acl_mappings", acl_mappings, f); @@ -1459,4 +1461,3 @@ int add_zone_to_group(const DoutPrefixProvider* dpp, RGWZoneGroup& zonegroup, } } // namespace rgw - diff --git a/src/rgw/rgw_zone_types.h b/src/rgw/rgw_zone_types.h index 02fc3fe0bed..368eb01b56a 100644 --- a/src/rgw/rgw_zone_types.h +++ b/src/rgw/rgw_zone_types.h @@ -495,6 +495,7 @@ struct RGWZoneGroupPlacementTierS3 { std::string region; HostStyle host_style{PathStyle}; std::string target_storage_class; + std::string location_constraint; /* Should below be bucket/zone specific?? */ std::string target_path; @@ -507,7 +508,7 @@ struct RGWZoneGroupPlacementTierS3 { int clear_params(const JSONFormattable& config); void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); + ENCODE_START(2, 1, bl); encode(endpoint, bl); encode(key, bl); encode(region, bl); @@ -517,11 +518,12 @@ struct RGWZoneGroupPlacementTierS3 { encode(acl_mappings, bl); encode(multipart_sync_threshold, bl); encode(multipart_min_part_size, bl); + encode(location_constraint, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); + DECODE_START(2, bl); decode(endpoint, bl); decode(key, bl); decode(region, bl); @@ -535,6 +537,11 @@ struct RGWZoneGroupPlacementTierS3 { decode(acl_mappings, bl); decode(multipart_sync_threshold, bl); decode(multipart_min_part_size, bl); + + if (struct_v >= 2) { + decode(location_constraint, bl); + } + DECODE_FINISH(bl); } void dump(Formatter *f) const; -- 2.47.3