]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
filter/posix: Implement `POSIXUser` as store
authorSamarah Uriarte <samarah.uriarte@ibm.com>
Tue, 11 Mar 2025 18:48:21 +0000 (13:48 -0500)
committerSamarah Uriarte <samarah.uriarte@ibm.com>
Thu, 10 Jul 2025 13:10:39 +0000 (08:10 -0500)
Signed-off-by: Samarah Uriarte <samarah.uriarte@ibm.com>
src/rgw/CMakeLists.txt
src/rgw/driver/posix/posixDB.cc [new file with mode: 0644]
src/rgw/driver/posix/posixDB.h [new file with mode: 0644]
src/rgw/driver/posix/rgw_sal_posix.cc
src/rgw/driver/posix/rgw_sal_posix.h

index 18f1213f894169ef3d221446c5fddca7fb3136b2..2f4bd0665cbdcf380dcf1457de11dd8aa52d37bf 100644 (file)
@@ -259,6 +259,7 @@ if(WITH_RADOSGW_POSIX)
   list(APPEND librgw_common_srcs
              driver/posix/rgw_sal_posix.cc
              driver/posix/lmdb-safe.cc
+             driver/posix/posixDB.cc
              driver/posix/notify.cpp)
 endif()
 if(WITH_JAEGER)
