]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/rados: add account metadata handler
authorCasey Bodley <cbodley@redhat.com>
Fri, 1 Dec 2023 04:44:06 +0000 (23:44 -0500)
committerCasey Bodley <cbodley@redhat.com>
Wed, 10 Apr 2024 16:53:05 +0000 (12:53 -0400)
Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/rgw/driver/rados/account.cc
src/rgw/driver/rados/account.h
src/rgw/driver/rados/rgw_sal_rados.h
src/rgw/driver/rados/rgw_service.cc
src/rgw/driver/rados/rgw_service.h

index acc4dee0c23609680d996cf77b83a70ad185c2b0..f7c86099eee88e21f2369c49a8493bd68a673860 100644 (file)
@@ -19,6 +19,8 @@
 #include "common/errno.h"
 #include "rgw_account.h"
 #include "rgw_common.h"
+#include "rgw_metadata.h"
+#include "rgw_metadata_lister.h"
 #include "rgw_obj_types.h"
 #include "rgw_string.h"
 #include "rgw_tools.h"
@@ -388,4 +390,194 @@ int remove(const DoutPrefixProvider* dpp,
   return 0;
 }
 
+
+// metadata abstraction
+
+struct CompleteInfo {
+  RGWAccountInfo info;
+  std::map<std::string, bufferlist> attrs;
+  bool has_attrs = false;
+
+  void dump(Formatter* f) const {
+    info.dump(f);
+    encode_json("attrs", attrs, f);
+  }
+
+  void decode_json(JSONObj* obj) {
+    decode_json_obj(info, obj);
+    has_attrs = JSONDecoder::decode_json("attrs", attrs, obj);
+  }
+};
+
+class MetadataObject : public RGWMetadataObject {
+  CompleteInfo aci;
+ public:
+  MetadataObject(const CompleteInfo& aci, const obj_version& v,
+                 ceph::real_time m)
+    : RGWMetadataObject(v, m), aci(aci) {}
+
+  void dump(Formatter *f) const override {
+    aci.dump(f);
+  }
+
+  CompleteInfo& get() { return aci; }
+};
+
+
+class MetadataLister : public RGWMetadataLister {
+ public:
+  using RGWMetadataLister::RGWMetadataLister;
+
+  void filter_transform(std::vector<std::string>& oids,
+                        std::list<std::string>& keys) override
+  {
+    // remove the oid prefix from keys
+    constexpr auto trim = [] (const std::string& oid) {
+      return oid.substr(account_oid_prefix.size());
+    };
+    std::transform(oids.begin(), oids.end(),
+                   std::back_inserter(keys),
+                   trim);
+  }
+};
+
+class MetadataHandler : public RGWMetadataHandler {
+  RGWSI_SysObj& sysobj;
+  const RGWZoneParams& zone;
+ public:
+  MetadataHandler(RGWSI_SysObj& sysobj, const RGWZoneParams& zone)
+    : sysobj(sysobj), zone(zone) {}
+
+  std::string get_type() override { return "account"; }
+
+  RGWMetadataObject* get_meta_obj(JSONObj* obj,
+                                  const obj_version& objv,
+                                  const ceph::real_time& mtime) override
+  {
+    CompleteInfo aci;
+    try {
+      decode_json_obj(aci, obj);
+    } catch (const JSONDecoder::err&) {
+      return nullptr;
+    }
+    return new MetadataObject(aci, objv, mtime);
+  }
+
+  int get(std::string& entry, RGWMetadataObject** obj,
+          optional_yield y, const DoutPrefixProvider* dpp) override
+  {
+    const std::string& account_id = entry;
+    CompleteInfo aci;
+    RGWObjVersionTracker objv;
+    ceph::real_time mtime;
+
+    int r = read(dpp, y, sysobj, zone, account_id,
+                 aci.info, aci.attrs, mtime, objv);
+    if (r < 0) {
+      return r;
+    }
+
+    *obj = new MetadataObject(aci, objv.read_version, mtime);
+    return 0;
+  }
+
+  int put(std::string& entry, RGWMetadataObject* obj,
+          RGWObjVersionTracker& objv, optional_yield y,
+          const DoutPrefixProvider* dpp,
+          RGWMDLogSyncType type, bool from_remote_zone) override
+  {
+    const std::string& account_id = entry;
+    auto account_obj = static_cast<MetadataObject*>(obj);
+    const auto& new_info = account_obj->get().info;
+
+    // account id must match metadata key
+    if (new_info.id != account_id) {
+      return -EINVAL;
+    }
+
+    // read existing metadata
+    RGWAccountInfo old_info;
+    std::map<std::string, ceph::buffer::list> old_attrs;
+    ceph::real_time old_mtime;
+    int r = read(dpp, y, sysobj, zone, account_id,
+                 old_info, old_attrs, old_mtime, objv);
+    if (r < 0 && r != -ENOENT) {
+      return r;
+    }
+    const RGWAccountInfo* pold_info = (r == -ENOENT ? nullptr : &old_info);
+
+    // write/overwrite metadata
+    constexpr bool exclusive = false;
+    return write(dpp, y, sysobj, zone, new_info, pold_info,
+                 account_obj->get().attrs, obj->get_mtime(),
+                 exclusive, objv);
+  }
+
+  int remove(std::string& entry, RGWObjVersionTracker& objv,
+             optional_yield y, const DoutPrefixProvider* dpp) override
+  {
+    const std::string& account_id = entry;
+
+    // read existing metadata
+    RGWAccountInfo info;
+    std::map<std::string, ceph::buffer::list> attrs;
+    ceph::real_time mtime;
+    int r = read(dpp, y, sysobj, zone, account_id,
+                 info, attrs, mtime, objv);
+    if (r < 0) {
+      return r;
+    }
+
+    return account::remove(dpp, y, sysobj, zone, info, objv);
+  }
+
+  int mutate(const std::string& entry,
+             const ceph::real_time& mtime,
+             RGWObjVersionTracker* objv,
+             optional_yield y,
+             const DoutPrefixProvider* dpp,
+             RGWMDLogStatus op_type,
+             std::function<int()> f) override
+  {
+    return -ENOTSUP; // unused
+  }
+
+  int list_keys_init(const DoutPrefixProvider* dpp,
+                     const std::string& marker, void** phandle) override
+  {
+    auto lister = std::make_unique<MetadataLister>(
+        sysobj.get_pool(zone.account_pool));
+    int r = lister->init(dpp, marker, account_oid_prefix);
+    if (r < 0) {
+      return r;
+    }
+    *phandle = lister.release();
+    return 0;
+  }
+
+  int list_keys_next(const DoutPrefixProvider* dpp, void* handle, int max,
+                     std::list<std::string>& keys, bool* truncated) override
+  {
+    auto lister = static_cast<MetadataLister*>(handle);
+    return lister->get_next(dpp, max, keys, truncated);
+  }
+
+  void list_keys_complete(void* handle) override
+  {
+    delete static_cast<MetadataLister*>(handle);
+  }
+
+  std::string get_marker(void* handle) override
+  {
+    auto lister = static_cast<MetadataLister*>(handle);
+    return lister->get_marker();
+  }
+};
+
+auto create_metadata_handler(RGWSI_SysObj& sysobj, const RGWZoneParams& zone)
+    -> std::unique_ptr<RGWMetadataHandler>
+{
+  return std::make_unique<MetadataHandler>(sysobj, zone);
+}
+
 } // namespace rgwrados::account
