From: Ali Masarwa Date: Sun, 12 Apr 2026 13:07:38 +0000 (+0300) Subject: RGW | standalone: add support for accounts in dbstore X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b718c6294fe13c3cfea8875422c87b840725db9b;p=ceph.git RGW | standalone: add support for accounts in dbstore Signed-off-by: Ali Masarwa --- diff --git a/src/rgw/driver/dbstore/common/dbstore.cc b/src/rgw/driver/dbstore/common/dbstore.cc index 6db081ca304..bf8edcdbb2e 100644 --- a/src/rgw/driver/dbstore/common/dbstore.cc +++ b/src/rgw/driver/dbstore/common/dbstore.cc @@ -234,6 +234,7 @@ int DB::InitializeParams(const DoutPrefixProvider *dpp, DBOpParams *params) params->cct = cct; //reset params here + params->account_table = account_table; params->user_table = user_table; params->bucket_table = bucket_table; params->quota_table = quota_table; @@ -430,6 +431,157 @@ out: return ret; } +int DB::get_account(const DoutPrefixProvider *dpp, + const std::string& query_str, const std::string& query_str_val, + RGWAccountInfo& ainfo, map *pattrs, + RGWObjVersionTracker *pobjv_tracker) { + int ret = 0; + + if (query_str.empty() || query_str_val.empty()) { + ldpp_dout(dpp, 0)<<"In GetAccount - Invalid query(" << query_str <<"), query_str_val(" << query_str_val <<")" << dendl; + return -1; + } + + DBOpParams params = {}; + InitializeParams(dpp, ¶ms); + + params.op.query_str = query_str; + + // validate query_str with AccountTable entries names + if (query_str == "name") { + params.op.account.info.name = query_str_val; + } else if (query_str == "email") { + params.op.account.info.email = query_str_val; + } else if (query_str == "account_id") { + params.op.account.info.id = query_str_val; + } else { + ldpp_dout(dpp, 0)<<"In GetAccount Invalid query string :" <read_version = params.op.account.account_version; + } + + return ret; +} + +int DB::store_account(const DoutPrefixProvider *dpp, + const RGWAccountInfo& ainfo, bool exclusive, const map *pattrs, + RGWObjVersionTracker *pobjv) +{ + DBOpParams params = {}; + InitializeParams(dpp, ¶ms); + int ret = 0; + + /* Check if the account already exists and return the old info, caller will have a use for it */ + RGWAccountInfo orig_info; + RGWObjVersionTracker objv_tracker = {}; + obj_version& obj_ver = objv_tracker.read_version; + + orig_info.id = ainfo.id; + ret = get_account(dpp, string("account_id"), ainfo.id, orig_info, nullptr, &objv_tracker); + + if (!ret && obj_ver.ver) { + /* already exists. */ + if (pobjv && (pobjv->read_version.ver != obj_ver.ver)) { + /* Object version mismatch.. return ECANCELED */ + ret = -ECANCELED; + ldpp_dout(dpp, 0)<<"Account Read version mismatch err:(" <read_version = obj_ver; + pobjv->write_version = obj_ver; + } + + return ret; +} + +int DB::remove_account(const DoutPrefixProvider *dpp, + const RGWAccountInfo &ainfo, RGWObjVersionTracker *pobjv) +{ + DBOpParams params = {}; + InitializeParams(dpp, ¶ms); + int ret = 0; + + RGWAccountInfo orig_info; + RGWObjVersionTracker objv_tracker = {}; + + orig_info.id = ainfo.id; + ret = get_account(dpp, string("account_id"), ainfo.id, orig_info, nullptr, &objv_tracker); + + if (ret) { + return ret; + } + + if (!ret && objv_tracker.read_version.ver) { + /* already exists. */ + + if (pobjv && (pobjv->read_version.ver != objv_tracker.read_version.ver)) { + /* Object version mismatch.. return ECANCELED */ + ret = -ECANCELED; + ldpp_dout(dpp, 0)<<"Account Read version mismatch err:(" < InsertAccount; + std::shared_ptr RemoveAccount; + std::shared_ptr GetAccount; std::shared_ptr InsertUser; std::shared_ptr RemoveUser; std::shared_ptr GetUser; @@ -382,6 +409,30 @@ class ObjectOp { class DBOp { private: + static constexpr std::string_view CreateAccountTableQ = + /* Corresponds to RGWAccountInfo + * + * AccountID is made Primary key. + * If multiple tenants are stored in single .db handle, should + * make both (AccountID, Tenant) as Primary Key. + * + * XXX: + * - Quota stored as blob .. should be linked to quota table. + */ + "CREATE TABLE IF NOT EXISTS '{}' ( \ + AccountID TEXT NOT NULL UNIQUE, \ + Tenant TEXT , \ + AccountName TEXT , \ + Email TEXT , \ + Quota BLOB , \ + BucketQuota BLOB , \ + MaxUsers INTEGER , \ + MaxRoles INTEGER , \ + MaxGroups INTEGER , \ + MaxBuckets INTEGER , \ + MaxAccessKeys INTEGER , \ + PRIMARY KEY (AccountID) \n);"; + static constexpr std::string_view CreateUserTableQ = /* Corresponds to rgw::sal::User * @@ -653,6 +704,9 @@ class DBOp { static std::string CreateTableSchema(std::string_view type, const DBOpParams *params) { + if (!type.compare("Account")) + return fmt::format(CreateAccountTableQ, + params->account_table); if (!type.compare("User")) return fmt::format(CreateUserTableQ, params->user_table); @@ -705,6 +759,76 @@ class DBOp { virtual int Execute(const DoutPrefixProvider *dpp, DBOpParams *params) { return 0; } }; +class InsertAccountOp : virtual public DBOp { + private: + static constexpr std::string_view Query = "INSERT OR REPLACE INTO '{}' \ + (AccountID, Tenant, AccountName, Email, \ + Quota, BucketQuota, MaxUsers, MaxRoles, MaxGroups, \ + MaxBuckets, MaxAccessKeys) \ + VALUES ({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {});"; + + public: + virtual ~InsertAccountOp() {} + + static std::string Schema(DBOpPrepareParams ¶ms) { + return fmt::format(Query, params.account_table, + params.op.account.account_id, params.op.account.tenant, + params.op.account.account_name, params.op.account.email, + params.op.account.quota, params.op.account.bucket_quota, + params.op.account.max_users, params.op.account.max_roles, + params.op.account.max_groups, params.op.account.max_buckets, + params.op.account.max_access_keys); + } +}; + +class RemoveAccountOp: virtual public DBOp { + private: + static constexpr std::string_view Query = + "DELETE from '{}' where AccountID = {}"; + + public: + virtual ~RemoveAccountOp() {} + + static std::string Schema(DBOpPrepareParams ¶ms) { + return fmt::format(Query, params.account_table, + params.op.account.account_id); + } +}; + +class GetAccountOp: virtual public DBOp { + private: + static constexpr std::string_view Query = "SELECT \ + AccountID, Tenant, AccountName, Email, \ + Quota, BucketQuota, MaxUsers, MaxRoles, MaxGroups, \ + MaxBuckets, MaxAccessKeys from '{}' where AccountID = {}"; + + static constexpr std::string_view QueryByName = "SELECT \ + AccountID, Tenant, AccountName, Email, \ + Quota, BucketQuota, MaxUsers, MaxRoles, MaxGroups, \ + MaxBuckets, MaxAccessKeys from '{}' where AccountName = {}"; + + static constexpr std::string_view QueryByEmail = "SELECT \ + AccountID, Tenant, AccountName, Email, \ + Quota, BucketQuota, MaxUsers, MaxRoles, MaxGroups, \ + MaxBuckets, MaxAccessKeys from '{}' where Email = {}"; + + public: + virtual ~GetAccountOp() {} + + static std::string Schema(DBOpPrepareParams ¶ms) { + if (params.op.query_str == "name") { + return fmt::format(QueryByName, params.account_table, + params.op.account.account_name); + } else if (params.op.query_str == "email") { + return fmt::format(QueryByEmail, params.account_table, + params.op.account.email); + } else { + return fmt::format(Query, params.account_table, + params.op.account.account_id); + } + } +}; + class InsertUserOp : virtual public DBOp { private: /* For existing entires, - @@ -1480,6 +1604,7 @@ class DB { private: const std::string db_name; rgw::sal::Driver* driver; + const std::string account_table; const std::string user_table; const std::string bucket_table; const std::string quota_table; @@ -1501,6 +1626,7 @@ class DB { public: DB(std::string db_name, CephContext *_cct) : db_name(db_name), + account_table(db_name+"_account_table"), user_table(db_name+"_user_table"), bucket_table(db_name+"_bucket_table"), quota_table(db_name+"_quota_table"), @@ -1512,6 +1638,7 @@ class DB { /* DB() {}*/ DB(CephContext *_cct) : db_name("default_db"), + account_table(db_name+"_account_table"), user_table(db_name+"_user_table"), bucket_table(db_name+"_bucket_table"), quota_table(db_name+"_quota_table"), @@ -1524,6 +1651,7 @@ class DB { const std::string getDBname() { return db_name; } const std::string getDBfile() { return db_name + ".db"; } + const std::string getAccountTable() { return account_table; } const std::string getUserTable() { return user_table; } const std::string getBucketTable() { return bucket_table; } const std::string getQuotaTable() { return quota_table; } @@ -1589,6 +1717,15 @@ class DB { RGWObjVersionTracker *pobjv_tracker, RGWUserInfo* pold_info); int remove_user(const DoutPrefixProvider *dpp, RGWUserInfo& uinfo, RGWObjVersionTracker *pobjv_tracker); + int get_account(const DoutPrefixProvider *dpp, + const std::string& query_str, const std::string& query_str_val, + RGWAccountInfo& ainfo, std::map *pattrs, + RGWObjVersionTracker *pobjv_tracker); + int store_account(const DoutPrefixProvider *dpp, + const RGWAccountInfo& ainfo, bool exclusive, const std::map *pattrs, + RGWObjVersionTracker *pobjv_tracker); + int remove_account(const DoutPrefixProvider *dpp, + const RGWAccountInfo &ainfo, RGWObjVersionTracker *pobjv_tracker); int get_bucket_info(const DoutPrefixProvider *dpp, const std::string& query_str, const std::string& query_str_val, RGWBucketInfo& info, rgw::sal::Attrs* pattrs, ceph::real_time* pmtime, diff --git a/src/rgw/driver/dbstore/sqlite/sqliteDB.cc b/src/rgw/driver/dbstore/sqlite/sqliteDB.cc index dc341ac7e98..ac573c4fd06 100644 --- a/src/rgw/driver/dbstore/sqlite/sqliteDB.cc +++ b/src/rgw/driver/dbstore/sqlite/sqliteDB.cc @@ -157,8 +157,8 @@ int SQLiteDB::InitPrepareParams(const DoutPrefixProvider *dpp, if (!params) return -1; - if (params->user_table.empty()) { - params->user_table = getUserTable(); + if (params->account_table.empty()) { + params->account_table = getAccountTable(); } if (params->user_table.empty()) { params->user_table = getUserTable(); @@ -176,6 +176,7 @@ int SQLiteDB::InitPrepareParams(const DoutPrefixProvider *dpp, params->lc_head_table = getLCHeadTable(); } + p_params.account_table = params->account_table; p_params.user_table = params->user_table; p_params.bucket_table = params->bucket_table; p_params.quota_table = params->quota_table; @@ -217,6 +218,20 @@ static int list_callback(void *None, int argc, char **argv, char **aname) return 0; } +enum GetAccount { + AccountID = 0, + AccountTenant, + AccountName, + Email, + AccountQuota, + AccountBucketQuota, + MaxUsers, + MaxRoles, + MaxGroups, + AccountMaxBuckets, + MaxAccessKeys, +}; + enum GetUser { UserID = 0, Tenant, @@ -359,6 +374,27 @@ enum GetLCHead { LCHeadStartDate }; +static int list_account(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) { + if (!stmt) + return -1; + + op.account.info.id = (const char*)sqlite3_column_text(stmt, AccountID); + op.account.info.tenant = (const char*)sqlite3_column_text(stmt, AccountTenant); + op.account.info.name = (const char*)sqlite3_column_text(stmt, AccountName); + op.account.info.email = (const char*)sqlite3_column_text(stmt, Email); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, AccountQuota, op.account.info.quota, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, AccountBucketQuota, op.account.info.bucket_quota, sdb); + + op.account.info.max_users = sqlite3_column_int(stmt, MaxUsers); + op.account.info.max_roles = sqlite3_column_int(stmt, MaxRoles); + op.account.info.max_groups = sqlite3_column_int(stmt, MaxGroups); + op.account.info.max_buckets = sqlite3_column_int(stmt, AccountMaxBuckets); + op.account.info.max_access_keys = sqlite3_column_int(stmt, MaxAccessKeys); + + return 0; +} + static int list_user(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) { if (!stmt) return -1; @@ -588,6 +624,9 @@ static int list_lc_head(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stm int SQLiteDB::InitializeDBOps(const DoutPrefixProvider *dpp) { (void)createTables(dpp); + dbops.InsertAccount = make_shared(&this->db, this->getDBname(), cct); + dbops.RemoveAccount = make_shared(&this->db, this->getDBname(), cct); + dbops.GetAccount = make_shared(&this->db, this->getDBname(), cct); dbops.InsertUser = make_shared(&this->db, this->getDBname(), cct); dbops.RemoveUser = make_shared(&this->db, this->getDBname(), cct); dbops.GetUser = make_shared(&this->db, this->getDBname(), cct); @@ -716,12 +755,16 @@ out: int SQLiteDB::createTables(const DoutPrefixProvider *dpp) { int ret = -1; - int cu = 0, cb = 0, cq = 0; + int ca = 0, cu = 0, cb = 0, cq = 0; DBOpParams params = {}; + params.account_table = getAccountTable(); params.user_table = getUserTable(); params.bucket_table = getBucketTable(); + if ((ca = createAccountTable(dpp, ¶ms))) + goto out; + if ((cu = createUserTable(dpp, ¶ms))) goto out; @@ -734,6 +777,8 @@ int SQLiteDB::createTables(const DoutPrefixProvider *dpp) ret = 0; out: if (ret) { + if (ca) + DeleteAccountTable(dpp, ¶ms); if (cu) DeleteUserTable(dpp, ¶ms); if (cb) @@ -744,6 +789,22 @@ out: return ret; } +int SQLiteDB::createAccountTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = CreateTableSchema("Account", params); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"CreateAccountTable failed" << dendl; + + ldpp_dout(dpp, 20)<<"CreateAccountTable succeeded" << dendl; + + return ret; +} + int SQLiteDB::createUserTable(const DoutPrefixProvider *dpp, DBOpParams *params) { int ret = -1; @@ -885,6 +946,22 @@ int SQLiteDB::createLCTables(const DoutPrefixProvider *dpp) return ret; } +int SQLiteDB::DeleteAccountTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = DeleteTableSchema(params->account_table); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"DeleteAccountTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"DeleteAccountTable succeeded " << dendl; + + return ret; +} + int SQLiteDB::DeleteUserTable(const DoutPrefixProvider *dpp, DBOpParams *params) { int ret = -1; @@ -1069,6 +1146,174 @@ int SQLObjectOp::InitializeObjectOps(string db_name, const DoutPrefixProvider *d return 0; } +int SQLInsertAccount::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLInsertAccount - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareInsertAccount"); +out: + return ret; +} + +int SQLInsertAccount::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.account_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.tenant, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.tenant.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.account_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.email, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.email.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.quota, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.account.info.quota, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.bucket_quota, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.account.info.bucket_quota, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_users, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_users, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_roles, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_roles, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_groups, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_groups, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_buckets, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_buckets, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.max_access_keys, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.account.info.max_access_keys, sdb); + +out: + return rc; +} + +int SQLInsertAccount::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLRemoveAccount::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLRemoveAccount - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareRemoveAccount"); +out: + return ret; +} + +int SQLRemoveAccount::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.account_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.id.c_str(), sdb); + +out: + return rc; +} + +int SQLRemoveAccount::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLGetAccount::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLGetAccount - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + if (params->op.query_str == "name") { + SQL_PREPARE(dpp, p_params, sdb, name_stmt, ret, "PrepareGetAccount"); + } else if (params->op.query_str == "email") { + SQL_PREPARE(dpp, p_params, sdb, email_stmt, ret, "PrepareGetAccount"); + } else { // by default by account_id + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareGetAccount"); + } +out: + return ret; +} + +int SQLGetAccount::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.query_str == "name") { + SQL_BIND_INDEX(dpp, name_stmt, index, p_params.op.account.account_name, sdb); + SQL_BIND_TEXT(dpp, name_stmt, index, params->op.account.info.name.c_str(), sdb); + } else if (params->op.query_str == "email") { + SQL_BIND_INDEX(dpp, email_stmt, index, p_params.op.account.email, sdb); + SQL_BIND_TEXT(dpp, email_stmt, index, params->op.account.info.email.c_str(), sdb); + } else { // by default by account_id + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.account.account_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.account.info.id.c_str(), sdb); + } + +out: + return rc; +} + +int SQLGetAccount::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + if (params->op.query_str == "name") { + SQL_EXECUTE(dpp, params, name_stmt, list_account); + } else if (params->op.query_str == "email") { + SQL_EXECUTE(dpp, params, email_stmt, list_account); + } else { // by default by account_id + SQL_EXECUTE(dpp, params, stmt, list_account); + } + +out: + return ret; +} + int SQLInsertUser::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) { int ret = -1; diff --git a/src/rgw/driver/dbstore/sqlite/sqliteDB.h b/src/rgw/driver/dbstore/sqlite/sqliteDB.h index acc64e7f5ea..342224d1614 100644 --- a/src/rgw/driver/dbstore/sqlite/sqliteDB.h +++ b/src/rgw/driver/dbstore/sqlite/sqliteDB.h @@ -45,6 +45,7 @@ class SQLiteDB : public DB, virtual public DBOp { /* default value matches with sqliteDB style */ int createTables(const DoutPrefixProvider *dpp) override; + int createAccountTable(const DoutPrefixProvider *dpp, DBOpParams *params); int createBucketTable(const DoutPrefixProvider *dpp, DBOpParams *params); int createUserTable(const DoutPrefixProvider *dpp, DBOpParams *params); int createObjectTable(const DoutPrefixProvider *dpp, DBOpParams *params); @@ -58,6 +59,7 @@ class SQLiteDB : public DB, virtual public DBOp { int createLCTables(const DoutPrefixProvider *dpp) override; + int DeleteAccountTable(const DoutPrefixProvider *dpp, DBOpParams *params); int DeleteBucketTable(const DoutPrefixProvider *dpp, DBOpParams *params); int DeleteUserTable(const DoutPrefixProvider *dpp, DBOpParams *params); int DeleteObjectTable(const DoutPrefixProvider *dpp, DBOpParams *params); @@ -83,6 +85,60 @@ class SQLObjectOp : public ObjectOp { int InitializeObjectOps(std::string db_name, const DoutPrefixProvider *dpp); }; +class SQLInsertAccount : public SQLiteDB, public InsertAccountOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLInsertAccount(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLInsertAccount() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLRemoveAccount : public SQLiteDB, public RemoveAccountOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLRemoveAccount(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLRemoveAccount() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLGetAccount : public SQLiteDB, public GetAccountOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + sqlite3_stmt *name_stmt = NULL; // Prepared statement to query by account name + sqlite3_stmt *email_stmt = NULL; // Prepared statement to query by email + + public: + SQLGetAccount(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLGetAccount() { + if (stmt) + sqlite3_finalize(stmt); + if (name_stmt) + sqlite3_finalize(name_stmt); + if (email_stmt) + sqlite3_finalize(email_stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + class SQLInsertUser : public SQLiteDB, public InsertUserOp { private: sqlite3 **sdb = NULL; diff --git a/src/rgw/driver/posix/posixDB.cc b/src/rgw/driver/posix/posixDB.cc index e56697d25b2..bbbe69917d6 100644 --- a/src/rgw/driver/posix/posixDB.cc +++ b/src/rgw/driver/posix/posixDB.cc @@ -108,5 +108,76 @@ int POSIXUserDB::Destroy(const DoutPrefixProvider *dpp) return 0; } +int POSIXAccountDB::ProcessOp(const DoutPrefixProvider *dpp, string_view Op, DBOpParams *params) { + int ret = -1; + shared_ptr db_op; + + db_op = getDBOp(dpp, Op, params); + + if (!db_op) { + ldpp_dout(dpp, 0)<<"No db_op found for Op("<Execute(dpp, params); + + if (ret) { + ldpp_dout(dpp, 0)<<"In Process op Execute failed for fop(" << Op << ")" << dendl; + } else { + ldpp_dout(dpp, 20)<<"Successfully processed fop(" << Op << ")" << dendl; + } + + return ret; +} + +int POSIXAccountDB::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) <<"InitializePOSIXAccountDBOps failed " << dendl; + closeDB(dpp); + db = NULL; + return ret; + } + + ldpp_dout(dpp, 0) << "POSIXAccountDB successfully initialized - name:" \ + << db_name << "" << dendl; + + return ret; +} + +int POSIXAccountDB::Destroy(const DoutPrefixProvider *dpp) +{ + DB::Destroy(dpp); + + ldpp_dout(dpp, 20)<<"POSIXAccountDB successfully destroyed - name:" \ + <cct; } + + virtual int InitPrepareParams(const DoutPrefixProvider *dpp, + DBOpPrepareParams &p_params, + DBOpParams* params) override { return 0; } + virtual int createLCTables(const DoutPrefixProvider *dpp) override { return 0; } + + virtual int ListAllBuckets(const DoutPrefixProvider *dpp, DBOpParams *params) override { return 0; } + virtual int ListAllUsers(const DoutPrefixProvider *dpp, DBOpParams *params) override { return 0; } + virtual int ListAllObjects(const DoutPrefixProvider *dpp, DBOpParams *params) override { return 0; } +}; + } } // namespace rgw::store diff --git a/src/rgw/driver/posix/rgw_sal_posix.cc b/src/rgw/driver/posix/rgw_sal_posix.cc index 0299404f65c..c1cb6a7a0e8 100644 --- a/src/rgw/driver/posix/rgw_sal_posix.cc +++ b/src/rgw/driver/posix/rgw_sal_posix.cc @@ -2034,6 +2034,94 @@ int POSIXDriver::get_user_by_swift(const DoutPrefixProvider* dpp, const std::str return -ENOTSUP; } +int POSIXDriver::load_account_by_id(const DoutPrefixProvider* dpp, + optional_yield y, + std::string_view id, + RGWAccountInfo& info, + Attrs& attrs, + RGWObjVersionTracker& objv) +{ + RGWObjVersionTracker objv_tracker; + + int ret = accountDB->get_account(dpp, std::string("account_id"), std::string(id), info, &attrs, + &objv_tracker); + + if (ret < 0) + return ret; + + objv = objv_tracker; + return 0; +} + +int POSIXDriver::load_account_by_name(const DoutPrefixProvider* dpp, + optional_yield y, + std::string_view tenant, + std::string_view name, + RGWAccountInfo& info, + Attrs& attrs, + RGWObjVersionTracker& objv) +{ + RGWObjVersionTracker objv_tracker; + + int ret = accountDB->get_account(dpp, std::string("name"), std::string(name), info, &attrs, + &objv_tracker); + + if (ret < 0) + return ret; + + objv = objv_tracker; + return 0; +} + +int POSIXDriver::load_account_by_email(const DoutPrefixProvider* dpp, + optional_yield y, + std::string_view email, + RGWAccountInfo& info, + Attrs& attrs, + RGWObjVersionTracker& objv) +{ + RGWObjVersionTracker objv_tracker; + + int ret = accountDB->get_account(dpp, std::string("email"), std::string(email), info, &attrs, + &objv_tracker); + + if (ret < 0) + return ret; + + objv = objv_tracker; + return 0; +} + +int POSIXDriver::store_account(const DoutPrefixProvider* dpp, + optional_yield y, bool exclusive, + const RGWAccountInfo& info, + const RGWAccountInfo* old_info, + const Attrs& attrs, + RGWObjVersionTracker& objv) +{ + int ret = accountDB->store_account(dpp, info, exclusive, &attrs, &objv); + + if (ret < 0) + return ret; + + return 0; +} + +int POSIXDriver::delete_account(const DoutPrefixProvider* dpp, + optional_yield y, + const RGWAccountInfo& info, + RGWObjVersionTracker& objv) +{ + int ret = accountDB->remove_account(dpp, info, &objv); + + if (ret < 0) + return ret; + + return 0; +} + + + int POSIXDriver::load_owner_by_email(const DoutPrefixProvider* dpp, optional_yield y, std::string_view email, diff --git a/src/rgw/driver/posix/rgw_sal_posix.h b/src/rgw/driver/posix/rgw_sal_posix.h index 4edc8b13abe..32e8c085a0f 100644 --- a/src/rgw/driver/posix/rgw_sal_posix.h +++ b/src/rgw/driver/posix/rgw_sal_posix.h @@ -475,6 +475,7 @@ class POSIXDriver : public StoreDriver { protected: CephContext *cct; std::unique_ptr userDB; + std::unique_ptr accountDB; POSIXZone zone; std::unique_ptr bucket_cache; std::string base_path; @@ -491,6 +492,7 @@ public: auto db_full_path = std::filesystem::path(db_path) / db_name; userDB = std::make_unique(db_full_path.string(), cct); + accountDB = std::make_unique(db_full_path.string(), cct); } virtual ~POSIXDriver() { } @@ -518,32 +520,32 @@ public: std::string_view id, RGWAccountInfo& info, Attrs& attrs, - RGWObjVersionTracker& objv) override { return -ENOTSUP; } + RGWObjVersionTracker& objv) override; virtual int load_account_by_name(const DoutPrefixProvider* dpp, optional_yield y, std::string_view tenant, std::string_view name, RGWAccountInfo& info, Attrs& attrs, - RGWObjVersionTracker& objv) override { return -ENOTSUP; } + RGWObjVersionTracker& objv) override; virtual int load_account_by_email(const DoutPrefixProvider* dpp, optional_yield y, std::string_view email, RGWAccountInfo& info, Attrs& attrs, - RGWObjVersionTracker& objv) override { return -ENOTSUP; } + RGWObjVersionTracker& objv) override; virtual int store_account(const DoutPrefixProvider* dpp, optional_yield y, bool exclusive, const RGWAccountInfo& info, const RGWAccountInfo* old_info, const Attrs& attrs, - RGWObjVersionTracker& objv) override { return -ENOTSUP; } + RGWObjVersionTracker& objv) override; virtual int delete_account(const DoutPrefixProvider* dpp, optional_yield y, const RGWAccountInfo& info, - RGWObjVersionTracker& objv) override { return -ENOTSUP; } + RGWObjVersionTracker& objv) override; virtual int load_stats(const DoutPrefixProvider* dpp, optional_yield y,