From: Casey Bodley Date: Wed, 8 Jan 2025 19:52:03 +0000 (-0500) Subject: rgw/s3: CreateBucket extension for layout type and shard count X-Git-Tag: testing/wip-pdonnell-testing-20250226.141530-debug~5^2~3 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=567f6086ce8365bdd9779e0f356cde501c6ccbc6;p=ceph-ci.git rgw/s3: CreateBucket extension for layout type and shard count 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: Indexless to create a normal pre-sharded bucket: Normal 1023 [1] https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html#API_CreateBucket_RequestSyntax Signed-off-by: Casey Bodley --- diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 4548fd92583..e273ed57692 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -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(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(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("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(':');