diff --git a/src/rgw/driver/posix/posixDB.cc b/src/rgw/driver/posix/posixDB.cc
new file mode 100644 (file)
index 0000000..82a8a76
--- /dev/null
@@ -0,0 +1,62 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "posixDB.h"
+#include "log/Log.h"
+
+using namespace std;
+
+namespace rgw { namespace store {
+
+int POSIXUserDB::Initialize(string logfile, int loglevel)
+{
+  int ret = -1;
+  const DoutPrefixProvider *dpp = get_def_dpp();
+
+  if (!cct) {
+    cout << "Failed to Initialize. No ceph Context \n";
+    return -1;
+  }
+
+  if (loglevel > 0) {
+    cct->_conf->subsys.set_log_level(ceph_subsys_rgw, loglevel);
+  }
+  if (!logfile.empty()) {
+    cct->_log->set_log_file(logfile);
+    cct->_log->reopen_log_file();
+  }
+
+  db = openDB(dpp);
+
+  if (!db) {
+    ldpp_dout(dpp, 0) <<"Failed to open database " << dendl;
+    return ret;
+  }
+
+  ret = InitializeDBOps(dpp);
+
+  if (ret) {
+    ldpp_dout(dpp, 0) <<"InitializePOSIXUserDBOps failed " << dendl;
+    closeDB(dpp);
+    db = NULL;
+    return ret;
+  }
+
+  ldpp_dout(dpp, 0) << "POSIXUserDB successfully initialized - name:" \
+    << db_name << "" << dendl;
+
+  return ret;
+}
+
+int POSIXUserDB::Destroy(const DoutPrefixProvider *dpp)
+{
+  DB::Destroy(dpp);
+
+  ldpp_dout(dpp, 20)<<"POSIXUserDB successfully destroyed - name:" \
+    <<db_name << dendl;
+
+  return 0;
+}
+
+} } // namespace rgw::store
+
diff --git a/src/rgw/driver/posix/posixDB.h b/src/rgw/driver/posix/posixDB.h
new file mode 100644 (file)
index 0000000..c439bb3
--- /dev/null
@@ -0,0 +1,138 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include "driver/rados/rgw_bucket.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string>
+#include <stdio.h>
+#include <iostream>
+#include <mutex>
+#include <condition_variable>
+#include "fmt/format.h"
+#include <map>
+#include "rgw_sal_store.h"
+#include "rgw_common.h"
+#include "driver/dbstore/sqlite/sqliteDB.h"
+#include "driver/dbstore/common/dbstore.h"
+#include "global/global_context.h"
+#include "global/global_init.h"
+#include "common/ceph_context.h"
+#include "rgw_multi.h"
+
+#include "driver/rados/rgw_obj_manifest.h" // FIXME: subclass dependency
+
+namespace rgw { namespace store {
+
+class POSIXUserDB;
+
+struct POSIXUserDBOpUserInfo : DBOpUserInfo {};
+
+struct POSIXUserDBOpInfo : DBOpInfo {};
+
+struct POSIXUserDBOpUserPrepareInfo : DBOpUserPrepareInfo {};
+
+struct POSIXUserDBOpPrepareInfo : DBOpPrepareInfo {};
+
+struct POSIXUserDBOpPrepareParams : DBOpPrepareParams {};
+
+struct POSIXUserDBOps : DBOps {};
+
+class POSIXUserDBOp : public DBOp {
+  private:
+    static constexpr std::string_view CreateUserTableQ =
+      /* Corresponds to rgw::sal::User
+       *
+       * For now only UserID is made Primary key.
+       * If multiple tenants are stored in single .db handle, should
+       * make both (UserID, Tenant) as Primary Key.
+       *
+       * XXX:
+       * - AccessKeys, SwiftKeys, Subusers (map<>) are stored as blob.
+       *   To enable easy query, first accesskey is stored in separate fields
+       *   AccessKeysID, AccessKeysSecret.
+       *   In future, may be have separate table to store these keys and
+       *   query on that table.
+       * - Quota stored as blob .. should be linked to quota table.
+       */
+      "CREATE TABLE IF NOT EXISTS '{}' (       \
+      UserID TEXT NOT NULL UNIQUE,             \
+      Tenant TEXT ,            \
+      NS TEXT ,                \
+      DisplayName TEXT , \
+      UserEmail TEXT , \
+      AccessKeysID TEXT ,      \
+      AccessKeysSecret TEXT ,  \
+      AccessKeys BLOB ,        \
+      SwiftKeys BLOB , \
+      SubUsers BLOB ,          \
+      Suspended INTEGER ,      \
+      MaxBuckets INTEGER ,     \
+      OpMask   INTEGER ,       \
+      UserCaps BLOB ,          \
+      Admin    INTEGER ,       \
+      System INTEGER ,         \
+      PlacementName TEXT ,     \
+      PlacementStorageClass TEXT ,     \
+      PlacementTags BLOB ,     \
+      BucketQuota BLOB ,       \
+      TempURLKeys BLOB ,       \
+      UserQuota BLOB , \
+      TYPE INTEGER ,           \
+      MfaIDs BLOB ,    \
+      AssumedRoleARN TEXT , \
+      UserAttrs   BLOB,   \
+      UserVersion   INTEGER,    \
+      UserVersionTag TEXT,      \
+      PRIMARY KEY (UserID) \n);";
+
+  public:
+    POSIXUserDBOp() : DBOp() {}
+    virtual ~POSIXUserDBOp() {}
+    std::mutex mtx; // to protect prepared stmt
+};
+
+class InsertPOSIXUserOp : public SQLInsertUser {};
+
+class RemovePOSIXUserOp: public SQLRemoveUser {};
+
+class POSIXUserDB : public SQLiteDB {
+  private:
+    const std::string db_name;
+    rgw::sal::Driver* driver;
+    const std::string user_table;
+
+  protected:
+    void *db;
+    CephContext *cct;
+    const DoutPrefix dp;
+    // Below mutex is to protect objectmap and other shared
+    // objects if any.
+    std::mutex mtx;
+
+  public:
+    POSIXUserDB(std::string db_name, CephContext *_cct) : SQLiteDB(db_name, _cct),
+    db_name(db_name),
+    user_table(db_name+"_user_table"),
+    cct(_cct),
+    dp(_cct, ceph_subsys_rgw, "rgw POSIXUserDBStore backend: ")
+    {}
+    /* POSIXUserDB() {}*/
+
+    int Initialize(std::string logfile, int loglevel);
+    int Destroy(const DoutPrefixProvider *dpp);
+
+    virtual int InitPrepareParams(const DoutPrefixProvider *dpp,
+                                  DBOpPrepareParams &p_params,
+                                  DBOpParams* params) { return 0; } // TODO
+    virtual int createLCTables(const DoutPrefixProvider *dpp) { return 0; }
+
+    virtual int ListAllBuckets(const DoutPrefixProvider *dpp, DBOpParams *params) { return 0; } // TODO
+    virtual int ListAllUsers(const DoutPrefixProvider *dpp, DBOpParams *params) { return 0; } // TODO
+    virtual int ListAllObjects(const DoutPrefixProvider *dpp, DBOpParams *params) { return 0; } // TODO
+};
+
+} } // namespace rgw::store
index d72b38ee45bb87f7a9cf425a462f6c5461172fae..e128a1de5f17ba3893cc4d72747b4a0c8a33cab6 100644 (file)
@@ -22,6 +22,8 @@
 #include "include/scope_guard.h"
 #include "common/Clock.h" // for ceph_clock_now()
 #include "common/errno.h"
