1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
5 #include "rgw_bucket.h"
6 #include "rgw_rest_bucket.h"
7 #include "rgw_sal_rados.h"
9 #include "include/str_list.h"
11 #include "services/svc_sys_obj.h"
12 #include "services/svc_zone.h"
14 #define dout_subsys ceph_subsys_rgw
17 class RGWOp_Bucket_Info
: public RGWRESTOp
{
20 RGWOp_Bucket_Info() {}
22 int check_caps(const RGWUserCaps
& caps
) override
{
23 return caps
.check_cap("buckets", RGW_CAP_READ
);
26 void execute(optional_yield y
) override
;
28 const char* name() const override
{ return "get_bucket_info"; }
31 void RGWOp_Bucket_Info::execute(optional_yield y
)
33 RGWBucketAdminOpState op_state
;
41 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
42 rgw_user
uid(uid_str
);
44 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
45 RESTArgs::get_bool(s
, "stats", false, &fetch_stats
);
47 op_state
.set_user_id(uid
);
48 op_state
.set_bucket_name(bucket
);
49 op_state
.set_fetch_stats(fetch_stats
);
51 op_ret
= RGWBucketAdminOp::info(store
, op_state
, flusher
, y
);
54 class RGWOp_Get_Policy
: public RGWRESTOp
{
59 int check_caps(const RGWUserCaps
& caps
) override
{
60 return caps
.check_cap("buckets", RGW_CAP_READ
);
63 void execute(optional_yield y
) override
;
65 const char* name() const override
{ return "get_policy"; }
68 void RGWOp_Get_Policy::execute(optional_yield y
)
70 RGWBucketAdminOpState op_state
;
75 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
76 RESTArgs::get_string(s
, "object", object
, &object
);
78 op_state
.set_bucket_name(bucket
);
79 op_state
.set_object(object
);
81 op_ret
= RGWBucketAdminOp::get_policy(store
, op_state
, flusher
);
84 class RGWOp_Check_Bucket_Index
: public RGWRESTOp
{
87 RGWOp_Check_Bucket_Index() {}
89 int check_caps(const RGWUserCaps
& caps
) override
{
90 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
93 void execute(optional_yield y
) override
;
95 const char* name() const override
{ return "check_bucket_index"; }
98 void RGWOp_Check_Bucket_Index::execute(optional_yield y
)
105 RGWBucketAdminOpState op_state
;
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
);
111 op_state
.set_bucket_name(bucket
);
112 op_state
.set_fix_index(fix_index
);
113 op_state
.set_check_objects(check_objects
);
115 op_ret
= RGWBucketAdminOp::check_index(store
, op_state
, flusher
, s
->yield
);
118 class RGWOp_Bucket_Link
: public RGWRESTOp
{
121 RGWOp_Bucket_Link() {}
123 int check_caps(const RGWUserCaps
& caps
) override
{
124 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
127 void execute(optional_yield y
) override
;
129 const char* name() const override
{ return "link_bucket"; }
132 void RGWOp_Bucket_Link::execute(optional_yield y
)
136 std::string bucket_id
;
137 std::string new_bucket_name
;
139 RGWBucketAdminOpState op_state
;
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
);
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
);
153 op_ret
= store
->forward_request_to_master(s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
155 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
158 op_ret
= RGWBucketAdminOp::link(store
, op_state
);
161 class RGWOp_Bucket_Unlink
: public RGWRESTOp
{
164 RGWOp_Bucket_Unlink() {}
166 int check_caps(const RGWUserCaps
& caps
) override
{
167 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
170 void execute(optional_yield y
) override
;
172 const char* name() const override
{ return "unlink_bucket"; }
175 void RGWOp_Bucket_Unlink::execute(optional_yield y
)
180 RGWBucketAdminOpState op_state
;
182 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
183 rgw_user
uid(uid_str
);
185 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
187 op_state
.set_user_id(uid
);
188 op_state
.set_bucket_name(bucket
);
191 op_ret
= store
->forward_request_to_master(s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
193 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
196 op_ret
= RGWBucketAdminOp::unlink(store
, op_state
);
199 class RGWOp_Bucket_Remove
: public RGWRESTOp
{
202 RGWOp_Bucket_Remove() {}
204 int check_caps(const RGWUserCaps
& caps
) override
{
205 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
208 void execute(optional_yield y
) override
;
210 const char* name() const override
{ return "remove_bucket"; }
213 void RGWOp_Bucket_Remove::execute(optional_yield y
)
215 std::string bucket_name
;
216 bool delete_children
;
217 std::unique_ptr
<rgw::sal::RGWBucket
> bucket
;
219 RESTArgs::get_string(s
, "bucket", bucket_name
, &bucket_name
);
220 RESTArgs::get_bool(s
, "purge-objects", false, &delete_children
);
222 op_ret
= store
->get_bucket(nullptr, string(), bucket_name
, &bucket
, y
);
224 ldpp_dout(this, 0) << "get_bucket returned ret=" << op_ret
<< dendl
;
228 op_ret
= bucket
->remove_bucket(delete_children
, string(), string(), true, &s
->info
, s
->yield
);
231 class RGWOp_Set_Bucket_Quota
: public RGWRESTOp
{
234 RGWOp_Set_Bucket_Quota() {}
236 int check_caps(const RGWUserCaps
& caps
) override
{
237 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
240 void execute(optional_yield y
) override
;
242 const char* name() const override
{ return "set_bucket_quota"; }
245 #define QUOTA_INPUT_MAX_LEN 1024
247 void RGWOp_Set_Bucket_Quota::execute(optional_yield y
)
249 bool uid_arg_existed
= false;
251 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
, &uid_arg_existed
);
252 if (! uid_arg_existed
) {
256 rgw_user
uid(uid_str
);
257 bool bucket_arg_existed
= false;
259 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
, &bucket_arg_existed
);
260 if (! bucket_arg_existed
) {
265 bool use_http_params
;
267 if (s
->content_length
> 0) {
268 use_http_params
= false;
270 const char *encoding
= s
->info
.env
->get("HTTP_TRANSFER_ENCODING");
271 use_http_params
= (!encoding
|| strcmp(encoding
, "chunked") != 0);
274 if (!use_http_params
) {
276 op_ret
= rgw_rest_get_json_input(store
->ctx(), s
, quota
, QUOTA_INPUT_MAX_LEN
, &empty
);
280 /* was probably chunked input, but no content provided, configure via http params */
281 use_http_params
= true;
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
);
291 RGWQuotaInfo
*old_quota
= &bucket_info
.quota
;
292 int64_t old_max_size_kb
= rgw_rounded_kb(old_quota
->max_size
);
294 RESTArgs::get_int64(s
, "max-objects", old_quota
->max_objects
, "a
.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
, "a
.enabled
);
300 RGWBucketAdminOpState op_state
;
301 op_state
.set_user_id(uid
);
302 op_state
.set_bucket_name(bucket
);
303 op_state
.set_quota(quota
);
305 op_ret
= RGWBucketAdminOp::set_quota(store
, op_state
);
308 class RGWOp_Sync_Bucket
: public RGWRESTOp
{
311 RGWOp_Sync_Bucket() {}
313 int check_caps(const RGWUserCaps
& caps
) override
{
314 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
317 void execute(optional_yield y
) override
;
319 const char* name() const override
{ return "sync_bucket"; }
322 void RGWOp_Sync_Bucket::execute(optional_yield y
)
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
);
333 op_state
.set_bucket_name(bucket
);
334 op_state
.set_tenant(tenant
);
335 op_state
.set_sync_bucket(sync_bucket
);
337 op_ret
= RGWBucketAdminOp::sync_bucket(store
, op_state
);
340 class RGWOp_Object_Remove
: public RGWRESTOp
{
343 RGWOp_Object_Remove() {}
345 int check_caps(const RGWUserCaps
& caps
) override
{
346 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
349 void execute(optional_yield y
) override
;
351 const char* name() const override
{ return "remove_object"; }
354 void RGWOp_Object_Remove::execute(optional_yield y
)
359 RGWBucketAdminOpState op_state
;
361 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
362 RESTArgs::get_string(s
, "object", object
, &object
);
364 op_state
.set_bucket_name(bucket
);
365 op_state
.set_object(object
);
367 op_ret
= RGWBucketAdminOp::remove_object(store
, op_state
);
371 RGWOp
*RGWHandler_Bucket::op_get()
374 if (s
->info
.args
.sub_resource_exists("policy"))
375 return new RGWOp_Get_Policy
;
377 if (s
->info
.args
.sub_resource_exists("index"))
378 return new RGWOp_Check_Bucket_Index
;
380 return new RGWOp_Bucket_Info
;
383 RGWOp
*RGWHandler_Bucket::op_put()
385 if (s
->info
.args
.sub_resource_exists("quota"))
386 return new RGWOp_Set_Bucket_Quota
;
388 if (s
->info
.args
.sub_resource_exists("sync"))
389 return new RGWOp_Sync_Bucket
;
391 return new RGWOp_Bucket_Link
;
394 RGWOp
*RGWHandler_Bucket::op_post()
396 return new RGWOp_Bucket_Unlink
;
399 RGWOp
*RGWHandler_Bucket::op_delete()
401 if (s
->info
.args
.sub_resource_exists("object"))
402 return new RGWOp_Object_Remove
;
404 return new RGWOp_Bucket_Remove
;