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