]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: front-end for bucket quotas of Swift API.
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Fri, 29 Apr 2016 19:54:39 +0000 (21:54 +0200)
committerRadoslaw Zarzynski <rzarzynski@mirantis.com>
Mon, 30 May 2016 09:41:00 +0000 (11:41 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
src/rgw/rgw_common.h
src/rgw/rgw_http_errors.h
src/rgw/rgw_op.cc

index d70c1a029803536fac7483927cb9b9850fdf8d9c..677f83cc5ffc79be1d660f2143e28bef24d06d87 100644 (file)
@@ -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"
index 2d998d244c9928493515914afcbde530930ebccf..4e6107e1e4dc460829d3e22e74a02cdd1a0bd148 100644 (file)
@@ -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 {
index 52ea617b27dd974b82487fe470d0e3186d258adf..b972e07e1ab16b7b0307306f1472c004a1de0590 100644 (file)
@@ -1912,6 +1912,50 @@ static void populate_with_generic_attrs(const req_state * const s,
 }
 
 
+static int filter_out_bucket_quota(std::map<std::string, bufferlist>& add_attrs,
+                                   const std::set<std::string>& 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<int64_t>(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<int64_t>(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);
 }