]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/sal: move User::create_bucket() to Bucket::create()
authorCasey Bodley <cbodley@redhat.com>
Sat, 18 Mar 2023 15:48:38 +0000 (11:48 -0400)
committerCasey Bodley <cbodley@redhat.com>
Tue, 7 Nov 2023 17:18:17 +0000 (12:18 -0500)
the CreateBucket operation always has to deal with existing buckets, so
we have to load the Bucket handle first anyway

also moves the related placement and forward_request_to_master() logic
out of sal entirely

Signed-off-by: Casey Bodley <cbodley@redhat.com>
25 files changed:
src/rgw/driver/d4n/rgw_sal_d4n.cc
src/rgw/driver/d4n/rgw_sal_d4n.h
src/rgw/driver/dbstore/common/dbstore.cc
src/rgw/driver/dbstore/common/dbstore.h
src/rgw/driver/dbstore/tests/dbstore_tests.cc
src/rgw/driver/posix/rgw_sal_posix.cc
src/rgw/driver/posix/rgw_sal_posix.h
src/rgw/driver/rados/rgw_rados.cc
src/rgw/driver/rados/rgw_rados.h
src/rgw/driver/rados/rgw_sal_rados.cc
src/rgw/driver/rados/rgw_sal_rados.h
src/rgw/driver/rados/rgw_zone.cc
src/rgw/driver/rados/rgw_zone.h
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_quota_types.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_sal.h
src/rgw/rgw_sal_dbstore.cc
src/rgw/rgw_sal_dbstore.h
src/rgw/rgw_sal_filter.cc
src/rgw/rgw_sal_filter.h
src/test/rgw/test_d4n_filter.cc
src/test/rgw/test_rgw_lua.cc

index 93cd8f2d4159d47bdf2c6367643887fa1d6066bd..efeb281c3cea67c1f06a7d04e934523dc50aadd7 100644 (file)
@@ -59,33 +59,11 @@ std::unique_ptr<Object> D4NFilterBucket::get_object(const rgw_obj_key& k)
   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,
index 459e885fc240210079af4f0375fc8214c1e68f5f..a54371f6cc6480b87ca427a50aaa277690ce797b 100644 (file)
@@ -71,23 +71,6 @@ class D4NFilterUser : public FilterUser {
       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 {
@@ -101,6 +84,9 @@ 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 {
index 54202862c8d6d0e25728bca3763d188c7eb4362b..5a4ae021ead3100d4cb38c29da6e45502bb322fb 100644 (file)
@@ -474,20 +474,16 @@ out:
 }
 
 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.
@@ -506,50 +502,48 @@ int DB::create_bucket(const DoutPrefixProvider *dpp,
   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", &params);
 
index b26cc116e82dc01852c877c4bd0944a04fb024e3..79f312cb844675d9cd6130b33289657de37ca253 100644 (file)
@@ -1595,20 +1595,16 @@ class DB {
         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; };
 
index 27edb7b857392ed8eec2f8ba12a3ab4cc35a3c4f..14fe9c37e754d178f91e06191fcc2256fcb098aa 100644 (file)
@@ -461,45 +461,37 @@ TEST_F(DBStoreTest, CreateBucket) {
   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);
 }
 
@@ -516,14 +508,14 @@ TEST_F(DBStoreTest, GetBucketQueryByName) {
   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;
 }
@@ -575,7 +567,7 @@ TEST_F(DBStoreTest, BucketChown) {
 
   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) {
index 5204017274a90ff9dc610522bdccae66d2955a97..e4e640b020347212d9e5e50266f56797698e5e2b 100644 (file)
@@ -37,51 +37,6 @@ const std::string MP_OBJ_PART_PFX = "part-";
 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);
@@ -566,74 +521,46 @@ int POSIXUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& ma
   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;
 }
 
@@ -1240,7 +1167,7 @@ int POSIXBucket::create(const DoutPrefixProvider* dpp, optional_yield y, bool* e
     } else if (existed != nullptr) {
       *existed = true;
     }
-    return ret;
+    return -ret;
   }
 
   return write_attrs(dpp, y);
