1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3 #include "rgw_rest_ratelimit.h"
4 class RGWOp_Ratelimit_Info
: public RGWRESTOp
{
5 int check_caps(const RGWUserCaps
& caps
) override
{
6 return caps
.check_cap("ratelimit", RGW_CAP_READ
);
9 void execute(optional_yield y
) override
;
11 const char* name() const override
{ return "get_ratelimit_info"; }
13 void RGWOp_Ratelimit_Info::execute(optional_yield y
)
15 ldpp_dout(this, 20) << "" << dendl
;
17 std::string ratelimit_scope
;
18 std::string bucket_name
;
19 std::string tenant_name
;
21 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
22 RESTArgs::get_string(s
, "ratelimit-scope", ratelimit_scope
, &ratelimit_scope
);
23 RESTArgs::get_string(s
, "bucket", bucket_name
, &bucket_name
);
24 RESTArgs::get_string(s
, "tenant", tenant_name
, &tenant_name
);
25 // RESTArgs::get_bool default value to true even if global is empty
27 std::string sval
= s
->info
.args
.get("global", &exists
);
29 if (!boost::iequals(sval
,"true") && !boost::iequals(sval
,"false")) {
31 ldpp_dout(this, 20) << "global is not equal to true or false" << dendl
;
35 RESTArgs::get_bool(s
, "global", false, &global
);
37 if (ratelimit_scope
== "bucket" && !bucket_name
.empty() && !global
) {
38 std::unique_ptr
<rgw::sal::Bucket
> bucket
;
39 int r
= store
->get_bucket(s
, nullptr, tenant_name
, bucket_name
, &bucket
, y
);
42 ldpp_dout(this, 0) << "Error on getting bucket info" << dendl
;
45 RGWRateLimitInfo ratelimit_info
;
46 auto iter
= bucket
->get_attrs().find(RGW_ATTR_RATELIMIT
);
47 if (iter
!= bucket
->get_attrs().end()) {
49 bufferlist
& bl
= iter
->second
;
50 auto biter
= bl
.cbegin();
51 decode(ratelimit_info
, biter
);
52 } catch (buffer::error
& err
) {
53 ldpp_dout(this, 0) << "Error on decoding ratelimit info from bucket" << dendl
;
59 s
->formatter
->open_object_section("bucket_ratelimit");
60 encode_json("bucket_ratelimit", ratelimit_info
, s
->formatter
);
61 s
->formatter
->close_section();
65 if (ratelimit_scope
== "user" && !uid_str
.empty() && !global
) {
66 RGWRateLimitInfo ratelimit_info
;
67 rgw_user
user(uid_str
);
68 std::unique_ptr
<rgw::sal::User
> user_sal
;
69 user_sal
= store
->get_user(user
);
70 if (!rgw::sal::User::empty(user_sal
)) {
71 op_ret
= user_sal
->load_user(this, y
);
73 ldpp_dout(this, 0) << "Cannot load user info" << dendl
;
77 ldpp_dout(this, 0) << "User does not exist" << dendl
;
82 auto iter
= user_sal
->get_attrs().find(RGW_ATTR_RATELIMIT
);
83 if(iter
!= user_sal
->get_attrs().end()) {
85 bufferlist
& bl
= iter
->second
;
86 auto biter
= bl
.cbegin();
87 decode(ratelimit_info
, biter
);
88 } catch (buffer::error
& err
) {
89 ldpp_dout(this, 0) << "Error on decoding ratelimit info from user" << dendl
;
95 s
->formatter
->open_object_section("user_ratelimit");
96 encode_json("user_ratelimit", ratelimit_info
, s
->formatter
);
97 s
->formatter
->close_section();
101 std::string realm_id
= store
->get_zone()->get_realm().get_id();
102 RGWPeriodConfig period_config
;
103 op_ret
= period_config
.read(this, static_cast<rgw::sal::RadosStore
*>(store
)->svc()->sysobj
, realm_id
, y
);
104 if (op_ret
&& op_ret
!= -ENOENT
) {
105 ldpp_dout(this, 0) << "Error on period config read" << dendl
;
109 s
->formatter
->open_object_section("period_config");
110 encode_json("bucket_ratelimit", period_config
.bucket_ratelimit
, s
->formatter
);
111 encode_json("user_ratelimit", period_config
.user_ratelimit
, s
->formatter
);
112 encode_json("anonymous_ratelimit", period_config
.anon_ratelimit
, s
->formatter
);
113 s
->formatter
->close_section();
121 class RGWOp_Ratelimit_Set
: public RGWRESTOp
{
122 int check_caps(const RGWUserCaps
& caps
) override
{
123 return caps
.check_cap("ratelimit", RGW_CAP_WRITE
);
126 void execute(optional_yield y
) override
;
128 const char* name() const override
{ return "put_ratelimit_info"; }
130 void set_ratelimit_info(bool have_max_read_ops
, int64_t max_read_ops
, bool have_max_write_ops
, int64_t max_write_ops
,
131 bool have_max_read_bytes
, int64_t max_read_bytes
, bool have_max_write_bytes
, int64_t max_write_bytes
,
132 bool have_enabled
, bool enabled
, bool& ratelimit_configured
, RGWRateLimitInfo
& ratelimit_info
);
136 void RGWOp_Ratelimit_Set::set_ratelimit_info(bool have_max_read_ops
, int64_t max_read_ops
, bool have_max_write_ops
, int64_t max_write_ops
,
137 bool have_max_read_bytes
, int64_t max_read_bytes
, bool have_max_write_bytes
, int64_t max_write_bytes
,
138 bool have_enabled
, bool enabled
, bool& ratelimit_configured
, RGWRateLimitInfo
& ratelimit_info
)
140 if (have_max_read_ops
) {
141 if (max_read_ops
>= 0) {
142 ratelimit_info
.max_read_ops
= max_read_ops
;
143 ratelimit_configured
= true;
146 if (have_max_write_ops
) {
147 if (max_write_ops
>= 0) {
148 ratelimit_info
.max_write_ops
= max_write_ops
;
149 ratelimit_configured
= true;
152 if (have_max_read_bytes
) {
153 if (max_read_bytes
>= 0) {
154 ratelimit_info
.max_read_bytes
= max_read_bytes
;
155 ratelimit_configured
= true;
158 if (have_max_write_bytes
) {
159 if (max_write_bytes
>= 0) {
160 ratelimit_info
.max_write_bytes
= max_write_bytes
;
161 ratelimit_configured
= true;
165 ratelimit_info
.enabled
= enabled
;
166 ratelimit_configured
= true;
168 if (!ratelimit_configured
) {
169 ldpp_dout(this, 0) << "No rate limit configuration arguments have been sent" << dendl
;
177 void RGWOp_Ratelimit_Set::execute(optional_yield y
)
180 std::string ratelimit_scope
;
181 std::string bucket_name
;
182 std::string tenant_name
;
183 RGWRateLimitInfo ratelimit_info
;
184 bool ratelimit_configured
= false;
185 bool enabled
= false;
186 bool have_enabled
= false;
188 int64_t max_read_ops
= 0;
189 bool have_max_read_ops
= false;
190 int64_t max_write_ops
= 0;
191 bool have_max_write_ops
= false;
192 int64_t max_read_bytes
= 0;
193 bool have_max_read_bytes
= false;
194 int64_t max_write_bytes
= 0;
195 bool have_max_write_bytes
= false;
196 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
197 RESTArgs::get_string(s
, "ratelimit-scope", ratelimit_scope
, &ratelimit_scope
);
198 RESTArgs::get_string(s
, "bucket", bucket_name
, &bucket_name
);
199 RESTArgs::get_string(s
, "tenant", tenant_name
, &tenant_name
);
200 // check there was no -EINVAL coming from get_int64
201 op_ret
= RESTArgs::get_int64(s
, "max-read-ops", 0, &max_read_ops
, &have_max_read_ops
);
202 op_ret
|= RESTArgs::get_int64(s
, "max-write-ops", 0, &max_write_ops
, &have_max_write_ops
);
203 op_ret
|= RESTArgs::get_int64(s
, "max-read-bytes", 0, &max_read_bytes
, &have_max_read_bytes
);
204 op_ret
|= RESTArgs::get_int64(s
, "max-write-bytes", 0, &max_write_bytes
, &have_max_write_bytes
);
206 ldpp_dout(this, 0) << "one of the maximum arguments could not be parsed" << dendl
;
209 // RESTArgs::get_bool default value to true even if enabled or global are empty
210 std::string sval
= s
->info
.args
.get("enabled", &have_enabled
);
212 if (!boost::iequals(sval
,"true") && !boost::iequals(sval
,"false")) {
213 ldpp_dout(this, 20) << "enabled is not equal to true or false" << dendl
;
218 RESTArgs::get_bool(s
, "enabled", false, &enabled
, &have_enabled
);
220 sval
= s
->info
.args
.get("global", &exists
);
222 if (!boost::iequals(sval
,"true") && !boost::iequals(sval
,"false")) {
223 ldpp_dout(this, 20) << "global is not equal to true or faslse" << dendl
;
228 RESTArgs::get_bool(s
, "global", false, &global
, nullptr);
229 set_ratelimit_info(have_max_read_ops
, max_read_ops
, have_max_write_ops
, max_write_ops
,
230 have_max_read_bytes
, max_read_bytes
, have_max_write_bytes
, max_write_bytes
,
231 have_enabled
, enabled
, ratelimit_configured
, ratelimit_info
);
235 if (ratelimit_scope
== "user" && !uid_str
.empty() && !global
) {
236 rgw_user
user(uid_str
);
237 std::unique_ptr
<rgw::sal::User
> user_sal
;
238 user_sal
= store
->get_user(user
);
239 if (!rgw::sal::User::empty(user_sal
)) {
240 op_ret
= user_sal
->load_user(this, y
);
242 ldpp_dout(this, 0) << "Cannot load user info" << dendl
;
246 ldpp_dout(this, 0) << "User does not exist" << dendl
;
250 auto iter
= user_sal
->get_attrs().find(RGW_ATTR_RATELIMIT
);
251 if (iter
!= user_sal
->get_attrs().end()) {
253 bufferlist
& bl
= iter
->second
;
254 auto biter
= bl
.cbegin();
255 decode(ratelimit_info
, biter
);
256 } catch (buffer::error
& err
) {
257 ldpp_dout(this, 0) << "Error on decoding ratelimit info from user" << dendl
;
262 set_ratelimit_info(have_max_read_ops
, max_read_ops
, have_max_write_ops
, max_write_ops
,
263 have_max_read_bytes
, max_read_bytes
, have_max_write_bytes
, max_write_bytes
,
264 have_enabled
, enabled
, ratelimit_configured
, ratelimit_info
);
266 ratelimit_info
.encode(bl
);
267 rgw::sal::Attrs attr
;
268 attr
[RGW_ATTR_RATELIMIT
] = bl
;
269 op_ret
= user_sal
->merge_and_store_attrs(this, attr
, y
);
273 if (ratelimit_scope
== "bucket" && !bucket_name
.empty() && !global
) {
274 ldpp_dout(this, 0) << "getting bucket info" << dendl
;
275 std::unique_ptr
<rgw::sal::Bucket
> bucket
;
276 op_ret
= store
->get_bucket(this, nullptr, tenant_name
, bucket_name
, &bucket
, y
);
278 ldpp_dout(this, 0) << "Error on getting bucket info" << dendl
;
281 auto iter
= bucket
->get_attrs().find(RGW_ATTR_RATELIMIT
);
282 if (iter
!= bucket
->get_attrs().end()) {
284 bufferlist
& bl
= iter
->second
;
285 auto biter
= bl
.cbegin();
286 decode(ratelimit_info
, biter
);
287 } catch (buffer::error
& err
) {
288 ldpp_dout(this, 0) << "Error on decoding ratelimit info from bucket" << dendl
;
294 set_ratelimit_info(have_max_read_ops
, max_read_ops
, have_max_write_ops
, max_write_ops
,
295 have_max_read_bytes
, max_read_bytes
, have_max_write_bytes
, max_write_bytes
,
296 have_enabled
, enabled
, ratelimit_configured
, ratelimit_info
);
297 ratelimit_info
.encode(bl
);
298 rgw::sal::Attrs attr
;
299 attr
[RGW_ATTR_RATELIMIT
] = bl
;
300 op_ret
= bucket
->merge_and_store_attrs(this, attr
, y
);
304 std::string realm_id
= store
->get_zone()->get_realm().get_id();
305 RGWPeriodConfig period_config
;
306 op_ret
= period_config
.read(s
, static_cast<rgw::sal::RadosStore
*>(store
)->svc()->sysobj
, realm_id
, y
);
307 if (op_ret
&& op_ret
!= -ENOENT
) {
308 ldpp_dout(this, 0) << "Error on period config read" << dendl
;
311 if (ratelimit_scope
== "bucket") {
312 ratelimit_info
= period_config
.bucket_ratelimit
;
313 set_ratelimit_info(have_max_read_ops
, max_read_ops
, have_max_write_ops
, max_write_ops
,
314 have_max_read_bytes
, max_read_bytes
, have_max_write_bytes
, max_write_bytes
,
315 have_enabled
, enabled
, ratelimit_configured
, ratelimit_info
);
316 period_config
.bucket_ratelimit
= ratelimit_info
;
317 op_ret
= period_config
.write(s
, static_cast<rgw::sal::RadosStore
*>(store
)->svc()->sysobj
, realm_id
, y
);
320 if (ratelimit_scope
== "anon") {
321 ratelimit_info
= period_config
.anon_ratelimit
;
322 set_ratelimit_info(have_max_read_ops
, max_read_ops
, have_max_write_ops
, max_write_ops
,
323 have_max_read_bytes
, max_read_bytes
, have_max_write_bytes
, max_write_bytes
,
324 have_enabled
, enabled
, ratelimit_configured
, ratelimit_info
);
325 period_config
.anon_ratelimit
= ratelimit_info
;
326 op_ret
= period_config
.write(s
, static_cast<rgw::sal::RadosStore
*>(store
)->svc()->sysobj
, realm_id
, y
);
329 if (ratelimit_scope
== "user") {
330 ratelimit_info
= period_config
.user_ratelimit
;
331 set_ratelimit_info(have_max_read_ops
, max_read_ops
, have_max_write_ops
, max_write_ops
,
332 have_max_read_bytes
, max_read_bytes
, have_max_write_bytes
, max_write_bytes
,
333 have_enabled
, enabled
, ratelimit_configured
, ratelimit_info
);
334 period_config
.user_ratelimit
= ratelimit_info
;
335 op_ret
= period_config
.write(s
, static_cast<rgw::sal::RadosStore
*>(store
)->svc()->sysobj
, realm_id
, y
);
342 RGWOp
* RGWHandler_Ratelimit::op_get()
344 return new RGWOp_Ratelimit_Info
;
346 RGWOp
* RGWHandler_Ratelimit::op_post()
348 return new RGWOp_Ratelimit_Set
;