]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/driver/rados/rgw_rest_bucket.cc
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / rgw / driver / rados / 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 "driver/rados/rgw_bucket.h"
6 #include "rgw_rest_bucket.h"
7 #include "rgw_sal.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 using namespace std;
17
18 class RGWOp_Bucket_Info : public RGWRESTOp {
19
20 public:
21 RGWOp_Bucket_Info() {}
22
23 int check_caps(const RGWUserCaps& caps) override {
24 return caps.check_cap("buckets", RGW_CAP_READ);
25 }
26
27 void execute(optional_yield y) override;
28
29 const char* name() const override { return "get_bucket_info"; }
30 };
31
32 void RGWOp_Bucket_Info::execute(optional_yield y)
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
52 op_ret = RGWBucketAdminOp::info(driver, op_state, flusher, y, this);
53 }
54
55 class RGWOp_Get_Policy : public RGWRESTOp {
56
57 public:
58 RGWOp_Get_Policy() {}
59
60 int check_caps(const RGWUserCaps& caps) override {
61 return caps.check_cap("buckets", RGW_CAP_READ);
62 }
63
64 void execute(optional_yield y) override;
65
66 const char* name() const override { return "get_policy"; }
67 };
68
69 void RGWOp_Get_Policy::execute(optional_yield y)
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
82 op_ret = RGWBucketAdminOp::get_policy(driver, op_state, flusher, this);
83 }
84
85 class RGWOp_Check_Bucket_Index : public RGWRESTOp {
86
87 public:
88 RGWOp_Check_Bucket_Index() {}
89
90 int check_caps(const RGWUserCaps& caps) override {
91 return caps.check_cap("buckets", RGW_CAP_WRITE);
92 }
93
94 void execute(optional_yield y) override;
95
96 const char* name() const override { return "check_bucket_index"; }
97 };
98
99 void RGWOp_Check_Bucket_Index::execute(optional_yield y)
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
116 op_ret = RGWBucketAdminOp::check_index(driver, op_state, flusher, s->yield, s);
117 }
118
119 class RGWOp_Bucket_Link : public RGWRESTOp {
120
121 public:
122 RGWOp_Bucket_Link() {}
123
124 int check_caps(const RGWUserCaps& caps) override {
125 return caps.check_cap("buckets", RGW_CAP_WRITE);
126 }
127
128 void execute(optional_yield y) override;
129
130 const char* name() const override { return "link_bucket"; }
131 };
132
133 void RGWOp_Bucket_Link::execute(optional_yield y)
134 {
135 std::string uid_str;
136 std::string bucket;
137 std::string bucket_id;
138 std::string new_bucket_name;
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);
145 RESTArgs::get_string(s, "new-bucket-name", new_bucket_name, &new_bucket_name);
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);
151 op_state.set_new_bucket_name(new_bucket_name);
152
153 bufferlist data;
154 op_ret = driver->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
155 if (op_ret < 0) {
156 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
157 return;
158 }
159 op_ret = RGWBucketAdminOp::link(driver, op_state, s);
160 }
161
162 class RGWOp_Bucket_Unlink : public RGWRESTOp {
163
164 public:
165 RGWOp_Bucket_Unlink() {}
166
167 int check_caps(const RGWUserCaps& caps) override {
168 return caps.check_cap("buckets", RGW_CAP_WRITE);
169 }
170
171 void execute(optional_yield y) override;
172
173 const char* name() const override { return "unlink_bucket"; }
174 };
175
176 void RGWOp_Bucket_Unlink::execute(optional_yield y)
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
191 bufferlist data;
192 op_ret = driver->forward_request_to_master(s, s->user.get(), nullptr, data, nullptr, s->info, y);
193 if (op_ret < 0) {
194 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
195 return;
196 }
197 op_ret = RGWBucketAdminOp::unlink(driver, op_state, s);
198 }
199
200 class RGWOp_Bucket_Remove : public RGWRESTOp {
201
202 public:
203 RGWOp_Bucket_Remove() {}
204
205 int check_caps(const RGWUserCaps& caps) override {
206 return caps.check_cap("buckets", RGW_CAP_WRITE);
207 }
208
209 void execute(optional_yield y) override;
210
211 const char* name() const override { return "remove_bucket"; }
212 };
213
214 void RGWOp_Bucket_Remove::execute(optional_yield y)
215 {
216 std::string bucket_name;
217 bool delete_children;
218 std::unique_ptr<rgw::sal::Bucket> bucket;
219
220 RESTArgs::get_string(s, "bucket", bucket_name, &bucket_name);
221 RESTArgs::get_bool(s, "purge-objects", false, &delete_children);
222
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 = driver->get_bucket(s, s->user.get(), string(), bucket_name, &bucket, y);
226 if (op_ret < 0) {
227 ldpp_dout(this, 0) << "get_bucket returned ret=" << op_ret << dendl;
228 if (op_ret == -ENOENT) {
229 op_ret = -ERR_NO_SUCH_BUCKET;
230 }
231 return;
232 }
233
234 op_ret = bucket->remove_bucket(s, delete_children, true, &s->info, s->yield);
235 }
236
237 class RGWOp_Set_Bucket_Quota : public RGWRESTOp {
238
239 public:
240 RGWOp_Set_Bucket_Quota() {}
241
242 int check_caps(const RGWUserCaps& caps) override {
243 return caps.check_cap("buckets", RGW_CAP_WRITE);
244 }
245
246 void execute(optional_yield y) override;
247
248 const char* name() const override { return "set_bucket_quota"; }
249 };
250
251 #define QUOTA_INPUT_MAX_LEN 1024
252
253 void RGWOp_Set_Bucket_Quota::execute(optional_yield y)
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) {
259 op_ret = -EINVAL;
260 return;
261 }
262 rgw_user uid(uid_str);
263 bool bucket_arg_existed = false;
264 std::string bucket_name;
265 RESTArgs::get_string(s, "bucket", bucket_name, &bucket_name, &bucket_arg_existed);
266 if (! bucket_arg_existed) {
267 op_ret = -EINVAL;
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;
282 op_ret = get_json_input(driver->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty);
283 if (op_ret < 0) {
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) {
291 std::unique_ptr<rgw::sal::Bucket> bucket;
292 op_ret = driver->get_bucket(s, nullptr, uid.tenant, bucket_name, &bucket, s->yield);
293 if (op_ret < 0) {
294 return;
295 }
296 RGWQuotaInfo *old_quota = &bucket->get_info().quota;
297 int64_t old_max_size_kb = rgw_rounded_kb(old_quota->max_size);
298 int64_t max_size_kb;
299 bool has_max_size_kb = false;
300 RESTArgs::get_int64(s, "max-objects", old_quota->max_objects, &quota.max_objects);
301 RESTArgs::get_int64(s, "max-size", old_quota->max_size, &quota.max_size);
302 RESTArgs::get_int64(s, "max-size-kb", old_max_size_kb, &max_size_kb, &has_max_size_kb);
303 if (has_max_size_kb)
304 quota.max_size = max_size_kb * 1024;
305 RESTArgs::get_bool(s, "enabled", old_quota->enabled, &quota.enabled);
306 }
307
308 RGWBucketAdminOpState op_state;
309 op_state.set_user_id(uid);
310 op_state.set_bucket_name(bucket_name);
311 op_state.set_quota(quota);
312
313 op_ret = RGWBucketAdminOp::set_quota(driver, op_state, s);
314 }
315
316 class RGWOp_Sync_Bucket : public RGWRESTOp {
317
318 public:
319 RGWOp_Sync_Bucket() {}
320
321 int check_caps(const RGWUserCaps& caps) override {
322 return caps.check_cap("buckets", RGW_CAP_WRITE);
323 }
324
325 void execute(optional_yield y) override;
326
327 const char* name() const override { return "sync_bucket"; }
328 };
329
330 void RGWOp_Sync_Bucket::execute(optional_yield y)
331 {
332 std::string bucket;
333 std::string tenant;
334 bool sync_bucket;
335
336 RGWBucketAdminOpState op_state;
337 RESTArgs::get_string(s, "bucket", bucket, &bucket);
338 RESTArgs::get_string(s, "tenant", tenant, &tenant);
339 RESTArgs::get_bool(s, "sync", true, &sync_bucket);
340
341 op_state.set_bucket_name(bucket);
342 op_state.set_tenant(tenant);
343 op_state.set_sync_bucket(sync_bucket);
344
345 op_ret = RGWBucketAdminOp::sync_bucket(driver, op_state, s);
346 }
347
348 class RGWOp_Object_Remove: public RGWRESTOp {
349
350 public:
351 RGWOp_Object_Remove() {}
352
353 int check_caps(const RGWUserCaps& caps) override {
354 return caps.check_cap("buckets", RGW_CAP_WRITE);
355 }
356
357 void execute(optional_yield y) override;
358
359 const char* name() const override { return "remove_object"; }
360 };
361
362 void RGWOp_Object_Remove::execute(optional_yield y)
363 {
364 std::string bucket;
365 std::string object;
366
367 RGWBucketAdminOpState op_state;
368
369 RESTArgs::get_string(s, "bucket", bucket, &bucket);
370 RESTArgs::get_string(s, "object", object, &object);
371
372 op_state.set_bucket_name(bucket);
373 op_state.set_object(object);
374
375 op_ret = RGWBucketAdminOp::remove_object(driver, op_state, s);
376 }
377
378
379 RGWOp *RGWHandler_Bucket::op_get()
380 {
381
382 if (s->info.args.sub_resource_exists("policy"))
383 return new RGWOp_Get_Policy;
384
385 if (s->info.args.sub_resource_exists("index"))
386 return new RGWOp_Check_Bucket_Index;
387
388 return new RGWOp_Bucket_Info;
389 }
390
391 RGWOp *RGWHandler_Bucket::op_put()
392 {
393 if (s->info.args.sub_resource_exists("quota"))
394 return new RGWOp_Set_Bucket_Quota;
395
396 if (s->info.args.sub_resource_exists("sync"))
397 return new RGWOp_Sync_Bucket;
398
399 return new RGWOp_Bucket_Link;
400 }
401
402 RGWOp *RGWHandler_Bucket::op_post()
403 {
404 return new RGWOp_Bucket_Unlink;
405 }
406
407 RGWOp *RGWHandler_Bucket::op_delete()
408 {
409 if (s->info.args.sub_resource_exists("object"))
410 return new RGWOp_Object_Remove;
411
412 return new RGWOp_Bucket_Remove;
413 }