]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
7c673cae FG |
3 | |
4 | #include "rgw_op.h" | |
5 | #include "rgw_bucket.h" | |
6 | #include "rgw_rest_bucket.h" | |
7 | ||
8 | #include "include/str_list.h" | |
9 | ||
11fdf7f2 | 10 | #include "services/svc_sys_obj.h" |
9f95a23c | 11 | #include "services/svc_zone.h" |
11fdf7f2 | 12 | |
7c673cae FG |
13 | #define dout_subsys ceph_subsys_rgw |
14 | ||
9f95a23c | 15 | |
7c673cae FG |
16 | class RGWOp_Bucket_Info : public RGWRESTOp { |
17 | ||
18 | public: | |
19 | RGWOp_Bucket_Info() {} | |
20 | ||
9f95a23c | 21 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
22 | return caps.check_cap("buckets", RGW_CAP_READ); |
23 | } | |
24 | ||
25 | void execute() override; | |
26 | ||
11fdf7f2 | 27 | const char* name() const override { return "get_bucket_info"; } |
7c673cae FG |
28 | }; |
29 | ||
30 | void RGWOp_Bucket_Info::execute() | |
31 | { | |
32 | RGWBucketAdminOpState op_state; | |
33 | ||
34 | bool fetch_stats; | |
35 | ||
36 | std::string bucket; | |
37 | ||
38 | string uid_str; | |
39 | ||
40 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
41 | rgw_user uid(uid_str); | |
42 | ||
43 | RESTArgs::get_string(s, "bucket", bucket, &bucket); | |
44 | RESTArgs::get_bool(s, "stats", false, &fetch_stats); | |
45 | ||
46 | op_state.set_user_id(uid); | |
47 | op_state.set_bucket_name(bucket); | |
48 | op_state.set_fetch_stats(fetch_stats); | |
49 | ||
50 | http_ret = RGWBucketAdminOp::info(store, op_state, flusher); | |
51 | } | |
52 | ||
53 | class RGWOp_Get_Policy : public RGWRESTOp { | |
54 | ||
55 | public: | |
56 | RGWOp_Get_Policy() {} | |
57 | ||
9f95a23c | 58 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
59 | return caps.check_cap("buckets", RGW_CAP_READ); |
60 | } | |
61 | ||
62 | void execute() override; | |
63 | ||
11fdf7f2 | 64 | const char* name() const override { return "get_policy"; } |
7c673cae FG |
65 | }; |
66 | ||
67 | void RGWOp_Get_Policy::execute() | |
68 | { | |
69 | RGWBucketAdminOpState op_state; | |
70 | ||
71 | std::string bucket; | |
72 | std::string object; | |
73 | ||
74 | RESTArgs::get_string(s, "bucket", bucket, &bucket); | |
75 | RESTArgs::get_string(s, "object", object, &object); | |
76 | ||
77 | op_state.set_bucket_name(bucket); | |
78 | op_state.set_object(object); | |
79 | ||
80 | http_ret = RGWBucketAdminOp::get_policy(store, op_state, flusher); | |
81 | } | |
82 | ||
83 | class RGWOp_Check_Bucket_Index : public RGWRESTOp { | |
84 | ||
85 | public: | |
86 | RGWOp_Check_Bucket_Index() {} | |
87 | ||
9f95a23c | 88 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
89 | return caps.check_cap("buckets", RGW_CAP_WRITE); |
90 | } | |
91 | ||
92 | void execute() override; | |
93 | ||
11fdf7f2 | 94 | const char* name() const override { return "check_bucket_index"; } |
7c673cae FG |
95 | }; |
96 | ||
97 | void RGWOp_Check_Bucket_Index::execute() | |
98 | { | |
99 | std::string bucket; | |
100 | ||
101 | bool fix_index; | |
102 | bool check_objects; | |
103 | ||
104 | RGWBucketAdminOpState op_state; | |
105 | ||
106 | RESTArgs::get_string(s, "bucket", bucket, &bucket); | |
107 | RESTArgs::get_bool(s, "fix", false, &fix_index); | |
108 | RESTArgs::get_bool(s, "check-objects", false, &check_objects); | |
109 | ||
110 | op_state.set_bucket_name(bucket); | |
111 | op_state.set_fix_index(fix_index); | |
112 | op_state.set_check_objects(check_objects); | |
113 | ||
9f95a23c | 114 | http_ret = RGWBucketAdminOp::check_index(store, op_state, flusher, s->yield); |
7c673cae FG |
115 | } |
116 | ||
117 | class RGWOp_Bucket_Link : public RGWRESTOp { | |
118 | ||
119 | public: | |
120 | RGWOp_Bucket_Link() {} | |
121 | ||
9f95a23c | 122 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
123 | return caps.check_cap("buckets", RGW_CAP_WRITE); |
124 | } | |
125 | ||
126 | void execute() override; | |
127 | ||
11fdf7f2 | 128 | const char* name() const override { return "link_bucket"; } |
7c673cae FG |
129 | }; |
130 | ||
131 | void RGWOp_Bucket_Link::execute() | |
132 | { | |
133 | std::string uid_str; | |
134 | std::string bucket; | |
135 | std::string bucket_id; | |
9f95a23c | 136 | std::string new_bucket_name; |
7c673cae FG |
137 | |
138 | RGWBucketAdminOpState op_state; | |
139 | ||
140 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
141 | RESTArgs::get_string(s, "bucket", bucket, &bucket); | |
142 | RESTArgs::get_string(s, "bucket-id", bucket_id, &bucket_id); | |
9f95a23c | 143 | RESTArgs::get_string(s, "new-bucket-name", new_bucket_name, &new_bucket_name); |
7c673cae FG |
144 | |
145 | rgw_user uid(uid_str); | |
146 | op_state.set_user_id(uid); | |
147 | op_state.set_bucket_name(bucket); | |
148 | op_state.set_bucket_id(bucket_id); | |
9f95a23c | 149 | op_state.set_new_bucket_name(new_bucket_name); |
7c673cae | 150 | |
9f95a23c TL |
151 | if (!store->svc()->zone->is_meta_master()) { |
152 | bufferlist data; | |
153 | op_ret = forward_request_to_master(s, nullptr, store, data, nullptr); | |
154 | if (op_ret < 0) { | |
155 | ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl; | |
156 | return; | |
157 | } | |
158 | } | |
7c673cae FG |
159 | http_ret = RGWBucketAdminOp::link(store, op_state); |
160 | } | |
161 | ||
162 | class RGWOp_Bucket_Unlink : public RGWRESTOp { | |
163 | ||
164 | public: | |
165 | RGWOp_Bucket_Unlink() {} | |
166 | ||
9f95a23c | 167 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
168 | return caps.check_cap("buckets", RGW_CAP_WRITE); |
169 | } | |
170 | ||
171 | void execute() override; | |
172 | ||
11fdf7f2 | 173 | const char* name() const override { return "unlink_bucket"; } |
7c673cae FG |
174 | }; |
175 | ||
176 | void RGWOp_Bucket_Unlink::execute() | |
177 | { | |
178 | std::string uid_str; | |
179 | std::string bucket; | |
180 | ||
181 | RGWBucketAdminOpState op_state; | |
182 | ||
183 | RESTArgs::get_string(s, "uid", uid_str, &uid_str); | |
184 | rgw_user uid(uid_str); | |
185 | ||
186 | RESTArgs::get_string(s, "bucket", bucket, &bucket); | |
187 | ||
188 | op_state.set_user_id(uid); | |
189 | op_state.set_bucket_name(bucket); | |
190 | ||
9f95a23c TL |
191 | if (!store->svc()->zone->is_meta_master()) { |
192 | bufferlist data; | |
193 | op_ret = forward_request_to_master(s, nullptr, store, data, nullptr); | |
194 | if (op_ret < 0) { | |
195 | ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl; | |
196 | return; | |
197 | } | |
198 | } | |
7c673cae FG |
199 | http_ret = RGWBucketAdminOp::unlink(store, op_state); |
200 | } | |
201 | ||
202 | class RGWOp_Bucket_Remove : public RGWRESTOp { | |
203 | ||
204 | public: | |
205 | RGWOp_Bucket_Remove() {} | |
206 | ||
9f95a23c | 207 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
208 | return caps.check_cap("buckets", RGW_CAP_WRITE); |
209 | } | |
210 | ||
211 | void execute() override; | |
212 | ||
11fdf7f2 | 213 | const char* name() const override { return "remove_bucket"; } |
7c673cae FG |
214 | }; |
215 | ||
216 | void RGWOp_Bucket_Remove::execute() | |
217 | { | |
218 | std::string bucket; | |
219 | bool delete_children; | |
220 | ||
221 | RGWBucketAdminOpState op_state; | |
222 | ||
223 | RESTArgs::get_string(s, "bucket", bucket, &bucket); | |
224 | RESTArgs::get_bool(s, "purge-objects", false, &delete_children); | |
225 | ||
226 | op_state.set_bucket_name(bucket); | |
227 | op_state.set_delete_children(delete_children); | |
228 | ||
9f95a23c TL |
229 | if (!store->svc()->zone->is_meta_master()) { |
230 | bufferlist data; | |
231 | op_ret = forward_request_to_master(s, nullptr, store, data, nullptr); | |
232 | if (op_ret < 0) { | |
233 | ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl; | |
234 | return; | |
235 | } | |
236 | } | |
237 | http_ret = RGWBucketAdminOp::remove_bucket(store, op_state, s->yield); | |
7c673cae FG |
238 | } |
239 | ||
94b18763 FG |
240 | class RGWOp_Set_Bucket_Quota : public RGWRESTOp { |
241 | ||
242 | public: | |
243 | RGWOp_Set_Bucket_Quota() {} | |
244 | ||
9f95a23c | 245 | int check_caps(const RGWUserCaps& caps) override { |
94b18763 FG |
246 | return caps.check_cap("buckets", RGW_CAP_WRITE); |
247 | } | |
248 | ||
11fdf7f2 | 249 | void execute() override; |
94b18763 | 250 | |
11fdf7f2 | 251 | const char* name() const override { return "set_bucket_quota"; } |
94b18763 FG |
252 | }; |
253 | ||
254 | #define QUOTA_INPUT_MAX_LEN 1024 | |
255 | ||
256 | void RGWOp_Set_Bucket_Quota::execute() | |
257 | { | |
258 | bool uid_arg_existed = false; | |
259 | std::string uid_str; | |
260 | RESTArgs::get_string(s, "uid", uid_str, &uid_str, &uid_arg_existed); | |
261 | if (! uid_arg_existed) { | |
262 | http_ret = -EINVAL; | |
263 | return; | |
264 | } | |
265 | rgw_user uid(uid_str); | |
266 | bool bucket_arg_existed = false; | |
267 | std::string bucket; | |
268 | RESTArgs::get_string(s, "bucket", bucket, &bucket, &bucket_arg_existed); | |
269 | if (! bucket_arg_existed) { | |
270 | http_ret = -EINVAL; | |
271 | return; | |
272 | } | |
273 | ||
274 | bool use_http_params; | |
275 | ||
276 | if (s->content_length > 0) { | |
277 | use_http_params = false; | |
278 | } else { | |
279 | const char *encoding = s->info.env->get("HTTP_TRANSFER_ENCODING"); | |
280 | use_http_params = (!encoding || strcmp(encoding, "chunked") != 0); | |
281 | } | |
282 | RGWQuotaInfo quota; | |
283 | if (!use_http_params) { | |
284 | bool empty; | |
285 | http_ret = rgw_rest_get_json_input(store->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty); | |
286 | if (http_ret < 0) { | |
287 | if (!empty) | |
288 | return; | |
289 | /* was probably chunked input, but no content provided, configure via http params */ | |
290 | use_http_params = true; | |
291 | } | |
292 | } | |
293 | if (use_http_params) { | |
294 | RGWBucketInfo bucket_info; | |
295 | map<string, bufferlist> attrs; | |
9f95a23c | 296 | http_ret = store->getRados()->get_bucket_info(store->svc(), uid.tenant, bucket, bucket_info, NULL, s->yield, &attrs); |
94b18763 FG |
297 | if (http_ret < 0) { |
298 | return; | |
299 | } | |
300 | RGWQuotaInfo *old_quota = &bucket_info.quota; | |
301 | int64_t old_max_size_kb = rgw_rounded_kb(old_quota->max_size); | |
302 | int64_t max_size_kb; | |
303 | RESTArgs::get_int64(s, "max-objects", old_quota->max_objects, "a.max_objects); | |
304 | RESTArgs::get_int64(s, "max-size-kb", old_max_size_kb, &max_size_kb); | |
305 | quota.max_size = max_size_kb * 1024; | |
306 | RESTArgs::get_bool(s, "enabled", old_quota->enabled, "a.enabled); | |
307 | } | |
308 | ||
309 | RGWBucketAdminOpState op_state; | |
310 | op_state.set_user_id(uid); | |
311 | op_state.set_bucket_name(bucket); | |
312 | op_state.set_quota(quota); | |
313 | ||
314 | http_ret = RGWBucketAdminOp::set_quota(store, op_state); | |
315 | } | |
316 | ||
9f95a23c TL |
317 | class RGWOp_Sync_Bucket : public RGWRESTOp { |
318 | ||
319 | public: | |
320 | RGWOp_Sync_Bucket() {} | |
321 | ||
322 | int check_caps(const RGWUserCaps& caps) override { | |
323 | return caps.check_cap("buckets", RGW_CAP_WRITE); | |
324 | } | |
325 | ||
326 | void execute() override; | |
327 | ||
328 | const char* name() const override { return "sync_bucket"; } | |
329 | }; | |
330 | ||
331 | void RGWOp_Sync_Bucket::execute() | |
332 | { | |
333 | std::string bucket; | |
334 | std::string tenant; | |
335 | bool sync_bucket; | |
336 | ||
337 | RGWBucketAdminOpState op_state; | |
338 | RESTArgs::get_string(s, "bucket", bucket, &bucket); | |
339 | RESTArgs::get_string(s, "tenant", tenant, &tenant); | |
340 | RESTArgs::get_bool(s, "sync", true, &sync_bucket); | |
341 | ||
342 | op_state.set_bucket_name(bucket); | |
343 | op_state.set_tenant(tenant); | |
344 | op_state.set_sync_bucket(sync_bucket); | |
345 | ||
346 | http_ret = RGWBucketAdminOp::sync_bucket(store, op_state); | |
347 | } | |
348 | ||
7c673cae FG |
349 | class RGWOp_Object_Remove: public RGWRESTOp { |
350 | ||
351 | public: | |
352 | RGWOp_Object_Remove() {} | |
353 | ||
9f95a23c | 354 | int check_caps(const RGWUserCaps& caps) override { |
7c673cae FG |
355 | return caps.check_cap("buckets", RGW_CAP_WRITE); |
356 | } | |
357 | ||
358 | void execute() override; | |
359 | ||
11fdf7f2 | 360 | const char* name() const override { return "remove_object"; } |
7c673cae FG |
361 | }; |
362 | ||
363 | void RGWOp_Object_Remove::execute() | |
364 | { | |
365 | std::string bucket; | |
366 | std::string object; | |
367 | ||
368 | RGWBucketAdminOpState op_state; | |
369 | ||
370 | RESTArgs::get_string(s, "bucket", bucket, &bucket); | |
371 | RESTArgs::get_string(s, "object", object, &object); | |
372 | ||
373 | op_state.set_bucket_name(bucket); | |
374 | op_state.set_object(object); | |
375 | ||
376 | http_ret = RGWBucketAdminOp::remove_object(store, op_state); | |
377 | } | |
378 | ||
9f95a23c | 379 | |
7c673cae FG |
380 | RGWOp *RGWHandler_Bucket::op_get() |
381 | { | |
382 | ||
383 | if (s->info.args.sub_resource_exists("policy")) | |
384 | return new RGWOp_Get_Policy; | |
385 | ||
386 | if (s->info.args.sub_resource_exists("index")) | |
387 | return new RGWOp_Check_Bucket_Index; | |
388 | ||
389 | return new RGWOp_Bucket_Info; | |
390 | } | |
391 | ||
392 | RGWOp *RGWHandler_Bucket::op_put() | |
393 | { | |
94b18763 FG |
394 | if (s->info.args.sub_resource_exists("quota")) |
395 | return new RGWOp_Set_Bucket_Quota; | |
9f95a23c TL |
396 | |
397 | if (s->info.args.sub_resource_exists("sync")) | |
398 | return new RGWOp_Sync_Bucket; | |
399 | ||
7c673cae FG |
400 | return new RGWOp_Bucket_Link; |
401 | } | |
402 | ||
403 | RGWOp *RGWHandler_Bucket::op_post() | |
404 | { | |
405 | return new RGWOp_Bucket_Unlink; | |
406 | } | |
407 | ||
408 | RGWOp *RGWHandler_Bucket::op_delete() | |
409 | { | |
410 | if (s->info.args.sub_resource_exists("object")) | |
411 | return new RGWOp_Object_Remove; | |
412 | ||
413 | return new RGWOp_Bucket_Remove; | |
414 | } | |
415 |