index e132f240812bea7160475ea24320e61c63d141d6..c5360aa90f9a5c6dd224e42d2b02e6e3d9104c39 100644 (file)
@@ -121,22 +121,6 @@ public:
                           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;
@@ -197,6 +181,9 @@ public:
                                      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,
index 1ec1763743502421c4a64d2905560626fd73101a..3632e66af595beadee8db32db8dbc3eb4e84f3c2 100644 (file)
@@ -2272,79 +2272,70 @@ void RGWRados::create_bucket_id(string *bucket_id)
   *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;
@@ -2352,7 +2343,7 @@ int RGWRados::create_bucket(const RGWUserInfo& owner, rgw_bucket& bucket,
     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;
@@ -2363,10 +2354,12 @@ int RGWRados::create_bucket(const RGWUserInfo& owner, rgw_bucket& bucket,
 
       /* 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;
index 18e818c4e893e4e47e0fac976427606fdeea8d6e..77a08c068a647ffc23b575a7a8948d106d04ca96 100644 (file)
@@ -628,21 +628,20 @@ public:
   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; }
 
index 328b4f82c8f21548b71e0b8380cf007b3f9a314a..fd8964e83ba15204bffd0e77940a8bcbf4be3620 100644 (file)
@@ -120,120 +120,52 @@ int RadosUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& ma
   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;
 }
 
index 8c1926f3fbef46642366bcc951796fba5cef1739..c8fa876260bfafd3371d8e33267ab337fe547437 100644 (file)
@@ -274,22 +274,6 @@ class RadosUser : public StoreUser {
     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,
@@ -544,6 +528,8 @@ class RadosBucket : public StoreBucket {
                                        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,
index 8c237f6bedac1cb2b6e260b5c54cf7a344341076..a9cc179f06c29137784c555abcd4f14a1ed02d60 100644 (file)
@@ -1094,6 +1094,27 @@ int delete_zone(const DoutPrefixProvider* dpp, optional_yield y,
   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,
index 6d55fd52c57586577a5da934dec60e6f83bad8e1..b57b05ada85723a9d890e691c5857f7ee11361ef 100644 (file)
@@ -943,6 +943,12 @@ int delete_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
index 067a939d7535eec8d7f6823a485d1400572ad5fd..1bd1fd85ba0c0d122d2b5dd518719a71917c1250 100644 (file)
@@ -487,6 +487,8 @@ int rgw_build_bucket_policies(const DoutPrefixProvider *dpp, rgw::sal::Driver* d
     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;
@@ -494,8 +496,7 @@ int rgw_build_bucket_policies(const DoutPrefixProvider *dpp, rgw::sal::Driver* d
                               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);
     }
   }
 
@@ -543,20 +544,13 @@ int rgw_build_bucket_policies(const DoutPrefixProvider *dpp, rgw::sal::Driver* d
 
     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
        */
@@ -3331,6 +3325,47 @@ static void filter_out_website(std::map<std::string, ceph::bufferlist>& add_attr
   }
 }
 
+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)
 {
@@ -3338,149 +3373,181 @@ 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 = &quota_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;
@@ -3506,31 +3573,33 @@ void RGWCreateBucket::execute(optional_yield y)
         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. */
@@ -7561,54 +7630,73 @@ int RGWBulkUploadOp::handle_dir(const std::string_view path, optional_yield y)
 {
   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);
 }
 
 
index e1189cb236d40bd1394c71a3c3609c118d4d28e1..21044046680a1e9bfe2e2f6519408561586f76cd 100644 (file)
@@ -1076,31 +1076,21 @@ public:
 };
 
 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;
@@ -1403,7 +1393,7 @@ protected:
   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()
