formatter->dump_string("display_name", info.display_name);
formatter->dump_string("email", info.user_email);
formatter->dump_int("suspended", (int)info.suspended);
+ formatter->dump_int("max_buckets", (int)info.max_buckets);
// subusers
formatter->open_array_section("subusers");
int skip_zero_entries = false; // log show
int purge_keys = false;
int yes_i_really_mean_it = false;
+ int max_buckets = -1;
std::string val;
std::ostringstream errs;
exit(EXIT_FAILURE);
}
auid = tmp;
+ } else if (ceph_argparse_witharg(args, i, &val, "--max-buckets", (char*)NULL)) {
+ max_buckets = atoi(val.c_str());
} else if (ceph_argparse_witharg(args, i, &val, "--date", (char*)NULL)) {
date = val;
if (end_date.empty())
case OPT_KEY_CREATE:
if (!user_id.empty())
info.user_id = user_id;
+ if (max_buckets >= 0)
+ info.max_buckets = max_buckets;
if (key_type == KEY_TYPE_SWIFT) {
access_key = info.user_id;
access_key.append(":");
#define RGW_SUSPENDED_USER_AUID (uint64_t)-2
+#define RGW_DEFAULT_MAX_BUCKETS 1000
+
#define CGI_PRINTF(state, format, ...) do { \
int __ret = FCGX_FPrintF(state->fcgx->out, format, __VA_ARGS__); \
if (state->header_ended) \
#define ERR_INVALID_UTF8 2017
#define ERR_UNPROCESSABLE_ENTITY 2018
#define ERR_TOO_LARGE 2019
+#define ERR_TOO_MANY_BUCKETS 2020
#define ERR_USER_SUSPENDED 2100
#define ERR_INTERNAL_ERROR 2200
map<string, RGWAccessKey> swift_keys;
map<string, RGWSubUser> subusers;
__u8 suspended;
+ uint32_t max_buckets;
- RGWUserInfo() : auid(0), suspended(0) {}
+ RGWUserInfo() : auid(0), suspended(0), max_buckets(RGW_DEFAULT_MAX_BUCKETS) {}
void encode(bufferlist& bl) const {
- ENCODE_START(9, 9, bl);
+ ENCODE_START(10, 9, bl);
::encode(auid, bl);
string access_key;
string secret_key;
::encode(subusers, bl);
::encode(suspended, bl);
::encode(swift_keys, bl);
+ ::encode(max_buckets, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator& bl) {
- DECODE_START_LEGACY_COMPAT_LEN_32(9, 9, 9, bl);
+ DECODE_START_LEGACY_COMPAT_LEN_32(10, 9, 9, bl);
if (struct_v >= 2) ::decode(auid, bl);
else auid = CEPH_AUTH_UID_DEFAULT;
string access_key;
if (struct_v >= 8) {
::decode(swift_keys, bl);
}
+ if (struct_v >= 10) {
+ ::decode(max_buckets, bl);
+ } else {
+ max_buckets = RGW_DEFAULT_MAX_BUCKETS;
+ }
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
if (!rgw_user_is_authenticated(s->user))
return -EACCES;
+ if (s->user.max_buckets) {
+ RGWUserBuckets buckets;
+ int ret = rgw_read_user_buckets(s->user.user_id, buckets, false);
+ if (ret < 0)
+ return ret;
+
+ if (buckets.count() >= s->user.max_buckets) {
+ return -ERR_TOO_MANY_BUCKETS;
+ }
+ }
+
return 0;
}
{ ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" },
{ ERR_REQUEST_TIMEOUT, 400, "RequestTimeout" },
{ ERR_TOO_LARGE, 400, "EntityTooLarge" },
+ { ERR_TOO_MANY_BUCKETS, 400, "TooManyBuckets" },
{ ERR_LENGTH_REQUIRED, 411, "MissingContentLength" },
{ EACCES, 403, "AccessDenied" },
{ EPERM, 403, "AccessDenied" },
* Cleanup data structure
*/
void clear() { buckets.clear(); }
+
+ size_t count() { return buckets.size(); }
};
WRITE_CLASS_ENCODER(RGWUserBuckets)