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 "driver/rados/rgw_bucket.h"
6 #include "rgw_rest_bucket.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
18 class RGWOp_Bucket_Info
: public RGWRESTOp
{
21 RGWOp_Bucket_Info() {}
23 int check_caps(const RGWUserCaps
& caps
) override
{
24 return caps
.check_cap("buckets", RGW_CAP_READ
);
27 void execute(optional_yield y
) override
;
29 const char* name() const override
{ return "get_bucket_info"; }
32 void RGWOp_Bucket_Info::execute(optional_yield y
)
34 RGWBucketAdminOpState op_state
;
42 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
43 rgw_user
uid(uid_str
);
45 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
46 RESTArgs::get_bool(s
, "stats", false, &fetch_stats
);
48 op_state
.set_user_id(uid
);
49 op_state
.set_bucket_name(bucket
);
50 op_state
.set_fetch_stats(fetch_stats
);
52 op_ret
= RGWBucketAdminOp::info(driver
, op_state
, flusher
, y
, this);
55 class RGWOp_Get_Policy
: public RGWRESTOp
{
60 int check_caps(const RGWUserCaps
& caps
) override
{
61 return caps
.check_cap("buckets", RGW_CAP_READ
);
64 void execute(optional_yield y
) override
;
66 const char* name() const override
{ return "get_policy"; }
69 void RGWOp_Get_Policy::execute(optional_yield y
)
71 RGWBucketAdminOpState op_state
;
76 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
77 RESTArgs::get_string(s
, "object", object
, &object
);
79 op_state
.set_bucket_name(bucket
);
80 op_state
.set_object(object
);
82 op_ret
= RGWBucketAdminOp::get_policy(driver
, op_state
, flusher
, this);
85 class RGWOp_Check_Bucket_Index
: public RGWRESTOp
{
88 RGWOp_Check_Bucket_Index() {}
90 int check_caps(const RGWUserCaps
& caps
) override
{
91 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
94 void execute(optional_yield y
) override
;
96 const char* name() const override
{ return "check_bucket_index"; }
99 void RGWOp_Check_Bucket_Index::execute(optional_yield y
)
106 RGWBucketAdminOpState op_state
;
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
);
112 op_state
.set_bucket_name(bucket
);
113 op_state
.set_fix_index(fix_index
);
114 op_state
.set_check_objects(check_objects
);
116 op_ret
= RGWBucketAdminOp::check_index(driver
, op_state
, flusher
, s
->yield
, s
);
119 class RGWOp_Bucket_Link
: public RGWRESTOp
{
122 RGWOp_Bucket_Link() {}
124 int check_caps(const RGWUserCaps
& caps
) override
{
125 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
128 void execute(optional_yield y
) override
;
130 const char* name() const override
{ return "link_bucket"; }
133 void RGWOp_Bucket_Link::execute(optional_yield y
)
137 std::string bucket_id
;
138 std::string new_bucket_name
;
140 RGWBucketAdminOpState op_state
;
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
);
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
);
154 op_ret
= driver
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
156 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
159 op_ret
= RGWBucketAdminOp::link(driver
, op_state
, s
);
162 class RGWOp_Bucket_Unlink
: public RGWRESTOp
{
165 RGWOp_Bucket_Unlink() {}
167 int check_caps(const RGWUserCaps
& caps
) override
{
168 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
171 void execute(optional_yield y
) override
;
173 const char* name() const override
{ return "unlink_bucket"; }
176 void RGWOp_Bucket_Unlink::execute(optional_yield y
)
181 RGWBucketAdminOpState op_state
;
183 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
);
184 rgw_user
uid(uid_str
);
186 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
188 op_state
.set_user_id(uid
);
189 op_state
.set_bucket_name(bucket
);
192 op_ret
= driver
->forward_request_to_master(s
, s
->user
.get(), nullptr, data
, nullptr, s
->info
, y
);
194 ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret
<< dendl
;
197 op_ret
= RGWBucketAdminOp::unlink(driver
, op_state
, s
);
200 class RGWOp_Bucket_Remove
: public RGWRESTOp
{
203 RGWOp_Bucket_Remove() {}
205 int check_caps(const RGWUserCaps
& caps
) override
{
206 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
209 void execute(optional_yield y
) override
;
211 const char* name() const override
{ return "remove_bucket"; }
214 void RGWOp_Bucket_Remove::execute(optional_yield y
)
216 std::string bucket_name
;
217 bool delete_children
;
218 std::unique_ptr
<rgw::sal::Bucket
> bucket
;
220 RESTArgs::get_string(s
, "bucket", bucket_name
, &bucket_name
);
221 RESTArgs::get_bool(s
, "purge-objects", false, &delete_children
);
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
);
227 ldpp_dout(this, 0) << "get_bucket returned ret=" << op_ret
<< dendl
;
228 if (op_ret
== -ENOENT
) {
229 op_ret
= -ERR_NO_SUCH_BUCKET
;
234 op_ret
= bucket
->remove_bucket(s
, delete_children
, true, &s
->info
, s
->yield
);
237 class RGWOp_Set_Bucket_Quota
: public RGWRESTOp
{
240 RGWOp_Set_Bucket_Quota() {}
242 int check_caps(const RGWUserCaps
& caps
) override
{
243 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
246 void execute(optional_yield y
) override
;
248 const char* name() const override
{ return "set_bucket_quota"; }
251 #define QUOTA_INPUT_MAX_LEN 1024
253 void RGWOp_Set_Bucket_Quota::execute(optional_yield y
)
255 bool uid_arg_existed
= false;
257 RESTArgs::get_string(s
, "uid", uid_str
, &uid_str
, &uid_arg_existed
);
258 if (! uid_arg_existed
) {
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
) {
271 bool use_http_params
;
273 if (s
->content_length
> 0) {
274 use_http_params
= false;
276 const char *encoding
= s
->info
.env
->get("HTTP_TRANSFER_ENCODING");
277 use_http_params
= (!encoding
|| strcmp(encoding
, "chunked") != 0);
280 if (!use_http_params
) {
282 op_ret
= get_json_input(driver
->ctx(), s
, quota
, QUOTA_INPUT_MAX_LEN
, &empty
);
286 /* was probably chunked input, but no content provided, configure via http params */
287 use_http_params
= true;
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
);
296 RGWQuotaInfo
*old_quota
= &bucket
->get_info().quota
;
297 int64_t old_max_size_kb
= rgw_rounded_kb(old_quota
->max_size
);
299 bool has_max_size_kb
= false;
300 RESTArgs::get_int64(s
, "max-objects", old_quota
->max_objects
, "a
.max_objects
);
301 RESTArgs::get_int64(s
, "max-size", old_quota
->max_size
, "a
.max_size
);
302 RESTArgs::get_int64(s
, "max-size-kb", old_max_size_kb
, &max_size_kb
, &has_max_size_kb
);
304 quota
.max_size
= max_size_kb
* 1024;
305 RESTArgs::get_bool(s
, "enabled", old_quota
->enabled
, "a
.enabled
);
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
);
313 op_ret
= RGWBucketAdminOp::set_quota(driver
, op_state
, s
);
316 class RGWOp_Sync_Bucket
: public RGWRESTOp
{
319 RGWOp_Sync_Bucket() {}
321 int check_caps(const RGWUserCaps
& caps
) override
{
322 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
325 void execute(optional_yield y
) override
;
327 const char* name() const override
{ return "sync_bucket"; }
330 void RGWOp_Sync_Bucket::execute(optional_yield y
)
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
);
341 op_state
.set_bucket_name(bucket
);
342 op_state
.set_tenant(tenant
);
343 op_state
.set_sync_bucket(sync_bucket
);
345 op_ret
= RGWBucketAdminOp::sync_bucket(driver
, op_state
, s
);
348 class RGWOp_Object_Remove
: public RGWRESTOp
{
351 RGWOp_Object_Remove() {}
353 int check_caps(const RGWUserCaps
& caps
) override
{
354 return caps
.check_cap("buckets", RGW_CAP_WRITE
);
357 void execute(optional_yield y
) override
;
359 const char* name() const override
{ return "remove_object"; }
362 void RGWOp_Object_Remove::execute(optional_yield y
)
367 RGWBucketAdminOpState op_state
;
369 RESTArgs::get_string(s
, "bucket", bucket
, &bucket
);
370 RESTArgs::get_string(s
, "object", object
, &object
);
372 op_state
.set_bucket_name(bucket
);
373 op_state
.set_object(object
);
375 op_ret
= RGWBucketAdminOp::remove_object(driver
, op_state
, s
);
379 RGWOp
*RGWHandler_Bucket::op_get()
382 if (s
->info
.args
.sub_resource_exists("policy"))
383 return new RGWOp_Get_Policy
;
385 if (s
->info
.args
.sub_resource_exists("index"))
386 return new RGWOp_Check_Bucket_Index
;
388 return new RGWOp_Bucket_Info
;
391 RGWOp
*RGWHandler_Bucket::op_put()
393 if (s
->info
.args
.sub_resource_exists("quota"))
394 return new RGWOp_Set_Bucket_Quota
;
396 if (s
->info
.args
.sub_resource_exists("sync"))
397 return new RGWOp_Sync_Bucket
;
399 return new RGWOp_Bucket_Link
;
402 RGWOp
*RGWHandler_Bucket::op_post()
404 return new RGWOp_Bucket_Unlink
;
407 RGWOp
*RGWHandler_Bucket::op_delete()
409 if (s
->info
.args
.sub_resource_exists("object"))
410 return new RGWOp_Object_Remove
;
412 return new RGWOp_Bucket_Remove
;