]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/cloud-transition: Include LocationConstraint for non-default regions
authorSoumya Koduri <skoduri@redhat.com>
Wed, 29 Oct 2025 20:00:11 +0000 (01:30 +0530)
committerSoumya Koduri <skoduri@redhat.com>
Mon, 10 Nov 2025 17:05:54 +0000 (22:35 +0530)
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 <skoduri@redhat.com>
(cherry picked from commit 7bca6467c783a7f33209721ea20d728e58daf457)

doc/radosgw/cloud-restore.rst
doc/radosgw/cloud-transition.rst
src/rgw/driver/rados/rgw_lc_tier.cc
src/rgw/driver/rados/rgw_lc_tier.h
src/rgw/driver/rados/rgw_sal_rados.cc
src/rgw/driver/rados/rgw_zone.cc
src/rgw/rgw_zone.cc
src/rgw/rgw_zone_types.h

index 234e94e57a6dcee7b973386b61f8ea397d9254c0..dc84f41ef585c973d92891539b4773788a4356df 100644 (file)
@@ -37,6 +37,7 @@ objects as well::
       "acls": [ { "type": <id | email | uri>,
                   "source_id": <source_id>,
                   "dest_id": <dest_id> } ... ],
+      "location_constraint": <location-constraint>,
       "target_path": <target_path>,
       "target_storage_class": <target-storage-class>,
       "multipart_sync_threshold": {object_size},
index d54bca2df51b401cb0efaf1083c7dcc6deede97e..6c03e159b7688ed9d57e50aa1c2b3e15f0664f68 100644 (file)
@@ -47,6 +47,7 @@ Cloud Storage Class Tier Configuration
     "acls": [ { "type": <id | email | uri>,
                 "source_id": <source_id>,
                 "dest_id": <dest_id> } ... ],
+    "location_constraint": <location-constraint>,
     "target_path": <target_path>,
     "target_storage_class": <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": [],
index 91ffeb5d2cf63aacdfd28e0cce1ae7e1d0472c2c..e820bd05c30de8fe5bebc404374f309d79f1f4b1 100644 (file)
@@ -1456,6 +1456,23 @@ static int cloud_tier_create_bucket(RGWLCCloudTierCtx& tier_ctx) {
   bufferlist out_bl;
   int ret = 0;
   pair<string, string> key(tier_ctx.storage_class, tier_ctx.target_bucket_name);
+  stringstream ss;
+  XMLFormatter formatter;
+  bufferlist bl;
+  std::string lconstraint;
+
+  struct CreateBucketReq {
+         std::optional<std::string>  lconstraint;
+
+    explicit CreateBucketReq(std::optional<std::string> _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);
 
index 20d6e0675d091503e1f04f0418079c6d7bd6a0a7..2c7bc89c51ffc85af9de20709076a59a359fc784 100644 (file)
@@ -29,6 +29,7 @@ struct RGWLCCloudTierCtx {
 
   /* Remote */
   RGWRESTConn& conn;
+  std::string location_constraint;
   std::string target_bucket_name;
   std::string target_storage_class;
 
index 4fc4dd06e8ee06e51bdda3ab2e3b6aa20d6e2be9..632bb5d88650c5c7bf2e162f8bea79d61d0d9cc1 100644 (file)
@@ -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;
 
index 79f97aeb794107f06911919d16665a4c012c84e3..34d5fbef41c4bb9064957b953cc44b534fde18c3 100644 (file)
@@ -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();
   }
index 321ad138526d61963bc2cc3ab0307fd67742cdbc..b1f59c7d873f0624ccaa2bd7e9ad66649a956374 100644 (file)
@@ -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
-
index 02fc3fe0bed016747f862ed8b5a58a3f97105e32..368eb01b56af5b889df9b83dc35ba3aa4e02e0fa 100644 (file)
@@ -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;