+#include "driver/dbstore/common/dbstore.h"
+#include "rgw_sal_dbstore.h"
 
 #define dout_subsys ceph_subsys_rgw
 #define dout_context g_ceph_context
@@ -1867,6 +1869,20 @@ int POSIXDriver::initialize(CephContext *cct, const DoutPrefixProvider *dpp)
 {
   FilterDriver::initialize(cct, dpp);
 
+  int ret = -1;
+  const static std::string tenant = "default_ns";
+  const auto& db_path = g_conf().get_val<std::string>("dbstore_db_dir");
+  const auto& db_name = g_conf().get_val<std::string>("dbstore_db_name_prefix") + "-" + tenant;
+  auto db_full_path = std::filesystem::path(db_path) / db_name;
+
+  userDB = new POSIXUserDB(db_full_path.string(), cct); 
+
+  if ((ret = userDB->Initialize("", -1)) < 0) {
+    ldout(cct, 0) << "User DB initialization failed for tenant("<<tenant<<")" << dendl;
+    delete userDB;
+    return ret;
+  }
+
   base_path = g_conf().get_val<std::string>("rgw_posix_base_path");
 
   ldpp_dout(dpp, 20) << "Initializing POSIX driver: " << base_path << dendl;
@@ -1882,7 +1898,7 @@ int POSIXDriver::initialize(CephContext *cct, const DoutPrefixProvider *dpp)
       g_conf().get_val<int64_t>("rgw_posix_cache_lmdb_count")));
 
   root_dir = std::make_unique<Directory>(base_path, nullptr, ctx());
