Skip to content

Commit

Permalink
rgw: add account admin ops
Browse files Browse the repository at this point in the history
Signed-off-by: Casey Bodley <cbodley@redhat.com>
  • Loading branch information
cbodley committed Apr 10, 2024
1 parent 91a5885 commit 6c834d6
Show file tree
Hide file tree
Showing 2 changed files with 310 additions and 0 deletions.
263 changes: 263 additions & 0 deletions src/rgw/rgw_account.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
47 changes: 47 additions & 0 deletions src/rgw/rgw_account.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,18 @@

#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
Expand All @@ -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

0 comments on commit 6c834d6

Please sign in to comment.