index 4bae82271f084a9420f965cddd5fcaf19c1a6ee5..c73d68bc626d334a0c94c334dcc11872d998000f 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <list>
 #include <map>
+#include <memory>
 #include <string>
 #include "include/encoding.h"
 #include "common/async/yield_context.h"
@@ -27,6 +28,7 @@ class JSONObj;
 struct rgw_raw_obj;
 class RGWAccountInfo;
 struct RGWBucketInfo;
+class RGWMetadataHandler;
 class RGWObjVersionTracker;
 class RGWSI_SysObj;
 class RGWStorageStats;
@@ -34,6 +36,10 @@ class RGWZoneParams;
 
 namespace rgwrados::account {
 
+/// Account metadata handler factory
+auto create_metadata_handler(RGWSI_SysObj& sysobj, const RGWZoneParams& zone)
+    -> std::unique_ptr<RGWMetadataHandler>;
+
 /// Return the rados object that tracks the given account's buckets. This
 /// can be used with the cls_user interface in namespace rgwrados::buckets.
 rgw_raw_obj get_buckets_obj(const RGWZoneParams& zone,
index 952979988280503659c4e0b4d711281d3db9128f..83ba68832b3a6df299877037d13a6665701ec732 100644 (file)
@@ -725,7 +725,7 @@ protected:
 
 class MPRadosSerializer : public StoreMPSerializer {
   librados::IoCtx ioctx;
-  rados::cls::lock::Lock lock;
+  ::rados::cls::lock::Lock lock;
   librados::ObjectWriteOperation op;
 
 public:
@@ -739,7 +739,7 @@ public:
 
 class LCRadosSerializer : public StoreLCSerializer {
   librados::IoCtx* ioctx;
-  rados::cls::lock::Lock lock;
+  ::rados::cls::lock::Lock lock;
 
 public:
   LCRadosSerializer(RadosStore* store, const std::string& oid, const std::string& lock_name, const std::string& cookie);
index e0d885b86a6e9dd76f9c1b2b416c9dfe2f6d97e6..8d726431fba7f500769ef21492df6b18dbe1f6e8 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "common/errno.h"
 
+#include "account.h"
 #include "rgw_bucket.h"
 #include "rgw_cr_rados.h"
 #include "rgw_datalog.h"
@@ -391,6 +392,8 @@ int RGWCtlDef::init(RGWServices& svc, rgw::sal::Driver* driver, const DoutPrefix
 
   meta.otp.reset(RGWOTPMetaHandlerAllocator::alloc());
   meta.role = std::make_unique<rgw::sal::RGWRoleMetadataHandler>(driver, svc.role);
+  meta.account = rgwrados::account::create_metadata_handler(
+      *svc.sysobj, svc.zone->get_zone_params());
 
   user.reset(new RGWUserCtl(svc.zone, svc.user, (RGWUserMetadataHandler *)meta.user.get()));
   bucket.reset(new RGWBucketCtl(svc.zone,
@@ -477,7 +480,13 @@ int RGWCtl::init(RGWServices *_svc, rgw::sal::Driver* driver, const DoutPrefixPr
 
   r = meta.role->attach(meta.mgr);
   if (r < 0) {
-    ldout(cct, 0) << "ERROR: failed to start init otp ctl (" << cpp_strerror(-r) << dendl;
+    ldout(cct, 0) << "ERROR: failed to start init meta.role ctl (" << cpp_strerror(-r) << dendl;
+    return r;
+  }
+
+  r = _ctl.meta.account->attach(meta.mgr);
+  if (r < 0) {
+    ldout(cct, 0) << "ERROR: failed to start init meta.account ctl (" << cpp_strerror(-r) << dendl;
     return r;
   }
   r = meta.topic->attach(meta.mgr);
index ebab083f27ec7bc0324d767fd829155cb8f9c602..c2da007b0fee66f61494b0b5a52b8f367f9f9fe6 100644 (file)
@@ -197,6 +197,7 @@ struct RGWCtlDef {
     std::unique_ptr<RGWMetadataHandler> otp;
     std::unique_ptr<RGWMetadataHandler> role;
     std::unique_ptr<RGWMetadataHandler> topic;
+    std::unique_ptr<RGWMetadataHandler> account;
 
     std::unique_ptr<RGWChainedCacheImpl<rgwrados::topic::cache_entry>> topic_cache;