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
, this);
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
, this);
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
, s
);
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
, 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
, s
);
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
, 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
, s
);
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 /* 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
);
226 ldpp_dout(this, 0) << "get_bucket returned ret=" << op_ret
<< dendl
;
230 op_ret
= bucket
->remove_bucket(s
, delete_children
, true, &s
->info
, s
->yield
);
233 class RGWOp_Set_Bucket_Quota
: public RGWRESTOp
{
236 RGWOp_Set_Bucket_Quota() {}
238 int check_caps(const RGWUserCaps
& caps
) override
{
239 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
242 void execute(optional_yield y
) override
;
244 const char* name() const override
{ return "set_bucket_quota"; }
247 #define QUOTA_INPUT_MAX_LEN 1024
249 void RGWOp_Set_Bucket_Quota::execute(optional_yield y
)
251 bool uid_arg_existed
= false;
253 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
, &uid_arg_existed
);
254 if (! uid_arg_existed
) {
258 rgw_user
uid(uid_str
);
259 bool bucket_arg_existed
= false;
261 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
, &bucket_arg_existed
);
262 if (! bucket_arg_existed
) {
267 bool use_http_params
;
269 if (s
->content_length
> 0) {
270 use_http_params
= false;
272 const char *encoding
= s
->info
.env
->get("HTTP_TRANSFER_ENCODING");
273 use_http_params
= (!encoding
|| strcmp(encoding
, "chunked") != 0);
276 if (!use_http_params
) {
278 op_ret
= rgw_rest_get_json_input(store
->ctx(), s
, quota
, QUOTA_INPUT_MAX_LEN
, &empty
);
282 /* was probably chunked input, but no content provided, configure via http params */
283 use_http_params
= true;
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
);
293 RGWQuotaInfo
*old_quota
= &bucket_info
.quota
;
294 int64_t old_max_size_kb
= rgw_rounded_kb(old_quota
->max_size
);
296 RESTArgs::get_int64(s
, "max-objects", old_quota
->max_objects
, "a
.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
, "a
.enabled
);
302 RGWBucketAdminOpState op_state
;
303 op_state
.set_user_id(uid
);
304 op_state
.set_bucket_name(bucket
);
305 op_state
.set_quota(quota
);
307 op_ret
= RGWBucketAdminOp::set_quota(store
, op_state
, s
);
310 class RGWOp_Sync_Bucket
: public RGWRESTOp
{
313 RGWOp_Sync_Bucket() {}
315 int check_caps(const RGWUserCaps
& caps
) override
{
316 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
319 void execute(optional_yield y
) override
;
321 const char* name() const override
{ return "sync_bucket"; }
324 void RGWOp_Sync_Bucket::execute(optional_yield y
)
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
);
335 op_state
.set_bucket_name(bucket
);
336 op_state
.set_tenant(tenant
);
337 op_state
.set_sync_bucket(sync_bucket
);
339 op_ret
= RGWBucketAdminOp::sync_bucket(store
, op_state
, s
);
342 class RGWOp_Object_Remove
: public RGWRESTOp
{
345 RGWOp_Object_Remove() {}
347 int check_caps(const RGWUserCaps
& caps
) override
{
348 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
351 void execute(optional_yield y
) override
;
353 const char* name() const override
{ return "remove_object"; }
356 void RGWOp_Object_Remove::execute(optional_yield y
)
361 RGWBucketAdminOpState op_state
;
363 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
364 RESTArgs::get_string(s
, "object", object
, &object
);
366 op_state
.set_bucket_name(bucket
);
367 op_state
.set_object(object
);
369 op_ret
= RGWBucketAdminOp::remove_object(store
, op_state
, s
);
373 RGWOp
*RGWHandler_Bucket::op_get()
376 if (s
->info
.args
.sub_resource_exists("policy"))
377 return new RGWOp_Get_Policy
;
379 if (s
->info
.args
.sub_resource_exists("index"))
380 return new RGWOp_Check_Bucket_Index
;
382 return new RGWOp_Bucket_Info
;
385 RGWOp
*RGWHandler_Bucket::op_put()
387 if (s
->info
.args
.sub_resource_exists("quota"))
388 return new RGWOp_Set_Bucket_Quota
;
390 if (s
->info
.args
.sub_resource_exists("sync"))
391 return new RGWOp_Sync_Bucket
;
393 return new RGWOp_Bucket_Link
;
396 RGWOp
*RGWHandler_Bucket::op_post()
398 return new RGWOp_Bucket_Unlink
;
401 RGWOp
*RGWHandler_Bucket::op_delete()
403 if (s
->info
.args
.sub_resource_exists("object"))
404 return new RGWOp_Object_Remove
;
406 return new RGWOp_Bucket_Remove
;