]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_bucket.cc
3a07cebf0a68f9cbfa20f49ac11e01ebdf95c0e7
[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);
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);
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);
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->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);
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->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);
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 op_ret = store->get_bucket(nullptr, string(), bucket_name, &bucket, y);
223 if (op_ret < 0) {
224 ldpp_dout(this, 0) << "get_bucket returned ret=" << op_ret << dendl;
225 return;
226 }
227
228 op_ret = bucket->remove_bucket(delete_children, string(), string(), true, &s->info, s->yield);
229 }
230
231 class RGWOp_Set_Bucket_Quota : public RGWRESTOp {
232
233 public:
234 RGWOp_Set_Bucket_Quota() {}
235
236 int check_caps(const RGWUserCaps& caps) override {
237 return caps.check_cap("buckets", RGW_CAP_WRITE);
238 }
239
240 void execute(optional_yield y) override;
241
242 const char* name() const override { return "set_bucket_quota"; }
243 };
244
245 #define QUOTA_INPUT_MAX_LEN 1024
246
247 void RGWOp_Set_Bucket_Quota::execute(optional_yield y)
248 {
249 bool uid_arg_existed = false;
250 std::string uid_str;
251 RESTArgs::get_string(s, "uid", uid_str, &uid_str, &uid_arg_existed);
252 if (! uid_arg_existed) {
253 op_ret = -EINVAL;
254 return;
255 }
256 rgw_user uid(uid_str);
257 bool bucket_arg_existed = false;
258 std::string bucket;
259 RESTArgs::get_string(s, "bucket", bucket, &bucket, &bucket_arg_existed);
260 if (! bucket_arg_existed) {
261 op_ret = -EINVAL;
262 return;
263 }
264
265 bool use_http_params;
266
267 if (s->content_length > 0) {
268 use_http_params = false;
269 } else {
270 const char *encoding = s->info.env->get("HTTP_TRANSFER_ENCODING");
271 use_http_params = (!encoding || strcmp(encoding, "chunked") != 0);
272 }
273 RGWQuotaInfo quota;
274 if (!use_http_params) {
275 bool empty;
276 op_ret = rgw_rest_get_json_input(store->ctx(), s, quota, QUOTA_INPUT_MAX_LEN, &empty);
277 if (op_ret < 0) {
278 if (!empty)
279 return;
280 /* was probably chunked input, but no content provided, configure via http params */
281 use_http_params = true;
282 }
283 }
284 if (use_http_params) {
285 RGWBucketInfo bucket_info;
286 map<string, bufferlist> attrs;
287 op_ret = store->getRados()->get_bucket_info(store->svc(), uid.tenant, bucket, bucket_info, NULL, s->yield, &attrs);
288 if (op_ret < 0) {
289 return;
290 }
291 RGWQuotaInfo *old_quota = &bucket_info.quota;
292 int64_t old_max_size_kb = rgw_rounded_kb(old_quota->max_size);
293 int64_t max_size_kb;
294 RESTArgs::get_int64(s, "max-objects", old_quota->max_objects, &quota.max_objects);
295 RESTArgs::get_int64(s, "max-size-kb", old_max_size_kb, &max_size_kb);
296 quota.max_size = max_size_kb * 1024;
297 RESTArgs::get_bool(s, "enabled", old_quota->enabled, &quota.enabled);
298 }
299
300 RGWBucketAdminOpState op_state;
301 op_state.set_user_id(uid);
302 op_state.set_bucket_name(bucket);
303 op_state.set_quota(quota);
304
305 op_ret = RGWBucketAdminOp::set_quota(store, op_state);
306 }
307
308 class RGWOp_Sync_Bucket : public RGWRESTOp {
309
310 public:
311 RGWOp_Sync_Bucket() {}
312
313 int check_caps(const RGWUserCaps& caps) override {
314 return caps.check_cap("buckets", RGW_CAP_WRITE);
315 }
316
317 void execute(optional_yield y) override;
318
319 const char* name() const override { return "sync_bucket"; }
320 };
321
322 void RGWOp_Sync_Bucket::execute(optional_yield y)
323 {
324 std::string bucket;
325 std::string tenant;
326 bool sync_bucket;
327
328 RGWBucketAdminOpState op_state;
329 RESTArgs::get_string(s, "bucket", bucket, &bucket);
330 RESTArgs::get_string(s, "tenant", tenant, &tenant);
331 RESTArgs::get_bool(s, "sync", true, &sync_bucket);
332
333 op_state.set_bucket_name(bucket);
334 op_state.set_tenant(tenant);
335 op_state.set_sync_bucket(sync_bucket);
336
337 op_ret = RGWBucketAdminOp::sync_bucket(store, op_state);
338 }
339
340 class RGWOp_Object_Remove: public RGWRESTOp {
341
342 public:
343 RGWOp_Object_Remove() {}
344
345 int check_caps(const RGWUserCaps& caps) override {
346 return caps.check_cap("buckets", RGW_CAP_WRITE);
347 }
348
349 void execute(optional_yield y) override;
350
351 const char* name() const override { return "remove_object"; }
352 };
353
354 void RGWOp_Object_Remove::execute(optional_yield y)
355 {
356 std::string bucket;
357 std::string object;
358
359 RGWBucketAdminOpState op_state;
360
361 RESTArgs::get_string(s, "bucket", bucket, &bucket);
362 RESTArgs::get_string(s, "object", object, &object);
363
364 op_state.set_bucket_name(bucket);
365 op_state.set_object(object);
366
367 op_ret = RGWBucketAdminOp::remove_object(store, op_state);
368 }
369
370
371 RGWOp *RGWHandler_Bucket::op_get()
372 {
373
374 if (s->info.args.sub_resource_exists("policy"))
375 return new RGWOp_Get_Policy;
376
377 if (s->info.args.sub_resource_exists("index"))
378 return new RGWOp_Check_Bucket_Index;
379
380 return new RGWOp_Bucket_Info;
381 }
382
383 RGWOp *RGWHandler_Bucket::op_put()
384 {
385 if (s->info.args.sub_resource_exists("quota"))
386 return new RGWOp_Set_Bucket_Quota;
387
388 if (s->info.args.sub_resource_exists("sync"))
389 return new RGWOp_Sync_Bucket;
390
391 return new RGWOp_Bucket_Link;
392 }
393
394 RGWOp *RGWHandler_Bucket::op_post()
395 {
396 return new RGWOp_Bucket_Unlink;
397 }
398
399 RGWOp *RGWHandler_Bucket::op_delete()
400 {
401 if (s->info.args.sub_resource_exists("object"))
402 return new RGWOp_Object_Remove;
403
404 return new RGWOp_Bucket_Remove;
405 }
406