return std::make_unique<D4NFilterObject>(std::move(o), this, filter);
}
-int D4NFilterUser::create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo * pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket_out,
- optional_yield y)
+int D4NFilterBucket::create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y)
{
- std::unique_ptr<Bucket> nb;
- int ret;
-
- ret = next->create_bucket(dpp, b, zonegroup_id, placement_rule, swift_ver_location, pquota_info, policy, attrs, info, ep_objv, exclusive, obj_lock_enabled, existed, req_info, &nb, y);
- if (ret < 0)
- return ret;
-
- Bucket* fb = new D4NFilterBucket(std::move(nb), this, filter);
- bucket_out->reset(fb);
- return 0;
+ return next->create(dpp, params, y);
}
int D4NFilterObject::copy_object(User* user,
FilterUser(std::move(_next)),
filter(_filter) {}
virtual ~D4NFilterUser() = default;
-
- virtual int create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo* pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket,
- optional_yield y) override;
};
class D4NFilterBucket : public FilterBucket {
virtual ~D4NFilterBucket() = default;
virtual std::unique_ptr<Object> get_object(const rgw_obj_key& key) override;
+ virtual int create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y) override;
};
class D4NFilterObject : public FilterObject {
}
int DB::create_bucket(const DoutPrefixProvider *dpp,
- const RGWUserInfo& owner, rgw_bucket& bucket,
- const string& zonegroup_id,
+ const rgw_user& owner, const rgw_bucket& bucket,
+ const std::string& zonegroup_id,
const rgw_placement_rule& placement_rule,
- const string& swift_ver_location,
- const RGWQuotaInfo * pquota_info,
- map<std::string, bufferlist>& attrs,
- RGWBucketInfo& info,
- obj_version *pobjv,
+ const std::map<std::string, bufferlist>& attrs,
+ const std::optional<std::string>& swift_ver_location,
+ const std::optional<RGWQuotaInfo>& quota,
+ std::optional<ceph::real_time> creation_time,
obj_version *pep_objv,
- real_time creation_time,
- rgw_bucket *pmaster_bucket,
- uint32_t *pmaster_num_shards,
- optional_yield y,
- bool exclusive)
+ RGWBucketInfo& info,
+ optional_yield y)
{
/*
* XXX: Simple creation for now.
orig_info.bucket.name = bucket.name;
ret = get_bucket_info(dpp, string("name"), "", orig_info, nullptr, nullptr, nullptr);
- if (!ret && !orig_info.owner.id.empty() && exclusive) {
+ if (!ret && !orig_info.owner.id.empty()) {
/* already exists. Return the old info */
-
info = std::move(orig_info);
return ret;
}
RGWObjVersionTracker& objv_tracker = info.objv_tracker;
-
objv_tracker.read_version.clear();
+ objv_tracker.generate_new_write_ver(cct);
- if (pobjv) {
- objv_tracker.write_version = *pobjv;
- } else {
- objv_tracker.generate_new_write_ver(cct);
- }
params.op.bucket.bucket_version = objv_tracker.write_version;
objv_tracker.read_version = params.op.bucket.bucket_version;
- uint64_t bid = next_bucket_id();
- string s = getDBname() + "." + std::to_string(bid);
- bucket.marker = bucket.bucket_id = s;
-
info.bucket = bucket;
- info.owner = owner.user_id;
+ if (info.bucket.marker.empty()) {
+ uint64_t bid = next_bucket_id();
+ string s = getDBname() + "." + std::to_string(bid);
+ info.bucket.marker = info.bucket.bucket_id = s;
+ }
+
+ info.owner = owner;
info.zonegroup = zonegroup_id;
info.placement_rule = placement_rule;
- info.swift_ver_location = swift_ver_location;
- info.swift_versioning = (!swift_ver_location.empty());
+ if (swift_ver_location) {
+ info.swift_ver_location = *swift_ver_location;
+ }
+ info.swift_versioning = swift_ver_location.has_value();
info.requester_pays = false;
- if (real_clock::is_zero(creation_time)) {
- info.creation_time = ceph::real_clock::now();
+ if (creation_time) {
+ info.creation_time = *creation_time;
} else {
- info.creation_time = creation_time;
+ info.creation_time = ceph::real_clock::now();
}
- if (pquota_info) {
- info.quota = *pquota_info;
+ if (quota) {
+ info.quota = *quota;
}
params.op.bucket.info = info;
params.op.bucket.bucket_attrs = attrs;
params.op.bucket.mtime = ceph::real_time();
- params.op.user.uinfo.user_id.id = owner.user_id.id;
+ params.op.user.uinfo.user_id.id = owner.id;
ret = ProcessOp(dpp, "InsertBucket", ¶ms);
RGWBucketInfo& info, rgw::sal::Attrs* pattrs, ceph::real_time* pmtime,
obj_version* pbucket_version);
int create_bucket(const DoutPrefixProvider *dpp,
- const RGWUserInfo& owner, rgw_bucket& bucket,
+ const rgw_user& owner, const rgw_bucket& bucket,
const std::string& zonegroup_id,
const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo * pquota_info,
- std::map<std::string, bufferlist>& attrs,
- RGWBucketInfo& info,
- obj_version *pobjv,
+ const std::map<std::string, bufferlist>& attrs,
+ const std::optional<std::string>& swift_ver_location,
+ const std::optional<RGWQuotaInfo>& quota,
+ std::optional<ceph::real_time> creation_time,
obj_version *pep_objv,
- real_time creation_time,
- rgw_bucket *pmaster_bucket,
- uint32_t *pmaster_num_shards,
- optional_yield y,
- bool exclusive);
+ RGWBucketInfo& info,
+ optional_yield y);
int next_bucket_id() { return ++max_bucket_id; };
struct DBOpParams params = GlobalParams;
int ret = -1;
RGWBucketInfo info;
- RGWUserInfo owner;
+ rgw_user owner;
rgw_bucket bucket;
obj_version objv;
rgw_placement_rule rule;
map<std::string, bufferlist> attrs;
- owner.user_id.id = "user_id1";
+ owner.id = "user_id1";
bucket.name = "bucket1";
bucket.tenant = "tenant";
- objv.ver = 2;
- objv.tag = "write_tag";
-
rule.name = "rule1";
rule.storage_class = "sc1";
- ret = db->create_bucket(dpp, owner, bucket, "zid", rule, "swift_ver", NULL,
- attrs, info, &objv, NULL, bucket_mtime, NULL, NULL,
- null_yield, false);
+ ret = db->create_bucket(dpp, owner, bucket, "zid", rule, attrs, "swift_ver",
+ std::nullopt, bucket_mtime, nullptr, info, null_yield);
ASSERT_EQ(ret, 0);
bucket.name = "bucket2";
- ret = db->create_bucket(dpp, owner, bucket, "zid", rule, "swift_ver", NULL,
- attrs, info, &objv, NULL, bucket_mtime, NULL, NULL,
- null_yield, false);
+ ret = db->create_bucket(dpp, owner, bucket, "zid", rule, attrs, "swift_ver",
+ std::nullopt, bucket_mtime, nullptr, info, null_yield);
ASSERT_EQ(ret, 0);
bucket.name = "bucket3";
- ret = db->create_bucket(dpp, owner, bucket, "zid", rule, "swift_ver", NULL,
- attrs, info, &objv, NULL, bucket_mtime, NULL, NULL,
- null_yield, false);
+ ret = db->create_bucket(dpp, owner, bucket, "zid", rule, attrs, "swift_ver",
+ std::nullopt, bucket_mtime, nullptr, info, null_yield);
ASSERT_EQ(ret, 0);
bucket.name = "bucket4";
- ret = db->create_bucket(dpp, owner, bucket, "zid", rule, "swift_ver", NULL,
- attrs, info, &objv, NULL, bucket_mtime, NULL, NULL,
- null_yield, false);
+ ret = db->create_bucket(dpp, owner, bucket, "zid", rule, attrs, "swift_ver",
+ std::nullopt, bucket_mtime, nullptr, info, null_yield);
ASSERT_EQ(ret, 0);
bucket.name = "bucket5";
- ret = db->create_bucket(dpp, owner, bucket, "zid", rule, "swift_ver", NULL,
- attrs, info, &objv, NULL, bucket_mtime, NULL, NULL,
- null_yield, false);
+ ret = db->create_bucket(dpp, owner, bucket, "zid", rule, attrs, "swift_ver",
+ std::nullopt, bucket_mtime, nullptr, info, null_yield);
ASSERT_EQ(ret, 0);
}
ASSERT_EQ(binfo.bucket.name, "bucket2");
ASSERT_EQ(binfo.bucket.tenant, "tenant");
ASSERT_EQ(binfo.owner.id, "user_id1");
- ASSERT_EQ(binfo.objv_tracker.read_version.ver, 2);
- ASSERT_EQ(binfo.objv_tracker.read_version.tag, "write_tag");
+ ASSERT_EQ(binfo.objv_tracker.read_version.ver, 1);
+ ASSERT_FALSE(binfo.objv_tracker.read_version.tag.empty());
ASSERT_EQ(binfo.zonegroup, "zid");
ASSERT_EQ(binfo.creation_time, bucket_mtime);
ASSERT_EQ(binfo.placement_rule.name, "rule1");
ASSERT_EQ(binfo.placement_rule.storage_class, "sc1");
- ASSERT_EQ(objv.ver, 2);
- ASSERT_EQ(objv.tag, "write_tag");
+ ASSERT_EQ(objv.ver, 1);
+ ASSERT_FALSE(objv.tag.empty());
marker1 = binfo.bucket.marker;
}
ret = db->update_bucket(dpp, "owner", info, false, &user, nullptr, &bucket_mtime, nullptr);
ASSERT_EQ(ret, 0);
- ASSERT_EQ(info.objv_tracker.read_version.ver, 3);
+ ASSERT_EQ(info.objv_tracker.read_version.ver, 2);
}
TEST_F(DBStoreTest, ListAllBuckets) {
const std::string MP_OBJ_PART_FMT = "{:0>5}";
const std::string MP_OBJ_HEAD_NAME = MP_OBJ_PART_PFX + "00000";
-static int decode_policy(CephContext* cct,
- bufferlist& bl,
- RGWAccessControlPolicy* policy)
-{
- auto iter = bl.cbegin();
- try {
- policy->decode(iter);
- } catch (buffer::error& err) {
- ldout(cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
- return -EIO;
- }
- if (cct->_conf->subsys.should_gather<ceph_subsys_rgw, 15>()) {
- ldout(cct, 15) << __func__ << " POSIX Read AccessControlPolicy";
- RGWAccessControlPolicy_S3* s3policy = static_cast<RGWAccessControlPolicy_S3 *>(policy);
- s3policy->to_xml(*_dout);
- *_dout << dendl;
- }
- return 0;
-}
-
-static int rgw_op_get_bucket_policy_from_attr(const DoutPrefixProvider* dpp,
- POSIXDriver* driver,
- User* user,
- Attrs& bucket_attrs,
- RGWAccessControlPolicy* policy,
- optional_yield y)
-{
- auto aiter = bucket_attrs.find(RGW_ATTR_ACL);
-
- if (aiter != bucket_attrs.end()) {
- int ret = decode_policy(driver->ctx(), aiter->second, policy);
- if (ret < 0)
- return ret;
- } else {
- ldout(driver->ctx(), 0) << "WARNING: couldn't find acl header for bucket, generating default" << dendl;
- /* object exists, but policy is broken */
- int r = user->load_user(dpp, y);
- if (r < 0)
- return r;
-
- policy->create_default(user->get_id(), user->get_display_name());
- }
- return 0;
-}
-
static inline bool get_attr(Attrs& attrs, const char* name, bufferlist& bl)
{
auto iter = attrs.find(name);
return 0;
}
-int POSIXUser::create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo * pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& binfo,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket_out,
- optional_yield y)
-{
- /* Check for existence */
- {
- std::unique_ptr<rgw::sal::Bucket> bucket;
+int POSIXBucket::create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y)
+{
+ ceph_assert(owner);
+ info.owner = owner->get_id();
- int ret = driver->load_bucket(dpp, this, b, &bucket, y);
- if (ret >= 0) {
- *existed = true;
- // Bucket exists. Check owner comparison
- if (bucket->get_info().owner.compare(this->get_id()) != 0) {
- return -EEXIST;
- }
- // Don't allow changes to ACL policy
- RGWAccessControlPolicy old_policy(driver->ctx());
- ret = rgw_op_get_bucket_policy_from_attr(
- dpp, driver, this, bucket->get_attrs(), &old_policy, y);
- if (ret >= 0 && old_policy != policy) {
- bucket_out->swap(bucket);
- return -EEXIST;
- }
- } else {
- *existed = false;
- }
- }
+ info.bucket.marker = params.marker;
+ info.bucket.bucket_id = params.bucket_id;
- binfo.bucket = b;
- binfo.owner = get_id();
- binfo.zonegroup = zonegroup_id;
- binfo.placement_rule = placement_rule;
- binfo.swift_ver_location = swift_ver_location;
- binfo.swift_versioning = (!swift_ver_location.empty());
- binfo.requester_pays = false;
- binfo.creation_time = ceph::real_clock::now();
- if (pquota_info) {
- binfo.quota = *pquota_info;
+ info.zonegroup = params.zonegroup_id;
+ info.placement_rule = params.placement_rule;
+ info.swift_versioning = params.swift_ver_location.has_value();
+ if (params.swift_ver_location) {
+ info.swift_ver_location = *params.swift_ver_location;
+ }
+ if (params.obj_lock_enabled) {
+ info.flags |= BUCKET_VERSIONED | BUCKET_OBJ_LOCK_ENABLED;
+ }
+ info.requester_pays = false;
+ if (params.creation_time) {
+ info.creation_time = *params.creation_time;
+ } else {
+ info.creation_time = ceph::real_clock::now();
+ }
+ if (params.quota) {
+ info.quota = *params.quota;
}
- POSIXBucket* fb = new POSIXBucket(driver, driver->get_root_fd(), binfo, this);
-
- int ret = fb->set_attrs(attrs);
+ int ret = set_attrs(attrs);
if (ret < 0) {
- delete fb;
- return ret;
+ return ret;
}
- ret = fb->create(dpp, y, existed);
+ bool existed = false;
+ ret = create(dpp, y, &existed);
if (ret < 0) {
- delete fb;
- return ret;
+ return ret;
}
- bucket_out->reset(fb);
return 0;
}
} else if (existed != nullptr) {
*existed = true;
}
- return ret;
+ return -ret;
}
return write_attrs(dpp, y);
const std::string& marker, const std::string& end_marker,
uint64_t max, bool need_stats, BucketList& buckets,
optional_yield y) override;
- virtual int create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo* pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket,
- optional_yield y) override;
virtual Attrs& get_attrs() override { return next->get_attrs(); }
virtual void set_attrs(Attrs& _attrs) override { next->set_attrs(_attrs); }
virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) override;
bool keep_index_consistent,
optional_yield y,
const DoutPrefixProvider *dpp) override;
+ virtual int create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y) override;
virtual int load_bucket(const DoutPrefixProvider* dpp, optional_yield y) override;
virtual RGWAccessControlPolicy& get_acl(void) override { return acls; }
virtual int set_acl(const DoutPrefixProvider* dpp, RGWAccessControlPolicy& acl,
*bucket_id = buf;
}
-int RGWRados::create_bucket(const RGWUserInfo& owner, rgw_bucket& bucket,
- const string& zonegroup_id,
+int RGWRados::create_bucket(const DoutPrefixProvider* dpp,
+ optional_yield y,
+ const rgw_bucket& bucket,
+ const rgw_user& owner,
+ const std::string& zonegroup_id,
const rgw_placement_rule& placement_rule,
- const string& swift_ver_location,
+ const RGWZonePlacementInfo* zone_placement,
+ const std::map<std::string, bufferlist>& attrs,
bool obj_lock_enabled,
- const RGWQuotaInfo * pquota_info,
- map<std::string, bufferlist>& attrs,
- RGWBucketInfo& info,
- obj_version *pobjv,
- obj_version *pep_objv,
- real_time creation_time,
- const rgw_bucket* pmaster_bucket,
- optional_yield y,
- const DoutPrefixProvider *dpp,
- bool exclusive)
+ const std::optional<std::string>& swift_ver_location,
+ const std::optional<RGWQuotaInfo>& quota,
+ std::optional<ceph::real_time> creation_time,
+ obj_version* pep_objv,
+ RGWBucketInfo& info)
{
-#define MAX_CREATE_RETRIES 20 /* need to bound retries */
- rgw_placement_rule selected_placement_rule;
- RGWZonePlacementInfo rule_info;
+ int ret = 0;
+#define MAX_CREATE_RETRIES 20 /* need to bound retries */
for (int i = 0; i < MAX_CREATE_RETRIES; i++) {
- int ret = 0;
- ret = svc.zone->select_bucket_placement(dpp, owner, zonegroup_id, placement_rule,
- &selected_placement_rule, &rule_info, y);
- if (ret < 0)
- return ret;
-
- if (!pmaster_bucket) {
- create_bucket_id(&bucket.marker);
- bucket.bucket_id = bucket.marker;
- } else {
- bucket.marker = pmaster_bucket->marker;
- bucket.bucket_id = pmaster_bucket->bucket_id;
- }
-
RGWObjVersionTracker& objv_tracker = info.objv_tracker;
-
objv_tracker.read_version.clear();
+ objv_tracker.generate_new_write_ver(cct);
- if (pobjv) {
- objv_tracker.write_version = *pobjv;
+ if (bucket.marker.empty()) {
+ create_bucket_id(&info.bucket.marker);
+ info.bucket.bucket_id = info.bucket.marker;
} else {
- objv_tracker.generate_new_write_ver(cct);
+ info.bucket = bucket;
}
- info.bucket = bucket;
- info.owner = owner.user_id;
+ info.owner = owner;
info.zonegroup = zonegroup_id;
- info.placement_rule = selected_placement_rule;
- info.swift_ver_location = swift_ver_location;
- info.swift_versioning = (!swift_ver_location.empty());
+ info.placement_rule = placement_rule;
+ info.swift_versioning = swift_ver_location.has_value();
+ if (swift_ver_location) {
+ info.swift_ver_location = *swift_ver_location;
+ }
if (obj_lock_enabled) {
info.flags |= BUCKET_VERSIONED | BUCKET_OBJ_LOCK_ENABLED;
}
- init_default_bucket_layout(cct, info.layout, svc.zone->get_zone(),
- rule_info.index_type);
+ if (zone_placement) {
+ init_default_bucket_layout(cct, info.layout, svc.zone->get_zone(),
+ zone_placement->index_type);
+ }
info.requester_pays = false;
- if (real_clock::is_zero(creation_time)) {
- info.creation_time = ceph::real_clock::now();
+ if (creation_time) {
+ info.creation_time = *creation_time;
} else {
- info.creation_time = creation_time;
+ info.creation_time = ceph::real_clock::now();
}
- if (pquota_info) {
- info.quota = *pquota_info;
+ if (quota) {
+ info.quota = *quota;
}
- int r = svc.bi->init_index(dpp, info, info.layout.current_index);
- if (r < 0) {
- return r;
+ if (zone_placement) {
+ ret = svc.bi->init_index(dpp, info, info.layout.current_index);
+ if (ret < 0) {
+ return ret;
+ }
}
+ constexpr bool exclusive = true;
ret = put_linked_bucket_info(info, exclusive, ceph::real_time(), pep_objv, &attrs, true, dpp, y);
if (ret == -ECANCELED) {
ret = -EEXIST;
if (ret == -EEXIST) {
/* we need to reread the info and return it, caller will have a use for it */
RGWBucketInfo orig_info;
- r = get_bucket_info(&svc, bucket.tenant, bucket.name, orig_info, NULL, y, NULL);
+ int r = get_bucket_info(&svc, bucket.tenant, bucket.name, orig_info, NULL, y, NULL);
if (r < 0) {
if (r == -ENOENT) {
continue;
/* only remove it if it's a different bucket instance */
if (orig_info.bucket.bucket_id != bucket.bucket_id) {
- int r = svc.bi->clean_index(dpp, info, info.layout.current_index);
- if (r < 0) {
- ldpp_dout(dpp, 0) << "WARNING: could not remove bucket index (r=" << r << ")" << dendl;
- }
+ if (zone_placement) {
+ r = svc.bi->clean_index(dpp, info, info.layout.current_index);
+ if (r < 0) {
+ ldpp_dout(dpp, 0) << "WARNING: could not remove bucket index (r=" << r << ")" << dendl;
+ }
+ }
r = ctl.bucket->remove_bucket_instance_info(info.bucket, info, y, dpp);
if (r < 0) {
ldpp_dout(dpp, 0) << "WARNING: " << __func__ << "(): failed to remove bucket instance info: bucket instance=" << info.bucket.get_key() << ": r=" << r << dendl;
bool get_obj_data_pool(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_pool *pool);
bool obj_to_raw(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_raw_obj *raw_obj);
- int create_bucket(const RGWUserInfo& owner, rgw_bucket& bucket,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- bool obj_lock_enabled,
- const RGWQuotaInfo * pquota_info,
- std::map<std::string,bufferlist>& attrs,
- RGWBucketInfo& bucket_info,
- obj_version *pobjv,
- obj_version *pep_objv,
- ceph::real_time creation_time,
- const rgw_bucket *master_bucket,
- optional_yield y,
- const DoutPrefixProvider *dpp,
- bool exclusive = true);
+ int create_bucket(const DoutPrefixProvider* dpp,
+ optional_yield y,
+ const rgw_bucket& bucket,
+ const rgw_user& owner,
+ const std::string& zonegroup_id,
+ const rgw_placement_rule& placement_rule,
+ const RGWZonePlacementInfo* zone_placement,
+ const std::map<std::string, bufferlist>& attrs,
+ bool obj_lock_enabled,
+ const std::optional<std::string>& swift_ver_location,
+ const std::optional<RGWQuotaInfo>& quota,
+ std::optional<ceph::real_time> creation_time,
+ obj_version* pep_objv,
+ RGWBucketInfo& info);
RGWCoroutinesManagerRegistry *get_cr_registry() { return cr_registry; }
return 0;
}
-int RadosUser::create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo * pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket_out,
- optional_yield y)
-{
- int ret;
- bufferlist in_data;
- RGWBucketInfo master_info;
- rgw_bucket* pmaster_bucket = nullptr;
- real_time creation_time;
- std::unique_ptr<Bucket> bucket;
- obj_version objv,* pobjv = NULL;
-
- /* If it exists, look it up; otherwise create it */
- ret = store->load_bucket(dpp, this, b, &bucket, y);
- if (ret < 0 && ret != -ENOENT)
- return ret;
-
- if (ret != -ENOENT) {
- *existed = true;
- } else {
- bucket = std::unique_ptr<Bucket>(new RadosBucket(store, b, this));
- *existed = false;
- bucket->set_attrs(attrs);
- }
-
- if (!store->svc()->zone->is_meta_master()) {
- JSONParser jp;
- ret = store->forward_request_to_master(dpp, this, NULL, in_data, &jp, req_info, y);
- if (ret < 0) {
- return ret;
- }
-
- JSONDecoder::decode_json("entry_point_object_ver", ep_objv, &jp);
- JSONDecoder::decode_json("object_ver", objv, &jp);
- JSONDecoder::decode_json("bucket_info", master_info, &jp);
- ldpp_dout(dpp, 20) << "parsed: objv.tag=" << objv.tag << " objv.ver=" << objv.ver << dendl;
- std::time_t ctime = ceph::real_clock::to_time_t(master_info.creation_time);
- ldpp_dout(dpp, 20) << "got creation time: << " << std::put_time(std::localtime(&ctime), "%F %T") << dendl;
- pmaster_bucket= &master_info.bucket;
- creation_time = master_info.creation_time;
- pobjv = &objv;
- obj_lock_enabled = master_info.obj_lock_enabled();
- }
-
- std::string zid = zonegroup_id;
- if (zid.empty()) {
- zid = store->svc()->zone->get_zonegroup().get_id();
- }
-
- if (*existed) {
- rgw_placement_rule selected_placement_rule;
- ret = store->svc()->zone->select_bucket_placement(dpp, this->get_info(),
- zid, placement_rule,
- &selected_placement_rule, nullptr, y);
- if (selected_placement_rule != info.placement_rule) {
- ret = -EEXIST;
- bucket_out->swap(bucket);
- return ret;
- }
- } else {
-
- ret = store->getRados()->create_bucket(this->get_info(), bucket->get_key(),
- zid, placement_rule, swift_ver_location,
- obj_lock_enabled, pquota_info,
- attrs, info, pobjv, &ep_objv, creation_time,
- pmaster_bucket, y, dpp, exclusive);
- if (ret == -EEXIST) {
- *existed = true;
- /* bucket already existed, might have raced with another bucket creation,
- * or might be partial bucket creation that never completed. Read existing
- * bucket info, verify that the reported bucket owner is the current user.
- * If all is ok then update the user's list of buckets. Otherwise inform
- * client about a name conflict.
- */
- if (info.owner.compare(this->get_id()) != 0) {
- return -EEXIST;
- }
- ret = 0;
- } else if (ret != 0) {
- return ret;
+int RadosBucket::create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y)
+{
+ ceph_assert(owner);
+ const rgw_user& owner_id = owner->get_id();
+
+ rgw_bucket key = get_key();
+ key.marker = params.marker;
+ key.bucket_id = params.bucket_id;
+
+ int ret = store->getRados()->create_bucket(
+ dpp, y, key, owner_id, params.zonegroup_id,
+ params.placement_rule, params.zone_placement, params.attrs,
+ params.obj_lock_enabled, params.swift_ver_location,
+ params.quota, params.creation_time, &bucket_version, info);
+
+ bool existed = false;
+ if (ret == -EEXIST) {
+ existed = true;
+ /* bucket already existed, might have raced with another bucket creation,
+ * or might be partial bucket creation that never completed. Read existing
+ * bucket info, verify that the reported bucket owner is the current user.
+ * If all is ok then update the user's list of buckets. Otherwise inform
+ * client about a name conflict.
+ */
+ if (info.owner != owner_id) {
+ return -ERR_BUCKET_EXISTS;
}
+ ret = 0;
+ } else if (ret != 0) {
+ return ret;
}
- bucket->set_version(ep_objv);
- bucket->get_info() = info;
-
- RadosBucket* rbucket = static_cast<RadosBucket*>(bucket.get());
- ret = rbucket->link(dpp, this, y, false);
- if (ret && !*existed && ret != -EEXIST) {
+ ret = link(dpp, owner, y, false);
+ if (ret && !existed && ret != -EEXIST) {
/* if it exists (or previously existed), don't remove it! */
- ret = rbucket->unlink(dpp, this, y);
+ ret = unlink(dpp, owner, y);
if (ret < 0) {
ldpp_dout(dpp, 0) << "WARNING: failed to unlink bucket: ret=" << ret
<< dendl;
}
- } else if (ret == -EEXIST || (ret == 0 && *existed)) {
+ } else if (ret == -EEXIST || (ret == 0 && existed)) {
ret = -ERR_BUCKET_EXISTS;
}
- bucket_out->swap(bucket);
-
return ret;
}
int list_buckets(const DoutPrefixProvider* dpp, const std::string& marker, const std::string& end_marker,
uint64_t max, bool need_stats, BucketList& buckets,
optional_yield y) override;
- virtual int create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo * pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket,
- optional_yield y) override;
virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) override;
virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y) override;
virtual int read_stats(const DoutPrefixProvider *dpp,
DoutPrefixProvider *dpp) override;
virtual RGWAccessControlPolicy& get_acl(void) override { return acls; }
virtual int set_acl(const DoutPrefixProvider* dpp, RGWAccessControlPolicy& acl, optional_yield y) override;
+ int create(const DoutPrefixProvider* dpp, const CreateParams& params,
+ optional_yield y) override;
virtual int load_bucket(const DoutPrefixProvider* dpp, optional_yield y) override;
virtual int read_stats(const DoutPrefixProvider *dpp,
const bucket_index_layout_generation& idx_layout,
return writer.remove(dpp, y);
}
+auto find_zone_placement(const DoutPrefixProvider* dpp,
+ const RGWZoneParams& info,
+ const rgw_placement_rule& rule)
+ -> const RGWZonePlacementInfo*
+{
+ auto i = info.placement_pools.find(rule.name);
+ if (i == info.placement_pools.end()) {
+ ldpp_dout(dpp, 0) << "ERROR: This zone does not contain placement rule "
+ << rule.name << dendl;
+ return nullptr;
+ }
+
+ const std::string& storage_class = rule.get_storage_class();
+ if (!i->second.storage_class_exists(storage_class)) {
+ ldpp_dout(dpp, 5) << "ERROR: The zone placement for rule " << rule.name
+ << " does not contain storage class " << storage_class << dendl;
+ return nullptr;
+ }
+
+ return &i->second;
+}
static int read_or_create_default_zone(const DoutPrefixProvider* dpp,
optional_yield y,
sal::ConfigStore* cfgstore, const RGWZoneParams& info,
sal::ZoneWriter& writer);
+/// Return the zone placement corresponding to the given rule, or nullptr.
+auto find_zone_placement(const DoutPrefixProvider* dpp,
+ const RGWZoneParams& info,
+ const rgw_placement_rule& rule)
+ -> const RGWZonePlacementInfo*;
+
/// Global state about the site configuration. Initialized once during
/// startup and may be reinitialized by RGWRealmReloader, but is otherwise
s->bucket_acl = std::make_unique<RGWAccessControlPolicy>(s->cct);
}
+ const RGWZoneGroup& zonegroup = s->penv.site->get_zonegroup();
+
/* check if copy source is within the current domain */
if (!s->src_bucket_name.empty()) {
std::unique_ptr<rgw::sal::Bucket> src_bucket;
rgw_bucket(s->src_tenant_name, s->src_bucket_name),
&src_bucket, y);
if (ret == 0) {
- string& zonegroup = src_bucket->get_info().zonegroup;
- s->local_source = driver->get_zone()->get_zonegroup().equals(zonegroup);
+ s->local_source = zonegroup.equals(src_bucket->get_info().zonegroup);
}
}
s->bucket_owner = s->bucket_acl->get_owner();
- std::unique_ptr<rgw::sal::ZoneGroup> zonegroup;
- int r = driver->get_zonegroup(s->bucket->get_info().zonegroup, &zonegroup);
- if (!r) {
- s->zonegroup_endpoint = zonegroup->get_endpoint();
- s->zonegroup_name = zonegroup->get_name();
- }
- if (r < 0 && ret == 0) {
- ret = r;
- }
+ s->zonegroup_endpoint = rgw::get_zonegroup_endpoint(zonegroup);
+ s->zonegroup_name = zonegroup.get_name();
- if (!driver->get_zone()->get_zonegroup().equals(s->bucket->get_info().zonegroup)) {
+ if (!zonegroup.equals(s->bucket->get_info().zonegroup)) {
ldpp_dout(dpp, 0) << "NOTICE: request for data in a different zonegroup ("
<< s->bucket->get_info().zonegroup << " != "
- << driver->get_zone()->get_zonegroup().get_id() << ")" << dendl;
+ << zonegroup.get_id() << ")" << dendl;
/* we now need to make sure that the operation actually requires copy source, that is
* it's a copy operation
*/
}
}
+static int select_bucket_placement(const DoutPrefixProvider* dpp,
+ const RGWZoneGroup& zonegroup,
+ const RGWUserInfo& user,
+ rgw_placement_rule& rule)
+{
+ std::string_view selected = "requested";
+
+ // select placement: requested rule > user default > zonegroup default
+ if (rule.name.empty()) {
+ selected = "user-default";
+ rule.inherit_from(user.default_placement);
+ if (rule.name.empty()) {
+ selected = "zonegroup-default";
+ rule.inherit_from(zonegroup.default_placement);
+ if (rule.name.empty()) {
+ ldpp_dout(dpp, 0) << "ERROR: misconfigured zonegroup " << zonegroup.id
+ << ", default placement should not be empty" << dendl;
+ return -ERR_ZONEGROUP_DEFAULT_PLACEMENT_MISCONFIGURATION;
+ }
+ }
+ }
+
+ // look up the zonegroup placement target
+ auto target = zonegroup.placement_targets.find(rule.name);
+ if (target == zonegroup.placement_targets.end()) {
+ ldpp_dout(dpp, 0) << "could not find " << selected << " placement target "
+ << rule.name << " within zonegroup" << dendl;
+ return -ERR_INVALID_LOCATION_CONSTRAINT;
+ }
+
+ // check the user's permission tags
+ if (!target->second.user_permitted(user.placement_tags)) {
+ ldpp_dout(dpp, 0) << "user not permitted to use placement rule "
+ << target->first << dendl;
+ return -EPERM;
+ }
+
+ ldpp_dout(dpp, 20) << "using " << selected << " placement target "
+ << rule.name << dendl;
+ return 0;
+}
void RGWCreateBucket::execute(optional_yield y)
{
if (op_ret < 0)
return;
- if (!relaxed_region_enforcement &&
- !location_constraint.empty() &&
- !driver->get_zone()->has_zonegroup_api(location_constraint)) {
- ldpp_dout(this, 0) << "location constraint (" << location_constraint << ")"
- << " can't be found." << dendl;
+ const rgw::SiteConfig& site = *s->penv.site;
+ const std::optional<RGWPeriod>& period = site.get_period();
+ const RGWZoneGroup& my_zonegroup = site.get_zonegroup();
+
+ if (s->system_request) {
+ // allow system requests to override the target zonegroup. for forwarded
+ // requests, we'll create the bucket for the originating zonegroup
+ createparams.zonegroup_id = s->info.args.get(RGW_SYS_PARAM_PREFIX "zonegroup");
+ }
+
+ const RGWZoneGroup* bucket_zonegroup = &my_zonegroup;
+ if (createparams.zonegroup_id.empty()) {
+ // default to the local zonegroup
+ createparams.zonegroup_id = my_zonegroup.id;
+ } else if (period) {
+ auto z = period->period_map.zonegroups.find(createparams.zonegroup_id);
+ if (z == period->period_map.zonegroups.end()) {
+ ldpp_dout(this, 0) << "could not find zonegroup "
+ << createparams.zonegroup_id << " in current period" << dendl;
+ op_ret = -ENOENT;
+ return;
+ }
+ bucket_zonegroup = &z->second;
+ } else if (createparams.zonegroup_id != my_zonegroup.id) {
+ ldpp_dout(this, 0) << "zonegroup does not match current zonegroup "
+ << createparams.zonegroup_id << dendl;
+ op_ret = -ENOENT;
+ return;
+ }
+
+ // validate the LocationConstraint
+ if (!location_constraint.empty() && !relaxed_region_enforcement) {
+ // on the master zonegroup, allow any valid api_name. otherwise it has to
+ // match the bucket's zonegroup
+ if (period && my_zonegroup.is_master) {
+ if (!period->period_map.zonegroups_by_api.count(location_constraint)) {
+ ldpp_dout(this, 0) << "location constraint (" << location_constraint
+ << ") can't be found." << dendl;
+ op_ret = -ERR_INVALID_LOCATION_CONSTRAINT;
+ s->err.message = "The specified location-constraint is not valid";
+ return;
+ }
+ } else if (bucket_zonegroup->api_name != location_constraint) {
+ ldpp_dout(this, 0) << "location constraint (" << location_constraint
+ << ") doesn't match zonegroup (" << bucket_zonegroup->api_name
+ << ')' << dendl;
op_ret = -ERR_INVALID_LOCATION_CONSTRAINT;
s->err.message = "The specified location-constraint is not valid";
return;
+ }
}
- if (!relaxed_region_enforcement && !driver->get_zone()->get_zonegroup().is_master_zonegroup() && !location_constraint.empty() &&
- driver->get_zone()->get_zonegroup().get_api_name() != location_constraint) {
- ldpp_dout(this, 0) << "location constraint (" << location_constraint << ")"
- << " doesn't match zonegroup" << " (" << driver->get_zone()->get_zonegroup().get_api_name() << ")"
- << dendl;
- op_ret = -ERR_INVALID_LOCATION_CONSTRAINT;
- s->err.message = "The specified location-constraint is not valid";
+ // select and validate the placement target
+ op_ret = select_bucket_placement(this, *bucket_zonegroup, s->user->get_info(),
+ createparams.placement_rule);
+ if (op_ret < 0) {
return;
}
- std::set<std::string> names;
- driver->get_zone()->get_zonegroup().get_placement_target_names(names);
- if (!placement_rule.name.empty() &&
- !names.count(placement_rule.name)) {
- ldpp_dout(this, 0) << "placement target (" << placement_rule.name << ")"
- << " doesn't exist in the placement targets of zonegroup"
- << " (" << driver->get_zone()->get_zonegroup().get_api_name() << ")" << dendl;
- op_ret = -ERR_INVALID_LOCATION_CONSTRAINT;
- s->err.message = "The specified placement target does not exist";
- return;
+ if (bucket_zonegroup == &my_zonegroup) {
+ // look up the zone placement pool
+ createparams.zone_placement = rgw::find_zone_placement(
+ this, site.get_zone_params(), createparams.placement_rule);
+ if (!createparams.zone_placement) {
+ op_ret = -ERR_INVALID_LOCATION_CONSTRAINT;
+ return;
+ }
}
- /* we need to make sure we read bucket info, it's not read before for this
- * specific request */
- {
- std::unique_ptr<rgw::sal::Bucket> tmp_bucket;
- op_ret = driver->load_bucket(this, s->user.get(),
- rgw_bucket(s->bucket_tenant, s->bucket_name),
- &tmp_bucket, y);
- if (op_ret < 0 && op_ret != -ENOENT)
- return;
- s->bucket_exists = (op_ret != -ENOENT);
+ // read the bucket info if it exists
+ op_ret = driver->load_bucket(this, s->user.get(),
+ rgw_bucket(s->bucket_tenant, s->bucket_name),
+ &s->bucket, y);
+ if (op_ret < 0 && op_ret != -ENOENT)
+ return;
+ s->bucket_exists = (op_ret != -ENOENT);
+ ceph_assert(s->bucket); // creates handle even on ENOENT
- if (s->bucket_exists) {
- if (!s->system_request &&
- driver->get_zone()->get_zonegroup().get_id() !=
- tmp_bucket->get_info().zonegroup) {
- op_ret = -EEXIST;
- return;
- }
- /* Initialize info from req_state */
- info = tmp_bucket->get_info();
+ if (s->bucket_exists) {
+ const RGWBucketInfo& info = s->bucket->get_info();
- if (!swift_ver_location) {
- swift_ver_location = info.swift_ver_location;
- }
- placement_rule.inherit_from(info.placement_rule);
-
- // don't allow changes to the acl policy
- RGWAccessControlPolicy old_policy(get_cct());
- int r = rgw_op_get_bucket_policy_from_attr(this, s->cct, driver, info.owner,
- tmp_bucket->get_attrs(),
- &old_policy, y);
- if (r >= 0 && old_policy != policy) {
- s->err.message = "Cannot modify existing access control policy";
- op_ret = -EEXIST;
- return;
- }
+ if (!s->system_request && createparams.zonegroup_id != info.zonegroup) {
+ s->err.message = "Cannot modify existing bucket's zonegroup";
+ op_ret = -EEXIST;
+ return;
}
- }
- s->bucket_owner.set_id(s->user->get_id());
- s->bucket_owner.set_name(s->user->get_display_name());
+ if (!createparams.swift_ver_location) {
+ createparams.swift_ver_location = info.swift_ver_location;
+ }
- string zonegroup_id;
+ // don't allow changes to placement
+ if (createparams.placement_rule != info.placement_rule) {
+ s->err.message = "Cannot modify existing bucket's placement rule";
+ op_ret = -EEXIST;
+ return;
+ }
- if (s->system_request) {
- zonegroup_id = s->info.args.get(RGW_SYS_PARAM_PREFIX "zonegroup");
- if (zonegroup_id.empty()) {
- zonegroup_id = driver->get_zone()->get_zonegroup().get_id();
+ // don't allow changes to the acl policy
+ RGWAccessControlPolicy old_policy(get_cct());
+ int r = rgw_op_get_bucket_policy_from_attr(this, s->cct, driver, info.owner,
+ s->bucket->get_attrs(),
+ &old_policy, y);
+ if (r >= 0 && old_policy != policy) {
+ s->err.message = "Cannot modify existing access control policy";
+ op_ret = -EEXIST;
+ return;
}
- } else {
- zonegroup_id = driver->get_zone()->get_zonegroup().get_id();
}
- /* Encode special metadata first as we're using std::map::emplace under
- * the hood. This method will add the new items only if the map doesn't
- * contain such keys yet. */
+ s->bucket_owner.set_id(s->user->get_id());
+ s->bucket_owner.set_name(s->user->get_display_name());
+
buffer::list aclbl;
policy.encode(aclbl);
- emplace_attr(RGW_ATTR_ACL, std::move(aclbl));
+ createparams.attrs[RGW_ATTR_ACL] = std::move(aclbl);
if (has_cors) {
buffer::list corsbl;
cors_config.encode(corsbl);
- emplace_attr(RGW_ATTR_CORS, std::move(corsbl));
+ createparams.attrs[RGW_ATTR_CORS] = std::move(corsbl);
}
- RGWQuotaInfo quota_info;
- const RGWQuotaInfo * pquota_info = nullptr;
if (need_metadata_upload()) {
/* It's supposed that following functions WILL NOT change any special
* attributes (like RGW_ATTR_ACL) if they are already present in attrs. */
- op_ret = rgw_get_request_metadata(this, s->cct, s->info, attrs, false);
+ op_ret = rgw_get_request_metadata(this, s->cct, s->info,
+ createparams.attrs, false);
if (op_ret < 0) {
return;
}
- prepare_add_del_attrs(s->bucket_attrs, rmattr_names, attrs);
- populate_with_generic_attrs(s, attrs);
+ prepare_add_del_attrs(s->bucket_attrs, rmattr_names, createparams.attrs);
+ populate_with_generic_attrs(s, createparams.attrs);
- op_ret = filter_out_quota_info(attrs, rmattr_names, quota_info);
+ RGWQuotaInfo quota;
+ op_ret = filter_out_quota_info(createparams.attrs, rmattr_names, quota);
if (op_ret < 0) {
return;
}
- pquota_info = "a_info;
+ createparams.quota = quota;
/* Web site of Swift API. */
- filter_out_website(attrs, rmattr_names, info.website_conf);
+ RGWBucketInfo& info = s->bucket->get_info();
+ filter_out_website(createparams.attrs, rmattr_names, info.website_conf);
info.has_website = !info.website_conf.is_empty();
}
- rgw_bucket tmp_bucket;
- tmp_bucket.tenant = s->bucket_tenant; /* ignored if bucket exists */
- tmp_bucket.name = s->bucket_name;
+ if (!driver->is_meta_master()) {
+ // apply bucket creation on the master zone first
+ bufferlist in_data;
+ JSONParser jp;
+ op_ret = driver->forward_request_to_master(this, s->user.get(), nullptr,
+ in_data, &jp, s->info, y);
+ if (op_ret < 0) {
+ return;
+ }
+
+ RGWBucketInfo master_info;
+ JSONDecoder::decode_json("bucket_info", master_info, &jp);
- /* Handle updates of the metadata for Swift's object versioning. */
- if (swift_ver_location) {
- info.swift_ver_location = *swift_ver_location;
- info.swift_versioning = (! swift_ver_location->empty());
+ // update params with info from the master
+ createparams.marker = master_info.bucket.marker;
+ createparams.bucket_id = master_info.bucket.bucket_id;
+ createparams.zonegroup_id = master_info.zonegroup;
+ createparams.obj_lock_enabled = master_info.obj_lock_enabled();
+ createparams.quota = master_info.quota;
+ createparams.creation_time = master_info.creation_time;
}
- /* We're replacing bucket with the newly created one */
- ldpp_dout(this, 10) << "user=" << s->user << " bucket=" << tmp_bucket << dendl;
- op_ret = s->user->create_bucket(this, tmp_bucket, zonegroup_id,
- placement_rule,
- info.swift_ver_location,
- pquota_info, policy, attrs, info, ep_objv,
- true, obj_lock_enabled, &s->bucket_exists, s->info,
- &s->bucket, y);
+ ldpp_dout(this, 10) << "user=" << s->user << " bucket=" << s->bucket << dendl;
+ op_ret = s->bucket->create(this, createparams, y);
/* continue if EEXIST and create_bucket will fail below. this way we can
* recover from a partial create by retrying it. */
- ldpp_dout(this, 20) << "rgw_create_bucket returned ret=" << op_ret << " bucket=" << s->bucket.get() << dendl;
+ ldpp_dout(this, 20) << "Bucket::create() returned ret=" << op_ret << " bucket=" << s->bucket << dendl;
if (op_ret)
return;
s->bucket_attrs = s->bucket->get_attrs();
}
- attrs.clear();
+ createparams.attrs.clear();
- op_ret = rgw_get_request_metadata(this, s->cct, s->info, attrs, false);
+ op_ret = rgw_get_request_metadata(this, s->cct, s->info, createparams.attrs, false);
if (op_ret < 0) {
return;
}
- prepare_add_del_attrs(s->bucket_attrs, rmattr_names, attrs);
- populate_with_generic_attrs(s, attrs);
- op_ret = filter_out_quota_info(attrs, rmattr_names, s->bucket->get_info().quota);
+ prepare_add_del_attrs(s->bucket_attrs, rmattr_names, createparams.attrs);
+ populate_with_generic_attrs(s, createparams.attrs);
+ op_ret = filter_out_quota_info(createparams.attrs, rmattr_names,
+ s->bucket->get_info().quota);
if (op_ret < 0) {
return;
}
/* Handle updates of the metadata for Swift's object versioning. */
- if (swift_ver_location) {
- s->bucket->get_info().swift_ver_location = *swift_ver_location;
- s->bucket->get_info().swift_versioning = (! swift_ver_location->empty());
+ if (createparams.swift_ver_location) {
+ s->bucket->get_info().swift_ver_location = *createparams.swift_ver_location;
+ s->bucket->get_info().swift_versioning = !createparams.swift_ver_location->empty();
}
/* Web site of Swift API. */
- filter_out_website(attrs, rmattr_names, s->bucket->get_info().website_conf);
+ filter_out_website(createparams.attrs, rmattr_names,
+ s->bucket->get_info().website_conf);
s->bucket->get_info().has_website = !s->bucket->get_info().website_conf.is_empty();
/* This will also set the quota on the bucket. */
- op_ret = s->bucket->merge_and_store_attrs(this, attrs, y);
+ op_ret = s->bucket->merge_and_store_attrs(this, createparams.attrs, y);
} while (op_ret == -ECANCELED && tries++ < 20);
/* Restore the proper return code. */
{
ldpp_dout(this, 20) << "got directory=" << path << dendl;
- op_ret = handle_dir_verify_permission(y);
- if (op_ret < 0) {
- return op_ret;
+ int ret = handle_dir_verify_permission(y);
+ if (ret < 0) {
+ return ret;
}
std::string bucket_name;
rgw_obj_key object_junk;
std::tie(bucket_name, object_junk) = *parse_path(path);
- /* we need to make sure we read bucket info, it's not read before for this
- * specific request */
- std::unique_ptr<rgw::sal::Bucket> bucket;
-
- /* Create metadata: ACLs. */
- std::map<std::string, ceph::bufferlist> attrs;
- RGWAccessControlPolicy policy;
- policy.create_default(s->user->get_id(), s->user->get_display_name());
- ceph::bufferlist aclbl;
- policy.encode(aclbl);
- attrs.emplace(RGW_ATTR_ACL, std::move(aclbl));
-
- obj_version objv, ep_objv;
- bool bucket_exists;
- RGWQuotaInfo quota_info;
- const RGWQuotaInfo* pquota_info = nullptr;
- RGWBucketInfo out_info;
- string swift_ver_location;
rgw_bucket new_bucket;
- req_info info = s->info;
new_bucket.tenant = s->bucket_tenant; /* ignored if bucket exists */
new_bucket.name = bucket_name;
- rgw_placement_rule placement_rule;
- placement_rule.storage_class = s->info.storage_class;
- forward_req_info(this, s->cct, info, bucket_name);
-
- op_ret = s->user->create_bucket(this, new_bucket,
- driver->get_zone()->get_zonegroup().get_id(),
- placement_rule, swift_ver_location,
- pquota_info, policy, attrs,
- out_info, ep_objv,
- true, false, &bucket_exists,
- info, &bucket, y);
- /* continue if EEXIST and create_bucket will fail below. this way we can
- * recover from a partial create by retrying it. */
- ldpp_dout(this, 20) << "rgw_create_bucket returned ret=" << op_ret
- << ", bucket=" << bucket << dendl;
- return op_ret;
+ // load the bucket
+ std::unique_ptr<rgw::sal::Bucket> bucket;
+ ret = driver->load_bucket(this, s->user.get(), new_bucket, &bucket, y);
+
+ // return success if it exists
+ if (ret != -ENOENT) {
+ return ret;
+ }
+ ceph_assert(bucket); // creates handle even on ENOENT
+
+ const auto& zonegroup = s->penv.site->get_zonegroup();
+
+ rgw::sal::Bucket::CreateParams createparams;
+ createparams.zonegroup_id = zonegroup.id;
+ createparams.placement_rule.storage_class = s->info.storage_class;
+ op_ret = select_bucket_placement(this, zonegroup, s->user->get_info(),
+ createparams.placement_rule);
+ createparams.zone_placement = rgw::find_zone_placement(
+ this, s->penv.site->get_zone_params(), createparams.placement_rule);
+
+ {
+ // create a default acl
+ RGWAccessControlPolicy policy;
+ policy.create_default(s->user->get_id(), s->user->get_display_name());
+ ceph::bufferlist aclbl;
+ policy.encode(aclbl);
+ createparams.attrs[RGW_ATTR_ACL] = std::move(aclbl);
+ }
+
+ if (!driver->is_meta_master()) {
+ // apply bucket creation on the master zone first
+ bufferlist in_data;
+ JSONParser jp;
+ req_info req = s->info;
+ forward_req_info(this, s->cct, req, bucket_name);
+
+ ret = driver->forward_request_to_master(this, s->user.get(), nullptr,
+ in_data, &jp, req, y);
+ if (ret < 0) {
+ return ret;
+ }
+
+ RGWBucketInfo master_info;
+ JSONDecoder::decode_json("bucket_info", master_info, &jp);
+
+ // update params with info from the master
+ createparams.marker = master_info.bucket.marker;
+ createparams.bucket_id = master_info.bucket.bucket_id;
+ createparams.obj_lock_enabled = master_info.obj_lock_enabled();
+ createparams.quota = master_info.quota;
+ createparams.creation_time = master_info.creation_time;
+ }
+
+ return bucket->create(this, createparams, y);
}
};
class RGWCreateBucket : public RGWOp {
-protected:
+ protected:
+ rgw::sal::Bucket::CreateParams createparams;
RGWAccessControlPolicy policy;
std::string location_constraint;
- rgw_placement_rule placement_rule;
- RGWBucketInfo info;
- obj_version ep_objv;
- bool has_cors;
- bool relaxed_region_enforcement;
- bool obj_lock_enabled;
+ bool has_cors = false;
+ bool relaxed_region_enforcement = false;
RGWCORSConfiguration cors_config;
- boost::optional<std::string> swift_ver_location;
- std::map<std::string, buffer::list> attrs;
std::set<std::string> rmattr_names;
- bufferlist in_data;
-
virtual bool need_metadata_upload() const { return false; }
-public:
- RGWCreateBucket() : has_cors(false), relaxed_region_enforcement(false), obj_lock_enabled(false) {}
-
+ public:
void emplace_attr(std::string&& key, buffer::list&& bl) {
- attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
+ createparams.attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
}
-
int verify_permission(optional_yield y) override;
void pre_exec() override;
void execute(optional_yield y) override;
RGWAccessControlPolicy policy;
RGWCORSConfiguration cors_config;
rgw_placement_rule placement_rule;
- boost::optional<std::string> swift_ver_location;
+ std::optional<std::string> swift_ver_location;
public:
RGWPutMetadataBucket()
class JSONObj;
struct RGWQuotaInfo {
- template<class T> friend class RGWQuotaCache;
-public:
int64_t max_size;
int64_t max_objects;
bool enabled;
if ((op_ret < 0) && (op_ret != -ERR_LENGTH_REQUIRED))
return op_ret;
- in_data.append(data);
-
if (data.length()) {
RGWCreateBucketParser parser;
size_t pos = location_constraint.find(':');
if (pos != string::npos) {
- placement_rule.init(location_constraint.substr(pos + 1), s->info.storage_class);
+ createparams.placement_rule.init(location_constraint.substr(pos + 1),
+ s->info.storage_class);
location_constraint = location_constraint.substr(0, pos);
} else {
- placement_rule.storage_class = s->info.storage_class;
+ createparams.placement_rule.storage_class = s->info.storage_class;
}
auto iter = s->info.x_meta_map.find("x-amz-bucket-object-lock-enabled");
if (iter != s->info.x_meta_map.end()) {
if (!boost::algorithm::iequals(iter->second, "true") && !boost::algorithm::iequals(iter->second, "false")) {
return -EINVAL;
}
- obj_lock_enabled = boost::algorithm::iequals(iter->second, "true");
+ createparams.obj_lock_enabled = boost::algorithm::iequals(iter->second, "true");
}
return 0;
}
if (s->system_request) {
JSONFormatter f; /* use json formatter for system requests output */
+ const RGWBucketInfo& info = s->bucket->get_info();
+ const obj_version& ep_objv = s->bucket->get_version();
f.open_object_section("info");
encode_json("entry_point_object_ver", ep_objv, &f);
encode_json("object_ver", info.objv_tracker.read_version, &f);
static int get_swift_versioning_settings(
req_state * const s,
- boost::optional<std::string>& swift_ver_location)
+ std::optional<std::string>& swift_ver_location)
{
/* Removing the Swift's versions location has lower priority than setting
* a new one. That's the reason why we're handling it first. */
const std::string vlocdel =
s->info.env->get("HTTP_X_REMOVE_VERSIONS_LOCATION", "");
if (vlocdel.size()) {
- swift_ver_location = boost::in_place(std::string());
+ swift_ver_location.emplace();
}
if (s->info.env->exists("HTTP_X_VERSIONS_LOCATION")) {
location_constraint = driver->get_zone()->get_zonegroup().get_api_name();
get_rmattrs_from_headers(s, CONT_PUT_ATTR_PREFIX,
CONT_REMOVE_ATTR_PREFIX, rmattr_names);
- placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""), s->info.storage_class);
+ createparams.placement_rule.init(s->info.env->get("HTTP_X_STORAGE_POLICY", ""),
+ s->info.storage_class);
- return get_swift_versioning_settings(s, swift_ver_location);
+ return get_swift_versioning_settings(s, createparams.swift_ver_location);
}
static inline int handle_metadata_errors(req_state* const s, const int op_ret)
class RGWCompressionInfo;
struct rgw_pubsub_topics;
struct rgw_pubsub_bucket_topics;
+class RGWZonePlacementInfo;
using RGWBucketListNameFilter = std::function<bool (const std::string&)>;
const std::string& marker, const std::string& end_marker,
uint64_t max, bool need_stats, BucketList& buckets,
optional_yield y) = 0;
- /** Create a new bucket owned by this user. Creates in the backing store, not just the instantiation. */
- virtual int create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo* pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket,
- optional_yield y) = 0;
/** Get the display name for this User */
virtual std::string& get_display_name() = 0;
// XXXX hack
virtual void set_owner(rgw::sal::User* _owner) = 0;
+ /// Input parameters for create().
+ struct CreateParams {
+ std::string zonegroup_id;
+ rgw_placement_rule placement_rule;
+ // zone placement is optional on buckets created for another zonegroup
+ const RGWZonePlacementInfo* zone_placement;
+ RGWAccessControlPolicy policy;
+ Attrs attrs;
+ bool obj_lock_enabled = false;
+ std::string marker;
+ std::string bucket_id;
+ std::optional<std::string> swift_ver_location;
+ std::optional<RGWQuotaInfo> quota;
+ std::optional<ceph::real_time> creation_time;
+ };
+
+ /// Create this bucket in the backing store.
+ virtual int create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y) = 0;
+
/** Load this bucket from the backing store. Requires the key to be set, fills other fields. */
virtual int load_bucket(const DoutPrefixProvider* dpp, optional_yield y) = 0;
/** Read the bucket stats from the backing Store, synchronous */
return 0;
}
- int DBUser::create_bucket(const DoutPrefixProvider *dpp,
- const rgw_bucket& b,
- const string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const string& swift_ver_location,
- const RGWQuotaInfo * pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool *existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket_out,
- optional_yield y)
- {
- int ret;
- bufferlist in_data;
- RGWBucketInfo master_info;
- rgw_bucket *pmaster_bucket = nullptr;
- real_time creation_time;
- std::unique_ptr<Bucket> bucket;
- obj_version objv, *pobjv = NULL;
-
- /* If it exists, look it up; otherwise create it */
- ret = store->load_bucket(dpp, this, b, &bucket, y);
- if (ret < 0 && ret != -ENOENT)
- return ret;
-
- if (ret != -ENOENT) {
- *existed = true;
- } else {
- bucket = std::make_unique<DBBucket>(store, b, this);
- *existed = false;
- bucket->set_attrs(attrs);
- }
-
- /*
- * XXX: If not master zone, fwd the request to master zone.
- * For now DBStore has single zone.
- */
- std::string zid = zonegroup_id;
- /* if (zid.empty()) {
- zid = svc()->zone->get_zonegroup().get_id();
- } */
-
- // XXX: For now single default zone and STANDARD storage class
- // supported.
- rgw_placement_rule selected_placement_rule;
- selected_placement_rule.name = "default";
- selected_placement_rule.storage_class = "STANDARD";
-
- if (*existed) {
- /* XXX: Handle this when zone is implemented
- ret = svc()->zone->select_bucket_placement(this.get_info(),
- zid, placement_rule,
- &selected_placement_rule, nullptr, y);
- if (selected_placement_rule != info.placement_rule) {
- ret = -EEXIST;
- bucket_out->swap(bucket);
- return ret;
- } */
- } else {
-
- /* XXX: We may not need to send all these params. Cleanup the unused ones */
- ret = store->getDB()->create_bucket(dpp, this->get_info(), bucket->get_key(),
- zid, selected_placement_rule, swift_ver_location, pquota_info,
- attrs, info, pobjv, &ep_objv, creation_time,
- pmaster_bucket, nullptr, y, exclusive);
- if (ret == -EEXIST) {
- *existed = true;
- ret = 0;
- } else if (ret != 0) {
- return ret;
- }
- }
-
- bucket->set_version(ep_objv);
- bucket->get_info() = info;
-
- bucket_out->swap(bucket);
-
- return ret;
+ int DBBucket::create(const DoutPrefixProvider *dpp,
+ const CreateParams& params,
+ optional_yield y)
+ {
+ ceph_assert(owner);
+ const rgw_user& owner_id = owner->get_id();
+
+ rgw_bucket key = get_key();
+ key.marker = params.marker;
+ key.bucket_id = params.bucket_id;
+
+ /* XXX: We may not need to send all these params. Cleanup the unused ones */
+ return store->getDB()->create_bucket(dpp, owner_id, key,
+ params.zonegroup_id, params.placement_rule, params.attrs,
+ params.swift_ver_location, params.quota, params.creation_time,
+ &bucket_version, info, y);
}
int DBUser::read_attrs(const DoutPrefixProvider* dpp, optional_yield y)
}
int list_buckets(const DoutPrefixProvider *dpp, const std::string& marker, const std::string& end_marker,
uint64_t max, bool need_stats, BucketList& buckets, optional_yield y) override;
- virtual int create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo* pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket,
- optional_yield y) override;
virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) override;
virtual int read_stats(const DoutPrefixProvider *dpp,
optional_yield y, RGWStorageStats* stats,
DoutPrefixProvider *dpp) override;
virtual RGWAccessControlPolicy& get_acl(void) override { return acls; }
virtual int set_acl(const DoutPrefixProvider *dpp, RGWAccessControlPolicy& acl, optional_yield y) override;
+ int create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y) override;
virtual int load_bucket(const DoutPrefixProvider *dpp, optional_yield y) override;
virtual int read_stats(const DoutPrefixProvider *dpp,
const bucket_index_layout_generation& idx_layout,
need_stats, buckets, y);
}
-int FilterUser::create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo * pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket_out,
- optional_yield y)
-{
- std::unique_ptr<Bucket> nb;
- int ret;
-
- ret = next->create_bucket(dpp, b, zonegroup_id, placement_rule, swift_ver_location, pquota_info, policy, attrs, info, ep_objv, exclusive, obj_lock_enabled, existed, req_info, &nb, y);
- if (ret < 0)
- return ret;
-
- Bucket* fb = new FilterBucket(std::move(nb), this);
- bucket_out->reset(fb);
- return 0;
-}
-
int FilterUser::read_attrs(const DoutPrefixProvider* dpp, optional_yield y)
{
return next->read_attrs(dpp, y);
return next->set_acl(dpp, acl, y);
}
+int FilterBucket::create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y)
+{
+ return next->create(dpp, params, y);
+}
+
int FilterBucket::load_bucket(const DoutPrefixProvider* dpp, optional_yield y)
{
return next->load_bucket(dpp, y);
const std::string& marker, const std::string& end_marker,
uint64_t max, bool need_stats, BucketList& buckets,
optional_yield y) override;
- virtual int create_bucket(const DoutPrefixProvider* dpp,
- const rgw_bucket& b,
- const std::string& zonegroup_id,
- const rgw_placement_rule& placement_rule,
- const std::string& swift_ver_location,
- const RGWQuotaInfo* pquota_info,
- const RGWAccessControlPolicy& policy,
- Attrs& attrs,
- RGWBucketInfo& info,
- obj_version& ep_objv,
- bool exclusive,
- bool obj_lock_enabled,
- bool* existed,
- req_info& req_info,
- std::unique_ptr<Bucket>* bucket,
- optional_yield y) override;
virtual std::string& get_display_name() override { return next->get_display_name(); }
virtual const std::string& get_tenant() override { return next->get_tenant(); }
optional_yield y) override;
virtual void set_owner(rgw::sal::User* _owner) override { next->set_owner(_owner); }
+ virtual int create(const DoutPrefixProvider* dpp,
+ const CreateParams& params,
+ optional_yield y) override;
virtual int load_bucket(const DoutPrefixProvider* dpp, optional_yield y) override;
virtual int read_stats(const DoutPrefixProvider *dpp,
const bucket_index_layout_generation& idx_layout,
}
int createBucket() {
- rgw_bucket b;
- string zonegroup_id = "test_id";
- rgw_placement_rule placement_rule;
- string swift_ver_location = "test_location";
- const RGWAccessControlPolicy policy;
- rgw::sal::Attrs attrs;
RGWBucketInfo info;
- obj_version ep_objv;
- bool bucket_exists;
- int ret;
-
- CephContext* cct = get_pointer(env->cct);
- RGWProcessEnv penv;
- RGWEnv rgw_env;
- req_state s(cct->get(), penv, &rgw_env, 0);
- req_info _req_info = s.info;
-
- b.name = "test_bucket";
- placement_rule.storage_class = "test_sc";
-
- ret = testUser->create_bucket(dpp, b,
- zonegroup_id,
- placement_rule,
- swift_ver_location,
- nullptr,
- policy,
- attrs,
- info,
- ep_objv,
- false,
- false,
- &bucket_exists,
- _req_info,
- &testBucket,
- null_yield);
-
- return ret;
+ info.bucket.name = "test_bucket";
+
+ testBucket = driver->get_bucket(testUser.get(), info);
+
+ rgw::sal::Bucket::CreateParams params;
+ params.zonegroup_id = "test_id";
+ params.placement_rule.storage_class = "test_sc";
+ params.swift_ver_location = "test_location";
+
+ return testBucket->create(dpp, params, null_yield);
}
int putObject(string name) {
return 0;
}
- virtual int create_bucket(const DoutPrefixProvider* dpp, const rgw_bucket& b, const std::string& zonegroup_id, const rgw_placement_rule& placement_rule, const std::string& swift_ver_location, const RGWQuotaInfo* pquota_info, const RGWAccessControlPolicy& policy, sal::Attrs& attrs, RGWBucketInfo& info, obj_version& ep_objv, bool exclusive, bool obj_lock_enabled, bool* existed, req_info& req_info, std::unique_ptr<sal::Bucket>* bucket, optional_yield y) override {
- return 0;
- }
-
virtual int read_attrs(const DoutPrefixProvider *dpp, optional_yield y) override {
return 0;
}