]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: Admin API Support for bucket quota change
authorJeegn Chen <jeegnchen@gmail.com>
Mon, 16 Oct 2017 09:46:39 +0000 (17:46 +0800)
committerJeegn Chen <jeegnchen@gmail.com>
Thu, 4 Jan 2018 06:56:49 +0000 (06:56 +0000)
Allow admin to change the quota of a individual bucket through Admin API

Fixes: http://tracker.ceph.com/issues/21811
Signed-off-by: Jeegn Chen <jeegnchen@gmail.com>
src/rgw/rgw_bucket.cc
src/rgw/rgw_bucket.h
src/rgw/rgw_rest_bucket.cc

index 5c3f85e1433df7fac5020d505ecb5a0c15dd1177..39c97c29bfa51b92b058d47f1dff9b1f7981afed 100644 (file)
@@ -917,6 +917,27 @@ int RGWBucket::unlink(RGWBucketAdminOpState& op_state, std::string *err_msg)
   return r;
 }
 
+int RGWBucket::set_quota(RGWBucketAdminOpState& op_state, std::string *err_msg)
+{
+  rgw_bucket bucket = op_state.get_bucket();
+  RGWBucketInfo bucket_info;
+  map<string, bufferlist> attrs;
+  RGWObjectCtx obj_ctx(store);
+  int r = store->get_bucket_info(obj_ctx, bucket.tenant, bucket.name, bucket_info, NULL, &attrs);
+  if (r < 0) {
+    set_err_msg(err_msg, "could not get bucket info for bucket=" + bucket.name + ": " + cpp_strerror(-r));
+    return r;
+  }
+
+  bucket_info.quota = op_state.quota;
+  r = store->put_bucket_instance_info(bucket_info, false, real_time(), &attrs);
+  if (r < 0) {
+    set_err_msg(err_msg, "ERROR: failed writing bucket instance info: " + cpp_strerror(-r));
+    return r;
+  }
+  return r;
+}
+
 int RGWBucket::remove(RGWBucketAdminOpState& op_state, bool bypass_gc,
                       bool keep_index_consistent, std::string *err_msg)
 {
@@ -1619,6 +1640,15 @@ int RGWBucketAdminOp::info(RGWRados *store, RGWBucketAdminOpState& op_state,
   return 0;
 }
 
+int RGWBucketAdminOp::set_quota(RGWRados *store, RGWBucketAdminOpState& op_state)
+{
+  RGWBucket bucket;
+
+  int ret = bucket.init(store, op_state);
+  if (ret < 0)
+    return ret;
+  return bucket.set_quota(op_state);
+}
 
 void rgw_data_change::dump(Formatter *f) const
 {
index ad75becc1a04baec7f86ed401e45555dbd20b2ac..be0625123b24122b015d2b663fd7e98cbd5fe4a2 100644 (file)
@@ -213,6 +213,8 @@ struct RGWBucketAdminOpState {
 
   rgw_bucket bucket;
 
+  RGWQuotaInfo quota;
+
   void set_fetch_stats(bool value) { stat_buckets = value; }
   void set_check_objects(bool value) { check_objects = value; }
   void set_fix_index(bool value) { fix_index = value; }
@@ -231,6 +233,10 @@ struct RGWBucketAdminOpState {
   void set_object(std::string& object_str) {
     object_name = object_str;
   }
+  void set_quota(RGWQuotaInfo& value) {
+    quota = value;
+  }
+
 
   rgw_user& get_user_id() { return uid; }
   std::string& get_user_display_name() { return display_name; }
@@ -300,6 +306,7 @@ public:
   int remove(RGWBucketAdminOpState& op_state, bool bypass_gc = false, bool keep_index_consistent = true, std::string *err_msg = NULL);
   int link(RGWBucketAdminOpState& op_state, std::string *err_msg = NULL);
   int unlink(RGWBucketAdminOpState& op_state, std::string *err_msg = NULL);
+  int set_quota(RGWBucketAdminOpState& op_state, std::string *err_msg = NULL);
 
   int remove_object(RGWBucketAdminOpState& op_state, std::string *err_msg = NULL);
   int policy_bl_to_stream(bufferlist& bl, ostream& o);
@@ -331,6 +338,7 @@ public:
                         const std::list<std::string>& user_ids,
                         RGWFormatterFlusher& flusher,
                         bool warnings_only = false);
+  static int set_quota(RGWRados *store, RGWBucketAdminOpState& op_state);
 };
 
 
index 62252ca6cc3a5290b9a910a7f228da84b3e54ba2..086a23f3bf4fe5a5f54c5cb64f2142a71bec67f4 100644 (file)
@@ -206,6 +206,55 @@ void RGWOp_Bucket_Remove::execute()
   http_ret = RGWBucketAdminOp::remove_bucket(store, op_state);
 }
 
+class RGWOp_Set_Bucket_Quota : public RGWRESTOp {
+
+public:
+  RGWOp_Set_Bucket_Quota() {}
+
+  int check_caps(RGWUserCaps& caps) {
+    return caps.check_cap("buckets", RGW_CAP_WRITE);
+  }
+
+  void execute();
+
+  virtual const string name() { return "set_bucket_quota"; }
+};
+
+#define QUOTA_INPUT_MAX_LEN 1024
+
+void RGWOp_Set_Bucket_Quota::execute()
+{
+  bool uid_arg_existed = false;
+  std::string uid_str;
+  RESTArgs::get_string(s, "uid", uid_str, &uid_str, &uid_arg_existed);
+  if (! uid_arg_existed) {
+    http_ret = -EINVAL;
+    return;
+  }
+  rgw_user uid(uid_str);
+  bool bucket_arg_existed = false;
+  std::string bucket;
+  RESTArgs::get_string(s, "bucket", bucket, &bucket, &bucket_arg_existed);
+  if (! bucket_arg_existed) {
+    http_ret = -EINVAL;
+    return;
+  }
+  RGWQuotaInfo quota;
+  bool empty;
+  http_ret = rgw_rest_get_json_input(store->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty);
+  if (http_ret < 0) {
+    ldout(store->ctx(), 20) << "failed to retrieve input" << dendl;
+    return;
+  }
+
+  RGWBucketAdminOpState op_state;
+  op_state.set_user_id(uid);
+  op_state.set_bucket_name(bucket);
+  op_state.set_quota(quota);
+
+  http_ret = RGWBucketAdminOp::set_quota(store, op_state);
+}
+
 class RGWOp_Object_Remove: public RGWRESTOp {
 
 public:
@@ -250,6 +299,8 @@ RGWOp *RGWHandler_Bucket::op_get()
 
 RGWOp *RGWHandler_Bucket::op_put()
 {
+  if (s->info.args.sub_resource_exists("quota"))
+    return new RGWOp_Set_Bucket_Quota;
   return new RGWOp_Bucket_Link;
 }