From 85e3a34ec3ee8c2615d0c756b85ab398cefe7e1e Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Wed, 1 Nov 2023 18:16:45 -0400 Subject: [PATCH] rgw: add account admin ops Signed-off-by: Casey Bodley (cherry picked from commit 6c834d6d38128dc03bb088f133f4bef6c0a711b9) --- src/rgw/rgw_account.cc | 263 +++++++++++++++++++++++++++++++++++++++++ src/rgw/rgw_account.h | 47 ++++++++ 2 files changed, 310 insertions(+) diff --git a/src/rgw/rgw_account.cc b/src/rgw/rgw_account.cc index a895b9bcfee..5d5371b963d 100644 --- a/src/rgw/rgw_account.cc +++ b/src/rgw/rgw_account.cc @@ -21,6 +21,8 @@ #include "common/random_string.h" #include "common/utf8.h" +#include "rgw_sal.h" + #define dout_subsys ceph_subsys_rgw namespace rgw::account { @@ -96,4 +98,265 @@ bool validate_name(std::string_view name, std::string* err_msg) return true; } + +int create(const DoutPrefixProvider* dpp, + rgw::sal::Driver* driver, + AdminOpState& op_state, + std::string& err_msg, + RGWFormatterFlusher& flusher, + optional_yield y) +{ + // validate account name if specified + if (!op_state.account_name.empty() && + !validate_name(op_state.account_name, &err_msg)) { + return -EINVAL; + } + + auto info = RGWAccountInfo{ + .tenant = op_state.tenant, + .name = op_state.account_name, + .email = op_state.email, + }; + + if (op_state.max_users) { + info.max_users = *op_state.max_users; + } + if (op_state.max_roles) { + info.max_roles = *op_state.max_roles; + } + if (op_state.max_groups) { + info.max_groups = *op_state.max_groups; + } + if (op_state.max_access_keys) { + info.max_access_keys = *op_state.max_access_keys; + } + if (op_state.max_buckets) { + info.max_buckets = *op_state.max_buckets; + } + + // account id is optional, but must be valid + if (op_state.account_id.empty()) { + info.id = generate_id(dpp->get_cct()); + } else if (!validate_id(op_state.account_id, &err_msg)) { + return -EINVAL; + } else { + info.id = op_state.account_id; + } + + constexpr RGWAccountInfo* old_info = nullptr; + constexpr bool exclusive = true; + rgw::sal::Attrs attrs; + RGWObjVersionTracker objv; + objv.generate_new_write_ver(dpp->get_cct()); + + int ret = driver->store_account(dpp, y, exclusive, info, + old_info, attrs, objv); + if (ret < 0) { + return ret; + } + + flusher.start(0); + encode_json("AccountInfo", info, flusher.get_formatter()); + flusher.flush(); + + return 0; +} + +int modify(const DoutPrefixProvider* dpp, + rgw::sal::Driver* driver, + AdminOpState& op_state, + std::string& err_msg, + RGWFormatterFlusher& flusher, + optional_yield y) +{ + int ret = 0; + RGWAccountInfo info; + rgw::sal::Attrs attrs; + RGWObjVersionTracker objv; + if (!op_state.account_id.empty()) { + ret = driver->load_account_by_id(dpp, y, op_state.account_id, + info, attrs, objv); + } else if (!op_state.account_name.empty()) { + ret = driver->load_account_by_name(dpp, y, op_state.tenant, + op_state.account_name, + info, attrs, objv); + } else if (!op_state.email.empty()) { + ret = driver->load_account_by_email(dpp, y, op_state.email, + info, attrs, objv); + } else { + err_msg = "requires --account-id or --account-name or --email"; + return -EINVAL; + } + if (ret < 0) { + return ret; + } + const RGWAccountInfo old_info = info; + + if (!op_state.tenant.empty() && op_state.tenant != info.tenant) { + err_msg = "cannot modify account tenant"; + return -EINVAL; + } + + if (!op_state.account_name.empty()) { + // name must be valid + if (!validate_name(op_state.account_name, &err_msg)) { + return -EINVAL; + } + info.name = op_state.account_name; + } + + if (!op_state.email.empty()) { + info.email = op_state.email; + } + + if (op_state.max_users) { + info.max_users = *op_state.max_users; + } + if (op_state.max_roles) { + info.max_roles = *op_state.max_roles; + } + if (op_state.max_groups) { + info.max_groups = *op_state.max_groups; + } + if (op_state.max_access_keys) { + info.max_access_keys = *op_state.max_access_keys; + } + if (op_state.max_buckets) { + info.max_buckets = *op_state.max_buckets; + } + + constexpr bool exclusive = false; + + ret = driver->store_account(dpp, y, exclusive, info, &old_info, attrs, objv); + if (ret < 0) { + return ret; + } + + flusher.start(0); + encode_json("AccountInfo", info, flusher.get_formatter()); + flusher.flush(); + + return 0; +} + +int remove(const DoutPrefixProvider* dpp, + rgw::sal::Driver* driver, + AdminOpState& op_state, + std::string& err_msg, + RGWFormatterFlusher& flusher, + optional_yield y) +{ + int ret = 0; + RGWAccountInfo info; + rgw::sal::Attrs attrs; + RGWObjVersionTracker objv; + + if (!op_state.account_id.empty()) { + ret = driver->load_account_by_id(dpp, y, op_state.account_id, + info, attrs, objv); + } else if (!op_state.account_name.empty()) { + ret = driver->load_account_by_name(dpp, y, op_state.tenant, + op_state.account_name, + info, attrs, objv); + } else if (!op_state.email.empty()) { + ret = driver->load_account_by_email(dpp, y, op_state.email, + info, attrs, objv); + } else { + err_msg = "requires --account-id or --account-name or --email"; + return -EINVAL; + } + if (ret < 0) { + return ret; + } + + return driver->delete_account(dpp, y, info, objv); +} + +int info(const DoutPrefixProvider* dpp, + rgw::sal::Driver* driver, + AdminOpState& op_state, + std::string& err_msg, + RGWFormatterFlusher& flusher, + optional_yield y) +{ + int ret = 0; + RGWAccountInfo info; + rgw::sal::Attrs attrs; + RGWObjVersionTracker objv; + + if (!op_state.account_id.empty()) { + ret = driver->load_account_by_id(dpp, y, op_state.account_id, + info, attrs, objv); + } else if (!op_state.account_name.empty()) { + ret = driver->load_account_by_name(dpp, y, op_state.tenant, + op_state.account_name, + info, attrs, objv); + } else if (!op_state.email.empty()) { + ret = driver->load_account_by_email(dpp, y, op_state.email, + info, attrs, objv); + } else { + err_msg = "requires --account-id or --account-name or --email"; + return -EINVAL; + } + if (ret < 0) { + return ret; + } + + flusher.start(0); + encode_json("AccountInfo", info, flusher.get_formatter()); + flusher.flush(); + + return 0; +} + +int stats(const DoutPrefixProvider* dpp, + rgw::sal::Driver* driver, + AdminOpState& op_state, + std::string& err_msg, + RGWFormatterFlusher& flusher, + optional_yield y) +{ + int ret = 0; + std::string account_id; + + if (!op_state.account_id.empty()) { + account_id = op_state.account_id; + } else if (!op_state.account_name.empty()) { + // look up account id by name + RGWAccountInfo info; + rgw::sal::Attrs attrs; + RGWObjVersionTracker objv; + ret = driver->load_account_by_name(dpp, y, op_state.tenant, + op_state.account_name, + info, attrs, objv); + if (ret < 0) { + return ret; + } + account_id = std::move(info.id); + } else { + err_msg = "requires account id or name"; + return -EINVAL; + } + + RGWStorageStats stats; + ceph::real_time last_synced; + ceph::real_time last_updated; + ret = driver->load_account_stats(dpp, y, account_id, stats, + last_synced, last_updated); + if (ret < 0) { + return ret; + } + + flusher.start(0); + auto f = flusher.get_formatter(); + f->open_object_section("AccountStats"); + encode_json("stats", stats, f); + encode_json("last_synced", last_synced, f); + encode_json("last_updated", last_updated, f); + f->close_section(); // AccountStats + flusher.flush(); + + return 0; +} + } // namespace rgw::account diff --git a/src/rgw/rgw_account.h b/src/rgw/rgw_account.h index 17ed0c06210..77969363261 100644 --- a/src/rgw/rgw_account.h +++ b/src/rgw/rgw_account.h @@ -15,9 +15,18 @@ #pragma once +#include +#include #include + #include "include/common_fwd.h" +#include "rgw_sal_fwd.h" + +class DoutPrefixProvider; +class RGWFormatterFlusher; +class optional_yield; + namespace rgw::account { /// generate a randomized account id in a specific format @@ -29,4 +38,42 @@ bool validate_id(std::string_view id, std::string* err_msg = nullptr); /// check an account name for any invalid characters bool validate_name(std::string_view name, std::string* err_msg = nullptr); + +struct AdminOpState { + std::string account_id; + std::string tenant; + std::string account_name; + std::string email; + std::optional max_users; + std::optional max_roles; + std::optional max_groups; + std::optional max_access_keys; + std::optional max_buckets; +}; + +/// create an account +int create(const DoutPrefixProvider* dpp, rgw::sal::Driver* driver, + AdminOpState& op_state, std::string& err_msg, + RGWFormatterFlusher& flusher, optional_yield y); + +/// modify an existing account +int modify(const DoutPrefixProvider* dpp, rgw::sal::Driver* driver, + AdminOpState& op_state, std::string& err_msg, + RGWFormatterFlusher& flusher, optional_yield y); + +/// remove an existing account +int remove(const DoutPrefixProvider* dpp, rgw::sal::Driver* driver, + AdminOpState& op_state, std::string& err_msg, + RGWFormatterFlusher& flusher, optional_yield y); + +/// dump RGWAccountInfo +int info(const DoutPrefixProvider* dpp, rgw::sal::Driver* driver, + AdminOpState& op_state, std::string& err_msg, + RGWFormatterFlusher& flusher, optional_yield y); + +/// dump account storage stats +int stats(const DoutPrefixProvider* dpp, rgw::sal::Driver* driver, + AdminOpState& op_state, std::string& err_msg, + RGWFormatterFlusher& flusher, optional_yield y); + } // namespace rgw::account -- 2.39.5