Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jewel: rgw: default quota fixes #10832

Merged
3 commits merged into from Oct 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions doc/radosgw/admin.rst
Expand Up @@ -400,6 +400,15 @@ To see how much of the quota a user has consumed, execute the following::
.. note:: You should execute ``radosgw-admin user stats`` with the
``--sync-stats`` option to receive the latest data.

Default Quotas
--------------

You can set default quotas in the config. These defaults are used when
creating a new user and have no effect on existing users. If the
relevant default quota is set in config, then that quota is set on the
new user, and that quota is enabled. See ``rgw bucket default quota max objects``,
``rgw bucket default quota max size``, ``rgw user default quota max objects``, and
``rgw user default quota max size`` in `Ceph Object Gateway Config Reference`_

Reading / Writing Global Quotas
-------------------------------
Expand Down Expand Up @@ -468,3 +477,4 @@ ranges for trim operations. ::

.. _radosgw-admin: ../../man/8/radosgw-admin/
.. _Pool Configuration: ../../rados/configuration/pool-pg-config-ref/
.. _Ceph Object Gateway Config Reference: ../config-ref/
34 changes: 34 additions & 0 deletions doc/radosgw/config-ref.rst
Expand Up @@ -346,6 +346,40 @@ Ceph configuration file, the default value will be set automatically.
:Type: Boolean
:Default: ``false``


``rgw bucket default quota max objects``

:Description: Default max number of objects per bucket. Set on new users,
if no other quota is specified. Has no effect on existing users.
:Type: Integer
:Default: ``-1``


``rgw bucket default quota max size``

:Description: Default max capacity per bucket, in kB. Set on new users,
if no other quota is specified. Has no effect on existing users.
:Type: Integer
:Default: ``-1``


``rgw user default quota max objects``

:Description: Default max number of objects for a user. This includes all
objects in all buckets owned by the user. Set on new users,
if no other quota is specified. Has no effect on existing users.
:Type: Integer
:Default: ``-1``


``rgw user default quota max size``

:Description: The value for user max size quota in kB set on new users,
if no other quota is specified. Has no effect on existing users.
:Type: Integer
:Default: ``-1``


Regions
=======

Expand Down
56 changes: 14 additions & 42 deletions src/rgw/rgw_quota.cc
Expand Up @@ -694,73 +694,45 @@ class RGWQuotaHandlerImpl : public RGWQuotaHandler {
return 0;
}
public:
RGWQuotaHandlerImpl(RGWRados *_store, bool quota_threads) : store(_store), bucket_stats_cache(_store), user_stats_cache(_store, quota_threads) {
if (store->ctx()->_conf->rgw_bucket_default_quota_max_objects >= 0) {
def_bucket_quota.max_objects = store->ctx()->_conf->rgw_bucket_default_quota_max_objects;
def_bucket_quota.enabled = true;
}
if (store->ctx()->_conf->rgw_bucket_default_quota_max_size >= 0) {
def_bucket_quota.max_size_kb = store->ctx()->_conf->rgw_bucket_default_quota_max_size;
def_bucket_quota.enabled = true;
}
if (store->ctx()->_conf->rgw_user_default_quota_max_objects >= 0) {
def_user_quota.max_objects = store->ctx()->_conf->rgw_user_default_quota_max_objects;
def_user_quota.enabled = true;
}
if (store->ctx()->_conf->rgw_user_default_quota_max_size >= 0) {
def_user_quota.max_size_kb = store->ctx()->_conf->rgw_user_default_quota_max_size;
def_user_quota.enabled = true;
}
}
RGWQuotaHandlerImpl(RGWRados *_store, bool quota_threads) : store(_store),
bucket_stats_cache(_store),
user_stats_cache(_store, quota_threads) {}