-  int ret = root_dir->open(dpp);
+  ret = root_dir->open(dpp);
   if (ret < 0) {
     if (ret == -ENOTDIR) {
       ldpp_dout(dpp, 0) << " ERROR: base path (" << base_path
@@ -1905,51 +1921,60 @@ int POSIXDriver::initialize(CephContext *cct, const DoutPrefixProvider *dpp)
 
 std::unique_ptr<User> POSIXDriver::get_user(const rgw_user &u)
 {
-  std::unique_ptr<User> user = next->get_user(u);
-
-  return std::make_unique<POSIXUser>(std::move(user), this);
+  return std::make_unique<POSIXUser>(this, u);
 }
 
 int POSIXDriver::get_user_by_access_key(const DoutPrefixProvider* dpp, const std::string& key, optional_yield y, std::unique_ptr<User>* user)
 {
-  std::unique_ptr<User> nu;
-  int ret;
+  RGWUserInfo uinfo;
+  rgw::sal::Attrs attrs;
+  RGWObjVersionTracker objv_tracker;
+
+  int ret = userDB->get_user(dpp, std::string("access_key"), key, uinfo, &attrs,
+      &objv_tracker);
 
-  ret = next->get_user_by_access_key(dpp, key, y, &nu);
-  if (ret != 0)
+  if (ret < 0)
     return ret;
 
-  User* u = new POSIXUser(std::move(nu), this);
+  User* u = new POSIXUser(this, uinfo);
+
+  if (!u)
+    return -ENOMEM;
+
+  u->get_attrs() = std::move(attrs);
+  u->get_version_tracker() = objv_tracker;
   user->reset(u);
   return 0;
 }
 
 int POSIXDriver::get_user_by_email(const DoutPrefixProvider* dpp, const std::string& email, optional_yield y, std::unique_ptr<User>* user)
 {
-  std::unique_ptr<User> nu;
-  int ret;
 
-  ret = next->get_user_by_email(dpp, email, y, &nu);
-  if (ret != 0)
+  RGWUserInfo uinfo;
+  rgw::sal::Attrs attrs;
+  RGWObjVersionTracker objv_tracker;
+
+  int ret = userDB->get_user(dpp, std::string("email"), email, uinfo, &attrs,
+      &objv_tracker);
+
+  if (ret < 0)
     return ret;
 
-  User* u = new POSIXUser(std::move(nu), this);
+  User* u = new POSIXUser(this, uinfo);
+
+  if (!u)
+    return -ENOMEM;
+
+  u->get_attrs() = std::move(attrs);
+  u->get_version_tracker() = objv_tracker;
   user->reset(u);
   return 0;
 }
 
 int POSIXDriver::get_user_by_swift(const DoutPrefixProvider* dpp, const std::string& user_str, optional_yield y, std::unique_ptr<User>* user)
 {
-  std::unique_ptr<User> nu;
-  int ret;
-
-  ret = next->get_user_by_swift(dpp, user_str, y, &nu);
-  if (ret != 0)
-    return ret;
-
-  User* u = new POSIXUser(std::move(nu), this);
-  user->reset(u);
-  return 0;
+  /* Swift keys and subusers are not supported by DBStore for now */
+  return -ENOTSUP;
 }
 
 std::unique_ptr<Object> POSIXDriver::get_object(const rgw_obj_key& k)
@@ -2172,28 +2197,41 @@ int POSIXBucket::create(const DoutPrefixProvider* dpp,
 
 int POSIXUser::read_attrs(const DoutPrefixProvider* dpp, optional_yield y)
 {
-  return next->read_attrs(dpp, y);
+  return driver->get_user_db()->get_user(dpp, std::string("user_id"), this->get_id().id, this->get_info(), &(this->get_attrs()),
+        &(this->get_version_tracker()));
 }
 
 int POSIXUser::merge_and_store_attrs(const DoutPrefixProvider* dpp,
                                      Attrs& new_attrs, optional_yield y)
 {
-  return next->merge_and_store_attrs(dpp, new_attrs, y);
+  auto attrs = this->get_attrs();
+  for(auto& it : new_attrs) {
+       attrs[it.first] = it.second;
+  }
+
+  return store_user(dpp, y, false);
 }
 
 int POSIXUser::load_user(const DoutPrefixProvider* dpp, optional_yield y)
 {
-  return next->load_user(dpp, y);
+  return driver->get_user_db()->get_user(dpp, std::string("user_id"), this->get_id().id, this->get_info(), &(this->get_attrs()),
+           &(this->get_version_tracker()));
 }
 
 int POSIXUser::store_user(const DoutPrefixProvider* dpp, optional_yield y, bool exclusive, RGWUserInfo* old_info)
 {
-  return next->store_user(dpp, y, exclusive, old_info);
+  return driver->get_user_db()->store_user(dpp, this->get_info(), exclusive, &(this->get_attrs()), &(this->get_version_tracker()), old_info);
 }
 
 int POSIXUser::remove_user(const DoutPrefixProvider* dpp, optional_yield y)
 {
-  return next->remove_user(dpp, y);
+  return driver->get_user_db()->remove_user(dpp, this->get_info(), &(this->get_version_tracker()));
+}
+
+int POSIXUser::verify_mfa(const std::string& mfa_str, bool* verified, const DoutPrefixProvider *dpp, optional_yield y)
+{
+  *verified = false;
+  return 0;
 }
 
 std::unique_ptr<Object> POSIXBucket::get_object(const rgw_obj_key& k)
index fdf2b9d510fe8b6410ecd4a603b0724e4becf321..3a75cba1315f49995f48c89d367437514864b4ab 100644 (file)
@@ -20,6 +20,7 @@
 #include <memory>
 #include "common/dout.h"
 #include "bucket_cache.h"
+#include "posixDB.h"
 
 namespace rgw { namespace sal {
 
@@ -350,7 +351,7 @@ std::string get_key_fname(rgw_obj_key& key, bool use_version);
 
 class POSIXDriver : public FilterDriver {
 protected:
-
+  rgw::store::POSIXUserDB* userDB;
   std::unique_ptr<BucketCache> bucket_cache;
   std::string base_path;
   std::unique_ptr<Directory> root_dir;
@@ -421,6 +422,7 @@ public:
 
   /* Internal APIs */
   int get_root_fd() { return root_dir->get_fd(); }
+  rgw::store::POSIXUserDB* get_user_db() { return userDB; }
   Directory* get_root_dir() { return root_dir.get(); }
   const std::string& get_base_path() const { return base_path; }
   BucketCache* get_bucket_cache() { return bucket_cache.get(); }
@@ -432,25 +434,40 @@ public:
 
 };
 
-class POSIXUser : public FilterUser {
+class POSIXUser : public StoreUser {
 private:
   POSIXDriver* driver;
 
 public:
-  POSIXUser(std::unique_ptr<User> _next, POSIXDriver* _driver) :
-    FilterUser(std::move(_next)),
-    driver(_driver) {}
+  POSIXUser(POSIXDriver* _driver) :
+    StoreUser(), driver(_driver) {}
+  POSIXUser(POSIXDriver* _driver, const rgw_user& _u) :
+    StoreUser(_u), driver(_driver) {}
+  POSIXUser(POSIXDriver* _driver, const RGWUserInfo& _info) :
+    StoreUser(_info), driver(_driver) {}
   virtual ~POSIXUser() = default;
 
-  virtual Attrs& get_attrs() override { return next->get_attrs(); }
-  virtual void set_attrs(Attrs& _attrs) override { next->set_attrs(_attrs); }
+  virtual std::unique_ptr<User> clone() override {
+    return std::unique_ptr<User>(new POSIXUser(*this));
+  }
   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_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                         uint64_t end_epoch, uint32_t max_entries,
+                         bool* is_truncated, RGWUsageIter& usage_iter,
+                         std::map<rgw_user_bucket, rgw_usage_log_entry>& usage) override { return 0; }
+  virtual int trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch,
+                         uint64_t end_epoch, optional_yield y) override { return 0; }
   virtual int load_user(const DoutPrefixProvider* dpp, optional_yield y) override;
   virtual int store_user(const DoutPrefixProvider* dpp, optional_yield y, bool
                         exclusive, RGWUserInfo* old_info = nullptr) override;
   virtual int remove_user(const DoutPrefixProvider* dpp, optional_yield y) override;
+  virtual int verify_mfa(const std::string& mfa_str, bool* verified,
+                         const DoutPrefixProvider* dpp, optional_yield y) override;
+  int list_groups(const DoutPrefixProvider* dpp, optional_yield y,
+                  std::string_view marker, uint32_t max_items,
+                  GroupList& listing) override { return -ENOTSUP; }
 };
 
 class POSIXBucket : public StoreBucket {