From: Radoslaw Zarzynski Date: Fri, 29 Apr 2016 19:54:39 +0000 (+0200) Subject: rgw: front-end for bucket quotas of Swift API. X-Git-Tag: v11.0.0~349^2~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=10f6d5801a94fee73bd729b08d14fa11513833ad;p=ceph.git rgw: front-end for bucket quotas of Swift API. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index d70c1a029803..677f83cc5ffc 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -88,6 +88,10 @@ using ceph::crypto::MD5; #define RGW_ATTR_TEMPURL_KEY1 RGW_ATTR_META_PREFIX "temp-url-key" #define RGW_ATTR_TEMPURL_KEY2 RGW_ATTR_META_PREFIX "temp-url-key-2" +/* Container quota of the Swift API. */ +#define RGW_ATTR_CQUOTA_NOBJS RGW_ATTR_META_PREFIX "quota-count" +#define RGW_ATTR_CQUOTA_MSIZE RGW_ATTR_META_PREFIX "quota-bytes" + #define RGW_ATTR_OLH_PREFIX RGW_ATTR_PREFIX "olh." #define RGW_ATTR_OLH_INFO RGW_ATTR_OLH_PREFIX "info" diff --git a/src/rgw/rgw_http_errors.h b/src/rgw/rgw_http_errors.h index 2d998d244c99..4e6107e1e4dc 100644 --- a/src/rgw/rgw_http_errors.h +++ b/src/rgw/rgw_http_errors.h @@ -76,7 +76,8 @@ const static struct rgw_http_errors RGW_HTTP_SWIFT_ERRORS[] = { { ERR_USER_SUSPENDED, 401, "UserSuspended" }, { ERR_INVALID_UTF8, 412, "Invalid UTF8" }, { ERR_BAD_URL, 412, "Bad URL" }, - { ERR_NOT_SLO_MANIFEST, 400, "Not an SLO manifest" } + { ERR_NOT_SLO_MANIFEST, 400, "Not an SLO manifest" }, + { ERR_QUOTA_EXCEEDED, 413, "QuotaExceeded" } }; struct rgw_http_status_code { diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 52ea617b27dd..b972e07e1ab1 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -1912,6 +1912,50 @@ static void populate_with_generic_attrs(const req_state * const s, } +static int filter_out_bucket_quota(std::map& add_attrs, + const std::set& rmattr_names, + RGWQuotaInfo& quota) +{ + /* Put new limit on max objects. */ + auto iter = add_attrs.find(RGW_ATTR_CQUOTA_NOBJS); + std::string err; + if (std::end(add_attrs) != iter) { + quota.max_objects = + static_cast(strict_strtoll(iter->second.c_str(), 10, &err)); + if (!err.empty()) { + return -EINVAL; + } + add_attrs.erase(iter); + } + + /* Put new limit on bucket (container) size. */ + iter = add_attrs.find(RGW_ATTR_CQUOTA_MSIZE); + if (iter != add_attrs.end()) { + quota.max_size = + static_cast(strict_strtoll(iter->second.c_str(), 10, &err)); + if (!err.empty()) { + return -EINVAL; + } + add_attrs.erase(iter); + } + + for (const auto& name : rmattr_names) { + /* Remove limit on max objects. */ + if (name.compare(RGW_ATTR_CQUOTA_NOBJS) == 0) { + quota.max_objects = -1; + } + + /* Remove limit on max bucket size. */ + if (name.compare(RGW_ATTR_CQUOTA_MSIZE) == 0) { + quota.max_size = -1; + } + } + + quota.enabled = quota.max_size > 0 || quota.max_objects > 0; + return 0; +} + + void RGWCreateBucket::execute() { RGWAccessControlPolicy old_policy(s->cct); @@ -2907,9 +2951,20 @@ void RGWPutMetadataBucket::execute() prepare_add_del_attrs(s->bucket_attrs, rmattr_names, attrs); populate_with_generic_attrs(s, attrs); + /* According to the Swift's behaviour and its container_quota WSGI middleware + * implementation: anyone with write permissions is able to set the bucket + * quota. This stays in contrast to account quotas that can be set only by + * clients holding reseller admin privileges. */ + op_ret = filter_out_bucket_quota(attrs, rmattr_names, s->bucket_info.quota); + if (op_ret < 0) { + return; + } + s->bucket_info.swift_ver_location = swift_ver_location; s->bucket_info.swift_versioning = (!swift_ver_location.empty()); + /* Setting attributes also stores the provided bucket info. Due to this + * fact, the new quota settings can be serialized with the same call. */ op_ret = rgw_bucket_set_attrs(store, s->bucket_info, attrs, &s->bucket_info.objv_tracker); }