]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add account admin ops
authorCasey Bodley <cbodley@redhat.com>
Wed, 1 Nov 2023 22:16:45 +0000 (18:16 -0400)
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/rgw_account.cc
src/rgw/rgw_account.h

index a895b9bcfeef5f427ca1842673f8ca713493baf6..5d5371b963d6b548da12a788fb297f42b31cb28c 100644 (file)
@@ -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
index 17ed0c06210d8ef0c8672d80c023f365e5eb674c..77969363261d7d45394a4845d3fe67c4efd2777f 100644 (file)
 
 #pragma once
 
+#include <cstdint>
+#include <optional>
 #include <string>
+
 #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<int32_t> max_users;
+  std::optional<int32_t> max_roles;
+  std::optional<int32_t> max_groups;
+  std::optional<int32_t> max_access_keys;
+  std::optional<int32_t> 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