virtual int check_quota(const rgw_user& user, rgw_bucket& bucket,
RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota,
uint64_t num_objs, uint64_t size) {

if (!bucket_quota.enabled && !user_quota.enabled && !def_bucket_quota.enabled && !def_user_quota.enabled)
if (!bucket_quota.enabled && !user_quota.enabled)
return 0;

uint64_t size_kb = rgw_rounded_objsize_kb(size);

RGWStorageStats bucket_stats;

/*
* we need to fetch bucket stats if the user quota is enabled, because the whole system relies
* on us periodically updating the user's bucket stats in the user's header, this happens in
* get_stats() if we actually fetch that info and not rely on cached data
*/

int ret = bucket_stats_cache.get_stats(user, bucket, bucket_stats, bucket_quota);
if (ret < 0)
return ret;

if (bucket_quota.enabled) {
ret = check_quota("bucket", bucket_quota, bucket_stats, num_objs, size_kb);
RGWStorageStats bucket_stats;
int ret = bucket_stats_cache.get_stats(user, bucket, bucket_stats, bucket_quota);
if (ret < 0)
return ret;
}

if (def_bucket_quota.enabled) {
ret = check_quota("def_bucket", def_bucket_quota, bucket_stats, num_objs, size_kb);
ret = check_quota("bucket", bucket_quota, bucket_stats, num_objs, size_kb);
if (ret < 0)
return ret;
return ret;
}

if (user_quota.enabled || def_user_quota.enabled) {
if (user_quota.enabled) {
RGWStorageStats user_stats;

ret = user_stats_cache.get_stats(user, bucket, user_stats, user_quota);
int ret = user_stats_cache.get_stats(user, bucket, user_stats, user_quota);
if (ret < 0)
return ret;

if (user_quota.enabled) {
ret = check_quota("user", user_quota, user_stats, num_objs, size_kb);
if (ret < 0)
return ret;
} else if (def_user_quota.enabled) {
ret = check_quota("def_user", def_user_quota, user_stats, num_objs, size_kb);
if (ret < 0)
return ret;
}
ret = check_quota("user", user_quota, user_stats, num_objs, size_kb);
if (ret < 0)
return ret;
}

return 0;
Expand Down
31 changes: 31 additions & 0 deletions src/rgw/rgw_rest_user.cc
Expand Up @@ -143,6 +143,37 @@ void RGWOp_User_Create::execute()
if (gen_key)
op_state.set_generate_key();

RGWQuotaInfo bucket_quota;
RGWQuotaInfo user_quota;

if (s->cct->_conf->rgw_bucket_default_quota_max_objects >= 0) {
bucket_quota.max_objects = s->cct->_conf->rgw_bucket_default_quota_max_objects;
bucket_quota.enabled = true;
}

if (s->cct->_conf->rgw_bucket_default_quota_max_size >= 0) {
bucket_quota.max_size_kb = s->cct->_conf->rgw_bucket_default_quota_max_size;
bucket_quota.enabled = true;
}

if (s->cct->_conf->rgw_user_default_quota_max_objects >= 0) {
user_quota.max_objects = s->cct->_conf->rgw_user_default_quota_max_objects;
user_quota.enabled = true;
}

if (s->cct->_conf->rgw_user_default_quota_max_size >= 0) {
user_quota.max_size_kb = s->cct->_conf->rgw_user_default_quota_max_size;
user_quota.enabled = true;
}

if (bucket_quota.enabled) {
op_state.set_bucket_quota(bucket_quota);
}

if (user_quota.enabled) {
op_state.set_user_quota(user_quota);
}

http_ret = RGWUserAdminOp_User::create(store, op_state, flusher);
}

Expand Down
24 changes: 22 additions & 2 deletions src/rgw/rgw_user.cc
Expand Up @@ -1932,8 +1932,18 @@ int RGWUser::execute_add(RGWUserAdminOpState& op_state, std::string *err_msg)
if (op_state.op_mask_specified)
user_info.op_mask = op_state.get_op_mask();

if (op_state.has_bucket_quota())
if (op_state.has_bucket_quota()) {
user_info.bucket_quota = op_state.get_bucket_quota();
} else {
if (cct->_conf->rgw_bucket_default_quota_max_objects >= 0) {
user_info.bucket_quota.max_objects = cct->_conf->rgw_bucket_default_quota_max_objects;
user_info.bucket_quota.enabled = true;
}
if (cct->_conf->rgw_bucket_default_quota_max_size >= 0) {
user_info.bucket_quota.max_size_kb = cct->_conf->rgw_bucket_default_quota_max_size;
user_info.bucket_quota.enabled = true;
}
}

if (op_state.temp_url_key_specified) {
map<int, string>::iterator iter;
Expand All @@ -1943,8 +1953,18 @@ int RGWUser::execute_add(RGWUserAdminOpState& op_state, std::string *err_msg)
}
}

if (op_state.has_user_quota())
if (op_state.has_user_quota()) {
user_info.user_quota = op_state.get_user_quota();
} else {
if (cct->_conf->rgw_user_default_quota_max_objects >= 0) {
user_info.user_quota.max_objects = cct->_conf->rgw_user_default_quota_max_objects;
user_info.user_quota.enabled = true;
}
if (cct->_conf->rgw_user_default_quota_max_size >= 0) {
user_info.user_quota.max_size_kb = cct->_conf->rgw_user_default_quota_max_size;
user_info.user_quota.enabled = true;
}
}

// update the request
op_state.set_user_info(user_info);
Expand Down