From: Casey Bodley Date: Thu, 18 Apr 2024 16:14:14 +0000 (-0400) Subject: rgw/account: add bucket_quota to RGWAccountInfo X-Git-Tag: v19.1.0~34^2~1 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=9cb03f5ceecf135331d6a869c365afda0a57ac50;p=ceph.git rgw/account: add bucket_quota to RGWAccountInfo support bucket quotas per account the same way as for user Fixes: https://tracker.ceph.com/issues/65551 Signed-off-by: Casey Bodley (cherry picked from commit b9677714b2a57e4f97ff87c9d654f4dddae3c2b2) --- diff --git a/doc/radosgw/account.rst b/doc/radosgw/account.rst index 28c70fc031073..15fb91c9e84bc 100644 --- a/doc/radosgw/account.rst +++ b/doc/radosgw/account.rst @@ -153,8 +153,13 @@ To view account stats:: To enable an account quota:: - radosgw-admin quota set --account-id={accountid} --max-size=10G - radosgw-admin quota enable --account-id={accountid} + radosgw-admin quota set --quota-scope=account --account-id={accountid} --max-size=10G + radosgw-admin quota enable --quota-scope=account --account-id={accountid} + +To enable a bucket quota for the account:: + + radosgw-admin quota set --quota-scope=bucket --account-id={accountid} --max-objects=1000000 + radosgw-admin quota enable --quota-scope=bucket --account-id={accountid} Migrate an existing User into an Account ---------------------------------------- diff --git a/src/rgw/rgw_account.cc b/src/rgw/rgw_account.cc index 44aa9a3d4c7af..d7e9acd7f5168 100644 --- a/src/rgw/rgw_account.cc +++ b/src/rgw/rgw_account.cc @@ -227,14 +227,22 @@ int modify(const DoutPrefixProvider* dpp, info.max_buckets = *op_state.max_buckets; } - if (op_state.quota_max_size) { - info.quota.max_size = *op_state.quota_max_size; - } - if (op_state.quota_max_objects) { - info.quota.max_objects = *op_state.quota_max_objects; - } - if (op_state.quota_enabled) { - info.quota.enabled = *op_state.quota_enabled; + RGWQuotaInfo* pquota = nullptr; + if (op_state.quota_scope == "account") { + pquota = &info.quota; + } else if (op_state.quota_scope == "bucket") { + pquota = &info.bucket_quota; + } + if (pquota) { + if (op_state.quota_max_size) { + pquota->max_size = *op_state.quota_max_size; + } + if (op_state.quota_max_objects) { + pquota->max_objects = *op_state.quota_max_objects; + } + if (op_state.quota_enabled) { + pquota->enabled = *op_state.quota_enabled; + } } constexpr bool exclusive = false; diff --git a/src/rgw/rgw_account.h b/src/rgw/rgw_account.h index f942d674b0ec5..2a6f3e2379751 100644 --- a/src/rgw/rgw_account.h +++ b/src/rgw/rgw_account.h @@ -49,6 +49,7 @@ struct AdminOpState { std::optional max_groups; std::optional max_access_keys; std::optional max_buckets; + std::string quota_scope; std::optional quota_max_size; std::optional quota_max_objects; std::optional quota_enabled; diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index b9dc45a741859..ec439e6618fbf 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -468,7 +468,7 @@ void usage() cout << "\nQuota options:\n"; cout << " --max-objects specify max objects (negative value to disable)\n"; cout << " --max-size specify max size (in B/K/M/G/T, negative value to disable)\n"; - cout << " --quota-scope scope of quota (bucket, user)\n"; + cout << " --quota-scope scope of quota (bucket, user, account)\n"; cout << "\nRate limiting options:\n"; cout << " --max-read-ops specify max requests per minute for READ ops per RGW (GET and HEAD request methods), 0 means unlimited\n"; cout << " --max-read-bytes specify max bytes per minute for READ ops per RGW (GET and HEAD request methods), 0 means unlimited\n"; @@ -10666,6 +10666,13 @@ next: op_state.tenant = tenant; op_state.account_name = account_name; + if (quota_scope != "bucket" && quota_scope != "account") { + cerr << "ERROR: invalid quota scope specification. Please specify " + "either --quota-scope=bucket or --quota-scope=account" << std::endl; + return EINVAL; + } + op_state.quota_scope = quota_scope; + if (opt_cmd == OPT::QUOTA_ENABLE) { op_state.quota_enabled = true; } else if (opt_cmd == OPT::QUOTA_DISABLE) { diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index f5b834e0672d3..4c9203093487e 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -3018,6 +3018,7 @@ void RGWAccountInfo::dump(Formatter * const f) const encode_json("name", name, f); encode_json("email", email, f); encode_json("quota", quota, f); + encode_json("bucket_quota", bucket_quota, f); encode_json("max_users", max_users, f); encode_json("max_roles", max_roles, f); encode_json("max_groups", max_groups, f); @@ -3032,6 +3033,7 @@ void RGWAccountInfo::decode_json(JSONObj* obj) JSONDecoder::decode_json("name", name, obj); JSONDecoder::decode_json("email", email, obj); JSONDecoder::decode_json("quota", quota, obj); + JSONDecoder::decode_json("bucket_quota", bucket_quota, obj); JSONDecoder::decode_json("max_users", max_users, obj); JSONDecoder::decode_json("max_roles", max_roles, obj); JSONDecoder::decode_json("max_groups", max_groups, obj); diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 63e7f9eacc1f3..c95acae4510ee 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -787,6 +787,7 @@ struct RGWAccountInfo { std::string name; std::string email; RGWQuotaInfo quota; + RGWQuotaInfo bucket_quota; static constexpr int32_t DEFAULT_USER_LIMIT = 1000; int32_t max_users = DEFAULT_USER_LIMIT; @@ -804,7 +805,7 @@ struct RGWAccountInfo { int32_t max_access_keys = DEFAULT_ACCESS_KEY_LIMIT; void encode(bufferlist& bl) const { - ENCODE_START(1, 1, bl); + ENCODE_START(2, 1, bl); encode(id, bl); encode(tenant, bl); encode(name, bl); @@ -815,11 +816,12 @@ struct RGWAccountInfo { encode(max_groups, bl); encode(max_buckets, bl); encode(max_access_keys, bl); + encode(bucket_quota, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { - DECODE_START(1, bl); + DECODE_START(2, bl); decode(id, bl); decode(tenant, bl); decode(name, bl); @@ -830,6 +832,9 @@ struct RGWAccountInfo { decode(max_groups, bl); decode(max_buckets, bl); decode(max_access_keys, bl); + if (struct_v >= 2) { + decode(bucket_quota, bl); + } DECODE_FINISH(bl); } diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 481e14b541647..602280182d7a7 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -1408,8 +1408,8 @@ static int get_owner_quota_info(DoutPrefixProvider* dpp, RGWObjVersionTracker objv; // ignored int r = driver->load_account_by_id(dpp, y, account_id, info, attrs, objv); if (r >= 0) { - // no bucket quota quotas.user_quota = info.quota; + quotas.bucket_quota = info.bucket_quota; } return r; }), owner); diff --git a/src/test/cli/radosgw-admin/help.t b/src/test/cli/radosgw-admin/help.t index af29e827591dd..b334806398bb2 100644 --- a/src/test/cli/radosgw-admin/help.t +++ b/src/test/cli/radosgw-admin/help.t @@ -336,7 +336,7 @@ Quota options: --max-objects specify max objects (negative value to disable) --max-size specify max size (in B/K/M/G/T, negative value to disable) - --quota-scope scope of quota (bucket, user) + --quota-scope scope of quota (bucket, user, account) Rate limiting options: --max-read-ops specify max requests per minute for READ ops per RGW (GET and HEAD request methods), 0 means unlimited