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