]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/s3: CreateBucket extension for layout type and shard count
authorCasey Bodley <cbodley@redhat.com>
Wed, 8 Jan 2025 19:52:03 +0000 (14:52 -0500)
committerCasey Bodley <cbodley@redhat.com>
Tue, 25 Feb 2025 16:15:57 +0000 (11:15 -0500)
extend s3's CreateBucketConfiguration [1] with a custom BucketIndex element
that can override rgw's default bucket index type and shard count

to create an indexless bucket:
  <CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <BucketIndex>
      <Type>Indexless</Type>
    </BucketIndex>
  </CreateBucketConfiguration>

to create a normal pre-sharded bucket:
  <CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <BucketIndex>
      <Type>Normal</Type>
      <NumShards>1023</NumShards>
    </BucketIndex>
  </CreateBucketConfiguration>

[1] https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html#API_CreateBucket_RequestSyntax

Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/rgw/rgw_rest_s3.cc

index 4548fd92583a533c3929b84f874906e5cec2cc56..e273ed576924ceaeb28a25b7ffa727e1ee2a69d6 100644 (file)
@@ -2485,12 +2485,26 @@ public:
   string location_constraint;
 };
 
+// BucketIndex
+struct RGWCreateBucketIndex : XMLObj {
+  XMLObj* type = nullptr;
+  XMLObj* num_shards = nullptr;
+
+  bool xml_end(const char*) override {
+    type = find_first("Type");
+    num_shards = find_first("NumShards");
+    return true;
+  }
+};
+
 // CreateBucketConfiguration
 struct RGWCreateBucketConfig : XMLObj {
   XMLObj* location_constraint = nullptr;
+  RGWCreateBucketIndex* index = nullptr;
 
   bool xml_end(const char*) override {
     location_constraint = find_first("LocationConstraint");
+    index = static_cast<RGWCreateBucketIndex*>(find_first("BucketIndex"));
     return true;
   }
 };
@@ -2500,6 +2514,8 @@ class RGWCreateBucketParser : public RGWXMLParser {
     using namespace std::string_view_literals;
     if (el == "CreateBucketConfiguration"sv) {
       return new RGWCreateBucketConfig;
+    } else if (el == "BucketIndex"sv) {
+      return new RGWCreateBucketIndex;
     }
     return new XMLObj;
   }
@@ -2562,6 +2578,41 @@ int RGWCreateBucket_ObjStore_S3::get_params(optional_yield y)
       ldpp_dout(this, 10) << "create bucket location constraint: "
           << location_constraint << dendl;
     }
+
+    if (config->index) {
+      if (!config->index->type) {
+        s->err.message = "Missing required element Type in BucketIndex";
+        return -EINVAL;
+      }
+      rgw::BucketIndexType type;
+      if (!parse(config->index->type->get_data(), type)) {
+        s->err.message = "Unknown Type in BucketIndex";
+        return -EINVAL;
+      }
+      createparams.index_type = type;
+
+      if (config->index->num_shards) {
+        if (type != rgw::BucketIndexType::Normal) {
+          s->err.message = "NumShards requires Type to be Normal";
+          return -EINVAL;
+        }
+        auto val = ceph::parse<uint32_t>(config->index->num_shards->get_data());
+        if (!val) {
+          s->err.message = "Failed to parse integer NumShards in BucketIndex";
+          return -EINVAL;
+        }
+        if (*val == 0) {
+          s->err.message = "NumShards must be greater than 0";
+          return -EINVAL;
+        }
+        const auto limit = s->cct->_conf.get_val<uint64_t>("rgw_max_dynamic_shards");
+        if (*val > limit) {
+          s->err.message = fmt::format("NumShards cannot exceed {}", limit);
+          return -EINVAL;
+        }
+        createparams.index_shards = val;
+      }
+    }
   }
 
   size_t pos = location_constraint.find(':');