]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_ratelimit.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rgw / rgw_rest_ratelimit.cc
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);
7 }
8
9 void execute(optional_yield y) override;
10
11 const char* name() const override { return "get_ratelimit_info"; }
12 };
13 void RGWOp_Ratelimit_Info::execute(optional_yield y)
14 {
15 ldpp_dout(this, 20) << "" << dendl;
16 std::string uid_str;
17 std::string ratelimit_scope;
18 std::string bucket_name;
19 std::string tenant_name;
20 bool global = false;
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
26 bool exists;
27 std::string sval = s->info.args.get("global", &exists);
28 if (exists) {
29 if (!boost::iequals(sval,"true") && !boost::iequals(sval,"false")) {
30 op_ret = -EINVAL;
31 ldpp_dout(this, 20) << "global is not equal to true or false" << dendl;
32 return;
33 }
34 }
35 RESTArgs::get_bool(s, "global", false, &global);
36
37 if (ratelimit_scope == "bucket" && !bucket_name.empty() && !global) {
38 std::unique_ptr<rgw::sal::Bucket> bucket;
39 int r = driver->get_bucket(s, nullptr, tenant_name, bucket_name, &bucket, y);
40 if (r != 0) {
41 op_ret = r;
42 ldpp_dout(this, 0) << "Error on getting bucket info" << dendl;
43 return;
44 }
45 RGWRateLimitInfo ratelimit_info;
46 auto iter = bucket->get_attrs().find(RGW_ATTR_RATELIMIT);
47 if (iter != bucket->get_attrs().end()) {
48 try {
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;
54 op_ret = -EIO;
55 return;
56 }
57 }
58 flusher.start(0);
59 s->formatter->open_object_section("bucket_ratelimit");
60 encode_json("bucket_ratelimit", ratelimit_info, s->formatter);
61 s->formatter->close_section();
62 flusher.flush();
63 return;
64 }
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 = driver->get_user(user);
70 if (!rgw::sal::User::empty(user_sal)) {
71 op_ret = user_sal->load_user(this, y);
72 if (op_ret) {
73 ldpp_dout(this, 0) << "Cannot load user info" << dendl;
74 return;
75 }
76 } else {
77 ldpp_dout(this, 0) << "User does not exist" << dendl;
78 op_ret = -ENOENT;
79 return;
80 }
81
82 auto iter = user_sal->get_attrs().find(RGW_ATTR_RATELIMIT);
83 if(iter != user_sal->get_attrs().end()) {
84 try {
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;
90 op_ret = -EIO;
91 return;
92 }
93 }
94 flusher.start(0);
95 s->formatter->open_object_section("user_ratelimit");
96 encode_json("user_ratelimit", ratelimit_info, s->formatter);
97 s->formatter->close_section();
98 flusher.flush();
99 }
100 if (global) {
101 std::string realm_id = driver->get_zone()->get_realm_id();
102 RGWPeriodConfig period_config;
103 op_ret = period_config.read(this, static_cast<rgw::sal::RadosStore*>(driver)->svc()->sysobj, realm_id, y);
104 if (op_ret && op_ret != -ENOENT) {
105 ldpp_dout(this, 0) << "Error on period config read" << dendl;
106 return;
107 }
108 flusher.start(0);
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();
114 flusher.flush();
115 return;
116 }
117 op_ret = -EINVAL;
118 return;
119 }
120
121 class RGWOp_Ratelimit_Set : public RGWRESTOp {
122 int check_caps(const RGWUserCaps& caps) override {
123 return caps.check_cap("ratelimit", RGW_CAP_WRITE);
124 }
125
126 void execute(optional_yield y) override;
127
128 const char* name() const override { return "put_ratelimit_info"; }
129
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);
133 };
134
135
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)
139 {
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;
144 }
145 }
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;
150 }
151 }
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;
156 }
157 }
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;
162 }
163 }
164 if (have_enabled) {
165 ratelimit_info.enabled = enabled;
166 ratelimit_configured = true;
167 }
168 if (!ratelimit_configured) {
169 ldpp_dout(this, 0) << "No rate limit configuration arguments have been sent" << dendl;
170 op_ret = -EINVAL;
171 return;
172 }
173
174 }
175
176
177 void RGWOp_Ratelimit_Set::execute(optional_yield y)
178 {
179 std::string uid_str;
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;
187 bool global = 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);
205 if (op_ret) {
206 ldpp_dout(this, 0) << "one of the maximum arguments could not be parsed" << dendl;
207 return;
208 }
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);
211 if (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;
214 op_ret = -EINVAL;
215 return;
216 }
217 }
218 RESTArgs::get_bool(s, "enabled", false, &enabled, &have_enabled);
219 bool exists;
220 sval = s->info.args.get("global", &exists);
221 if (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;
224 op_ret = -EINVAL;
225 return;
226 }
227 }
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);
232 if (op_ret) {
233 return;
234 }
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 = driver->get_user(user);
239 if (!rgw::sal::User::empty(user_sal)) {
240 op_ret = user_sal->load_user(this, y);
241 if (op_ret) {
242 ldpp_dout(this, 0) << "Cannot load user info" << dendl;
243 return;
244 }
245 } else {
246 ldpp_dout(this, 0) << "User does not exist" << dendl;
247 op_ret = -ENOENT;
248 return;
249 }
250 auto iter = user_sal->get_attrs().find(RGW_ATTR_RATELIMIT);
251 if (iter != user_sal->get_attrs().end()) {
252 try {
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;
258 op_ret = -EIO;
259 return;
260 }
261 }
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);
265 bufferlist bl;
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);
270 return;
271 }
272
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 = driver->get_bucket(this, nullptr, tenant_name, bucket_name, &bucket, y);
277 if (op_ret) {
278 ldpp_dout(this, 0) << "Error on getting bucket info" << dendl;
279 return;
280 }
281 auto iter = bucket->get_attrs().find(RGW_ATTR_RATELIMIT);
282 if (iter != bucket->get_attrs().end()) {
283 try {
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;
289 op_ret = -EIO;
290 return;
291 }
292 }
293 bufferlist bl;
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);
301 return;
302 }
303 if (global) {
304 std::string realm_id = driver->get_zone()->get_realm_id();
305 RGWPeriodConfig period_config;
306 op_ret = period_config.read(s, static_cast<rgw::sal::RadosStore*>(driver)->svc()->sysobj, realm_id, y);
307 if (op_ret && op_ret != -ENOENT) {
308 ldpp_dout(this, 0) << "Error on period config read" << dendl;
309 return;
310 }
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*>(driver)->svc()->sysobj, realm_id, y);
318 return;
319 }
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*>(driver)->svc()->sysobj, realm_id, y);
327 return;
328 }
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*>(driver)->svc()->sysobj, realm_id, y);
336 return;
337 }
338 }
339 op_ret = -EINVAL;
340 return;
341 }
342 RGWOp* RGWHandler_Ratelimit::op_get()
343 {
344 return new RGWOp_Ratelimit_Info;
345 }
346 RGWOp* RGWHandler_Ratelimit::op_post()
347 {
348 return new RGWOp_Ratelimit_Set;
349 }