index f7d06657ed682ccd05e993c6944ca42ea817eb31..48d46dc62b438a9afd6eeb25417adabdb881d025 100644 (file)
@@ -28,8 +28,6 @@ static inline int64_t rgw_rounded_kb(int64_t bytes)
 class JSONObj;
 
 struct RGWQuotaInfo {
-  template<class T> friend class RGWQuotaCache;
-public:
   int64_t max_size;
   int64_t max_objects;
   bool enabled;
index 6c3a8c8adc1682ee1305aa0b92d4c3e874f7a6c0..971b63e85d799114585f4f0933bb5132112f8b9d 100644 (file)
@@ -2456,8 +2456,6 @@ int RGWCreateBucket_ObjStore_S3::get_params(optional_yield y)
   if ((op_ret < 0) && (op_ret != -ERR_LENGTH_REQUIRED))
     return op_ret;
 
-  in_data.append(data);
-
   if (data.length()) {
     RGWCreateBucketParser parser;
 
@@ -2486,17 +2484,18 @@ int RGWCreateBucket_ObjStore_S3::get_params(optional_yield y)
 
   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;
 }
@@ -2516,6 +2515,8 @@ void RGWCreateBucket_ObjStore_S3::send_response()
   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);
index 7ef73285583baa2f0e08b8a3fecb1cf1b8625d85..b941d4bb099253bc64f72c47434e01a0e9b37c2c 100644 (file)
@@ -682,14 +682,14 @@ static void get_rmattrs_from_headers(const req_state * const s,
 
 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")) {
@@ -724,9 +724,10 @@ int RGWCreateBucket_ObjStore_SWIFT::get_params(optional_yield y)
   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)
index d69942532881cab817c4038c444070bc5f13a23f..d449535c3986f70fd4d4fd20fa4e07c445065c01 100644 (file)
@@ -39,6 +39,7 @@ typedef std::shared_ptr<RGWSyncModuleInstance> RGWSyncModuleInstanceRef;
 class RGWCompressionInfo;
 struct rgw_pubsub_topics;
 struct rgw_pubsub_bucket_topics;
+class RGWZonePlacementInfo;
 
 
 using RGWBucketListNameFilter = std::function<bool (const std::string&)>;
@@ -487,23 +488,6 @@ class User {
                             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;
@@ -674,6 +658,27 @@ class Bucket {
     // 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 */
index 792fa457f895274dbdd891a4b76aefbf71c5c23f..c8046a65a00dafa00d888e8dd79ba21374a06a23 100644 (file)
@@ -58,90 +58,22 @@ namespace rgw::sal {
     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)
index 41a0b89ea50296153abd23c8beec73b6db6c0f50..83f3ff965782542184bc928156f030a88ecfa503 100644 (file)
@@ -88,22 +88,6 @@ protected:
       }
       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,
@@ -178,6 +162,9 @@ protected:
                                        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,
index c70d9e372dc306e61f7ecc971d3fff0e4cfa778c..01a11351367268d5ad22df959e04e2aa6d48994f 100644 (file)
@@ -508,35 +508,6 @@ int FilterUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& m
                             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);
@@ -636,6 +607,13 @@ int FilterBucket::set_acl(const DoutPrefixProvider* dpp,
   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);
index b2aa1be399f3f9d98a9f8107d2ac028de1d6e548..1711723bdd263b4a1dc4765e2570efca9caaa22f 100644 (file)
@@ -325,22 +325,6 @@ public:
                           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(); }
@@ -419,6 +403,9 @@ public:
                      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,
index 7ceb7092c64f0cf1b0ed8f08d902a9f1fe0f7063..2d39981806c8ef6a718dbdffb0c8f84e98810bca 100644 (file)
@@ -114,43 +114,17 @@ class D4NFilterFixture : public ::testing::Test {
     }
 
     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) {
index 05f0d291961a68332e1e1f0188f6139cc38595fa..8502ce81ef5acb8cc62f525516cf8d155b94df7d 100644 (file)
@@ -78,10 +78,6 @@ public:
     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;
   }