From b2893d171075597dd52df1268e7e03ad68e5e04b Mon Sep 17 00:00:00 2001 From: Jeegn Chen Date: Mon, 16 Oct 2017 17:46:39 +0800 Subject: [PATCH] rgw: Admin API Support for bucket quota change 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 --- src/rgw/rgw_bucket.cc | 30 ++++++++++++++++++++++ src/rgw/rgw_bucket.h | 8 ++++++ src/rgw/rgw_rest_bucket.cc | 51 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 5c3f85e1433..39c97c29bfa 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -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 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 { diff --git a/src/rgw/rgw_bucket.h b/src/rgw/rgw_bucket.h index ad75becc1a0..be0625123b2 100644 --- a/src/rgw/rgw_bucket.h +++ b/src/rgw/rgw_bucket.h @@ -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& user_ids, RGWFormatterFlusher& flusher, bool warnings_only = false); + static int set_quota(RGWRados *store, RGWBucketAdminOpState& op_state); }; diff --git a/src/rgw/rgw_rest_bucket.cc b/src/rgw/rgw_rest_bucket.cc index 62252ca6cc3..086a23f3bf4 100644 --- a/src/rgw/rgw_rest_bucket.cc +++ b/src/rgw/rgw_rest_bucket.cc @@ -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; } -- 2.39.5