]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_rest_bucket.cc
import quincy 17.2.0
[ceph.git] / ceph / src / rgw / rgw_rest_bucket.cc
CommitLineData
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 16using namespace std;
9f95a23c 17
7c673cae
FG
18class RGWOp_Bucket_Info : public RGWRESTOp {
19
20public:
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 32void 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
55class RGWOp_Get_Policy : public RGWRESTOp {
56
57public:
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 69void 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
85class RGWOp_Check_Bucket_Index : public RGWRESTOp {
86
87public:
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 99void 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
119class RGWOp_Bucket_Link : public RGWRESTOp {
120
121public:
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 133void 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
162class RGWOp_Bucket_Unlink : public RGWRESTOp {
163
164public:
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 176void 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
200class RGWOp_Bucket_Remove : public RGWRESTOp {
201
202public:
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 214void 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
237class RGWOp_Set_Bucket_Quota : public RGWRESTOp {
238
239public:
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 253void 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, &quota.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, &quota.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
313class RGWOp_Sync_Bucket : public RGWRESTOp {
314
315public:
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 327void 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
345class RGWOp_Object_Remove: public RGWRESTOp {
346
347public:
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 359void 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
376RGWOp *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
388RGWOp *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
399RGWOp *RGWHandler_Bucket::op_post()
400{
401 return new RGWOp_Bucket_Unlink;
402}
403
404RGWOp *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}