]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_op.h
update sources to 12.2.7
[ceph.git] / ceph / src / rgw / rgw_op.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /**
4 * All operations via the rados gateway are carried out by
5 * small classes known as RGWOps. This class contains a req_state
6 * and each possible command is a subclass of this with a defined
7 * execute() method that does whatever the subclass name implies.
8 * These subclasses must be further subclassed (by interface type)
9 * to provide additional virtual methods such as send_response or get_params.
10 */
11 #ifndef CEPH_RGW_OP_H
12 #define CEPH_RGW_OP_H
13
14 #include <limits.h>
15
16 #include <array>
17 #include <memory>
18 #include <string>
19 #include <set>
20 #include <map>
21 #include <vector>
22
23 #include <boost/optional.hpp>
24 #include <boost/utility/in_place_factory.hpp>
25 #include <boost/function.hpp>
26
27 #include "common/armor.h"
28 #include "common/mime.h"
29 #include "common/utf8.h"
30 #include "common/ceph_json.h"
31 #include "common/utf8.h"
32 #include "common/ceph_time.h"
33
34 #include "rgw_common.h"
35 #include "rgw_rados.h"
36 #include "rgw_user.h"
37 #include "rgw_bucket.h"
38 #include "rgw_acl.h"
39 #include "rgw_cors.h"
40 #include "rgw_quota.h"
41
42 #include "rgw_lc.h"
43 #include "rgw_torrent.h"
44 #include "rgw_tag.h"
45 #include "cls/lock/cls_lock_client.h"
46 #include "cls/rgw/cls_rgw_client.h"
47
48 #include "include/assert.h"
49
50 using ceph::crypto::SHA1;
51
52 struct req_state;
53 class RGWOp;
54
55
56 namespace rgw {
57 namespace auth {
58 namespace registry {
59
60 class StrategyRegistry;
61
62 }
63 }
64 }
65
66
67 class RGWHandler {
68 protected:
69 RGWRados* store;
70 struct req_state* s;
71
72 int do_init_permissions();
73 int do_read_permissions(RGWOp* op, bool only_bucket);
74
75 public:
76 RGWHandler()
77 : store(nullptr),
78 s(nullptr) {
79 }
80 virtual ~RGWHandler();
81
82 virtual int init(RGWRados* store,
83 struct req_state* _s,
84 rgw::io::BasicClient* cio);
85
86 virtual int init_permissions(RGWOp*) {
87 return 0;
88 }
89
90 virtual int retarget(RGWOp* op, RGWOp** new_op) {
91 *new_op = op;
92 return 0;
93 }
94
95 virtual int read_permissions(RGWOp* op) = 0;
96 virtual int authorize() = 0;
97 virtual int postauth_init() = 0;
98 virtual int error_handler(int err_no, std::string* error_content);
99 virtual void dump(const string& code, const string& message) const {}
100 };
101
102
103
104 void rgw_bucket_object_pre_exec(struct req_state *s);
105
106 /**
107 * Provide the base class for all ops.
108 */
109 class RGWOp {
110 protected:
111 struct req_state *s;
112 RGWHandler *dialect_handler;
113 RGWRados *store;
114 RGWCORSConfiguration bucket_cors;
115 bool cors_exist;
116 RGWQuotaInfo bucket_quota;
117 RGWQuotaInfo user_quota;
118 int op_ret;
119
120 int do_aws4_auth_completion();
121
122 virtual int init_quota();
123
124 public:
125 RGWOp()
126 : s(nullptr),
127 dialect_handler(nullptr),
128 store(nullptr),
129 cors_exist(false),
130 op_ret(0) {
131 }
132
133 virtual ~RGWOp() = default;
134
135 int get_ret() const { return op_ret; }
136
137 virtual int init_processing() {
138 op_ret = init_quota();
139 if (op_ret < 0)
140 return op_ret;
141
142 return 0;
143 }
144
145 virtual void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) {
146 this->store = store;
147 this->s = s;
148 this->dialect_handler = dialect_handler;
149 }
150 int read_bucket_cors();
151 bool generate_cors_headers(string& origin, string& method, string& headers, string& exp_headers, unsigned *max_age);
152
153 virtual int verify_params() { return 0; }
154 virtual bool prefetch_data() { return false; }
155
156 /* Authenticate requester -- verify its identity.
157 *
158 * NOTE: typically the procedure is common across all operations of the same
159 * dialect (S3, Swift API). However, there are significant exceptions in
160 * both APIs: browser uploads, /info and OPTIONS handlers. All of them use
161 * different, specific authentication schema driving the need for per-op
162 * authentication. The alternative is to duplicate parts of the method-
163 * dispatch logic in RGWHandler::authorize() and pollute it with a lot
164 * of special cases. */
165 virtual int verify_requester(const rgw::auth::StrategyRegistry& auth_registry) {
166 /* TODO(rzarzynski): rename RGWHandler::authorize to generic_authenticate. */
167 return dialect_handler->authorize();
168 }
169 virtual int verify_permission() = 0;
170 virtual int verify_op_mask();
171 virtual void pre_exec() {}
172 virtual void execute() = 0;
173 virtual void send_response() {}
174 virtual void complete() {
175 send_response();
176 }
177 virtual const string name() = 0;
178 virtual RGWOpType get_type() { return RGW_OP_UNKNOWN; }
179
180 virtual uint32_t op_mask() { return 0; }
181
182 virtual int error_handler(int err_no, string *error_content);
183 };
184
185 class RGWGetObj : public RGWOp {
186 protected:
187 seed torrent; // get torrent
188 const char *range_str;
189 const char *if_mod;
190 const char *if_unmod;
191 const char *if_match;
192 const char *if_nomatch;
193 uint32_t mod_zone_id;
194 uint64_t mod_pg_ver;
195 off_t ofs;
196 uint64_t total_len;
197 off_t start;
198 off_t end;
199 ceph::real_time mod_time;
200 ceph::real_time lastmod;
201 ceph::real_time unmod_time;
202 ceph::real_time *mod_ptr;
203 ceph::real_time *unmod_ptr;
204 map<string, bufferlist> attrs;
205 bool get_data;
206 bool partial_content;
207 bool ignore_invalid_range;
208 bool range_parsed;
209 bool skip_manifest;
210 bool skip_decrypt{false};
211 rgw_obj obj;
212 utime_t gc_invalidate_time;
213 bool is_slo;
214 string lo_etag;
215 bool rgwx_stat; /* extended rgw stat operation */
216 string version_id;
217
218 // compression attrs
219 RGWCompressionInfo cs_info;
220 off_t first_block, last_block;
221 off_t q_ofs, q_len;
222 bool first_data;
223 uint64_t cur_ofs;
224 bufferlist waiting;
225 uint64_t action = 0;
226
227 int init_common();
228 public:
229 RGWGetObj() {
230 range_str = NULL;
231 if_mod = NULL;
232 if_unmod = NULL;
233 if_match = NULL;
234 if_nomatch = NULL;
235 mod_zone_id = 0;
236 mod_pg_ver = 0;
237 start = 0;
238 ofs = 0;
239 total_len = 0;
240 end = -1;
241 mod_ptr = NULL;
242 unmod_ptr = NULL;
243 get_data = false;
244 partial_content = false;
245 range_parsed = false;
246 skip_manifest = false;
247 is_slo = false;
248 first_block = 0;
249 last_block = 0;
250 q_ofs = 0;
251 q_len = 0;
252 first_data = true;
253 cur_ofs = 0;
254 }
255
256 bool prefetch_data() override;
257
258 void set_get_data(bool get_data) {
259 this->get_data = get_data;
260 }
261
262 int verify_permission() override;
263 void pre_exec() override;
264 void execute() override;
265 int parse_range();
266 int read_user_manifest_part(
267 rgw_bucket& bucket,
268 const rgw_bucket_dir_entry& ent,
269 RGWAccessControlPolicy * const bucket_acl,
270 const boost::optional<rgw::IAM::Policy>& bucket_policy,
271 const off_t start_ofs,
272 const off_t end_ofs);
273 int handle_user_manifest(const char *prefix);
274 int handle_slo_manifest(bufferlist& bl);
275
276 int get_data_cb(bufferlist& bl, off_t ofs, off_t len);
277
278 virtual int get_params() = 0;
279 virtual int send_response_data_error() = 0;
280 virtual int send_response_data(bufferlist& bl, off_t ofs, off_t len) = 0;
281
282 const string name() override { return "get_obj"; }
283 RGWOpType get_type() override { return RGW_OP_GET_OBJ; }
284 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
285 virtual bool need_object_expiration() { return false; }
286 /**
287 * calculates filter used to decrypt RGW objects data
288 */
289 virtual int get_decrypt_filter(std::unique_ptr<RGWGetDataCB>* filter, RGWGetDataCB* cb, bufferlist* manifest_bl) {
290 *filter = nullptr;
291 return 0;
292 }
293 };
294
295 class RGWGetObj_CB : public RGWGetDataCB
296 {
297 RGWGetObj *op;
298 public:
299 explicit RGWGetObj_CB(RGWGetObj *_op) : op(_op) {}
300 ~RGWGetObj_CB() override {}
301
302 int handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) override {
303 return op->get_data_cb(bl, bl_ofs, bl_len);
304 }
305 };
306
307 class RGWGetObj_Filter : public RGWGetDataCB
308 {
309 protected:
310 RGWGetDataCB* next;
311 public:
312 RGWGetObj_Filter(RGWGetDataCB* next): next(next) {}
313 ~RGWGetObj_Filter() override {}
314 /**
315 * Passes data through filter.
316 * Filter can modify content of bl.
317 * When bl_len == 0 , it means 'flush
318 */
319 int handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) override {
320 return next->handle_data(bl, bl_ofs, bl_len);
321 }
322 /**
323 * Flushes any cached data. Used by RGWGetObjFilter.
324 * Return logic same as handle_data.
325 */
326 int flush() override {
327 return next->flush();
328 }
329 /**
330 * Allows filter to extend range required for successful filtering
331 */
332 int fixup_range(off_t& ofs, off_t& end) override {
333 return next->fixup_range(ofs, end);
334 }
335 };
336
337 class RGWGetObjTags : public RGWOp {
338 protected:
339 bufferlist tags_bl;
340 bool has_tags{false};
341 public:
342 int verify_permission();
343 void execute();
344 void pre_exec();
345
346 virtual void send_response_data(bufferlist& bl) = 0;
347 virtual const string name() noexcept override { return "get_obj_tags"; }
348 virtual uint32_t op_mask() { return RGW_OP_TYPE_READ; }
349 RGWOpType get_type() { return RGW_OP_GET_OBJ_TAGGING; }
350
351 };
352
353 class RGWPutObjTags : public RGWOp {
354 protected:
355 bufferlist tags_bl;
356 public:
357 int verify_permission();
358 void execute();
359
360 virtual void send_response() = 0;
361 virtual int get_params() = 0;
362 virtual const string name() { return "put_obj_tags"; }
363 virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
364 RGWOpType get_type() { return RGW_OP_PUT_OBJ_TAGGING; }
365
366 };
367
368 class RGWDeleteObjTags: public RGWOp {
369 public:
370 void pre_exec();
371 int verify_permission();
372 void execute();
373
374 virtual void send_response() = 0;
375 virtual const string name() { return "delete_obj_tags"; }
376 virtual uint32_t op_mask() { return RGW_OP_TYPE_DELETE; }
377 RGWOpType get_type() { return RGW_OP_DELETE_OBJ_TAGGING;}
378 };
379
380 class RGWBulkDelete : public RGWOp {
381 public:
382 struct acct_path_t {
383 std::string bucket_name;
384 rgw_obj_key obj_key;
385 };
386
387 struct fail_desc_t {
388 int err;
389 acct_path_t path;
390 };
391
392 class Deleter {
393 protected:
394 unsigned int num_deleted;
395 unsigned int num_unfound;
396 std::list<fail_desc_t> failures;
397
398 RGWRados * const store;
399 req_state * const s;
400
401 public:
402 Deleter(RGWRados * const str, req_state * const s)
403 : num_deleted(0),
404 num_unfound(0),
405 store(str),
406 s(s) {
407 }
408
409 unsigned int get_num_deleted() const {
410 return num_deleted;
411 }
412
413 unsigned int get_num_unfound() const {
414 return num_unfound;
415 }
416
417 const std::list<fail_desc_t> get_failures() const {
418 return failures;
419 }
420
421 bool verify_permission(RGWBucketInfo& binfo,
422 map<string, bufferlist>& battrs,
423 ACLOwner& bucket_owner /* out */);
424 bool delete_single(const acct_path_t& path);
425 bool delete_chunk(const std::list<acct_path_t>& paths);
426 };
427 /* End of Deleter subclass */
428
429 static const size_t MAX_CHUNK_ENTRIES = 1024;
430
431 protected:
432 std::unique_ptr<Deleter> deleter;
433
434 public:
435 RGWBulkDelete()
436 : deleter(nullptr) {
437 }
438
439 int verify_permission() override;
440 void pre_exec() override;
441 void execute() override;
442
443 virtual int get_data(std::list<acct_path_t>& items,
444 bool * is_truncated) = 0;
445 void send_response() override = 0;
446
447 const string name() override { return "bulk_delete"; }
448 RGWOpType get_type() override { return RGW_OP_BULK_DELETE; }
449 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
450 };
451
452 inline ostream& operator<<(ostream& out, const RGWBulkDelete::acct_path_t &o) {
453 return out << o.bucket_name << "/" << o.obj_key;
454 }
455
456
457 class RGWBulkUploadOp : public RGWOp {
458 boost::optional<RGWObjectCtx> dir_ctx;
459
460 protected:
461 class fail_desc_t {
462 public:
463 fail_desc_t(const int err, std::string path)
464 : err(err),
465 path(std::move(path)) {
466 }
467
468 const int err;
469 const std::string path;
470 };
471
472 static constexpr std::array<int, 2> terminal_errors = {
473 { -EACCES, -EPERM }
474 };
475
476 /* FIXME: boost::container::small_vector<fail_desc_t, 4> failures; */
477 std::vector<fail_desc_t> failures;
478 size_t num_created;
479
480 class StreamGetter;
481 class DecoratedStreamGetter;
482 class AlignedStreamGetter;
483
484 virtual std::unique_ptr<StreamGetter> create_stream() = 0;
485 virtual void send_response() = 0;
486
487 boost::optional<std::pair<std::string, rgw_obj_key>>
488 parse_path(const boost::string_ref& path);
489
490 std::pair<std::string, std::string>
491 handle_upload_path(struct req_state *s);
492
493 bool handle_file_verify_permission(RGWBucketInfo& binfo,
494 const rgw_obj& obj,
495 std::map<std::string, ceph::bufferlist>& battrs,
496 ACLOwner& bucket_owner /* out */);
497 int handle_file(boost::string_ref path,
498 size_t size,
499 AlignedStreamGetter& body);
500
501 int handle_dir_verify_permission();
502 int handle_dir(boost::string_ref path);
503
504 public:
505 RGWBulkUploadOp()
506 : num_created(0) {
507 }
508
509 void init(RGWRados* const store,
510 struct req_state* const s,
511 RGWHandler* const h) override {
512 RGWOp::init(store, s, h);
513 dir_ctx.emplace(store);
514 }
515
516 int verify_permission() override;
517 void pre_exec() override;
518 void execute() override;
519
520 const std::string name() override {
521 return "bulk_upload";
522 }
523
524 RGWOpType get_type() override {
525 return RGW_OP_BULK_UPLOAD;
526 }
527
528 uint32_t op_mask() override {
529 return RGW_OP_TYPE_WRITE;
530 }
531 }; /* RGWBulkUploadOp */
532
533
534 class RGWBulkUploadOp::StreamGetter {
535 public:
536 StreamGetter() = default;
537 virtual ~StreamGetter() = default;
538
539 virtual ssize_t get_at_most(size_t want, ceph::bufferlist& dst) = 0;
540 virtual ssize_t get_exactly(size_t want, ceph::bufferlist& dst) = 0;
541 }; /* End of nested subclass StreamGetter */
542
543
544 class RGWBulkUploadOp::DecoratedStreamGetter : public StreamGetter {
545 StreamGetter& decoratee;
546
547 protected:
548 StreamGetter& get_decoratee() {
549 return decoratee;
550 }
551
552 public:
553 DecoratedStreamGetter(StreamGetter& decoratee)
554 : decoratee(decoratee) {
555 }
556 virtual ~DecoratedStreamGetter() = default;
557
558 ssize_t get_at_most(const size_t want, ceph::bufferlist& dst) override {
559 return get_decoratee().get_at_most(want, dst);
560 }
561
562 ssize_t get_exactly(const size_t want, ceph::bufferlist& dst) override {
563 return get_decoratee().get_exactly(want, dst);
564 }
565 }; /* RGWBulkUploadOp::DecoratedStreamGetter */
566
567
568 class RGWBulkUploadOp::AlignedStreamGetter
569 : public RGWBulkUploadOp::DecoratedStreamGetter {
570 size_t position;
571 size_t length;
572 size_t alignment;
573
574 public:
575 template <typename U>
576 AlignedStreamGetter(const size_t position,
577 const size_t length,
578 const size_t alignment,
579 U&& decoratee)
580 : DecoratedStreamGetter(std::forward<U>(decoratee)),
581 position(position),
582 length(length),
583 alignment(alignment) {
584 }
585 virtual ~AlignedStreamGetter();
586 ssize_t get_at_most(size_t want, ceph::bufferlist& dst) override;
587 ssize_t get_exactly(size_t want, ceph::bufferlist& dst) override;
588 }; /* RGWBulkUploadOp::AlignedStreamGetter */
589
590
591 struct RGWUsageStats {
592 uint64_t bytes_used = 0;
593 uint64_t bytes_used_rounded = 0;
594 uint64_t buckets_count = 0;
595 uint64_t objects_count = 0;
596 };
597
598 #define RGW_LIST_BUCKETS_LIMIT_MAX 10000
599
600 class RGWListBuckets : public RGWOp {
601 protected:
602 bool sent_data;
603 std::string marker;
604 std::string end_marker;
605 int64_t limit;
606 uint64_t limit_max;
607 std::map<std::string, ceph::bufferlist> attrs;
608 bool is_truncated;
609
610 RGWUsageStats global_stats;
611 std::map<std::string, RGWUsageStats> policies_stats;
612
613 virtual uint64_t get_default_max() const {
614 return 1000;
615 }
616
617 public:
618 RGWListBuckets()
619 : sent_data(false),
620 limit(RGW_LIST_BUCKETS_LIMIT_MAX),
621 limit_max(RGW_LIST_BUCKETS_LIMIT_MAX),
622 is_truncated(false) {
623 }
624
625 int verify_permission() override;
626 void execute() override;
627
628 virtual int get_params() = 0;
629 virtual void handle_listing_chunk(RGWUserBuckets&& buckets) {
630 /* The default implementation, used by e.g. S3, just generates a new
631 * part of listing and sends it client immediately. Swift can behave
632 * differently: when the reverse option is requested, all incoming
633 * instances of RGWUserBuckets are buffered and finally reversed. */
634 return send_response_data(buckets);
635 }
636 virtual void send_response_begin(bool has_buckets) = 0;
637 virtual void send_response_data(RGWUserBuckets& buckets) = 0;
638 virtual void send_response_end() = 0;
639 void send_response() override {}
640
641 virtual bool should_get_stats() { return false; }
642 virtual bool supports_account_metadata() { return false; }
643
644 const string name() override { return "list_buckets"; }
645 RGWOpType get_type() override { return RGW_OP_LIST_BUCKETS; }
646 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
647 };
648
649 class RGWGetUsage : public RGWOp {
650 protected:
651 bool sent_data;
652 string start_date;
653 string end_date;
654 int show_log_entries;
655 int show_log_sum;
656 map<string, bool> categories;
657 map<rgw_user_bucket, rgw_usage_log_entry> usage;
658 map<string, rgw_usage_log_entry> summary_map;
659 map<string, cls_user_bucket_entry> buckets_usage;
660 cls_user_header header;
661 public:
662 RGWGetUsage() : sent_data(false), show_log_entries(true), show_log_sum(true){
663 }
664
665 int verify_permission() override;
666 void execute() override;
667
668 virtual int get_params() = 0;
669 void send_response() override {}
670
671 virtual bool should_get_stats() { return false; }
672
673 const string name() override { return "get_usage"; }
674 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
675 };
676
677 class RGWStatAccount : public RGWOp {
678 protected:
679 RGWUsageStats global_stats;
680 std::map<std::string, RGWUsageStats> policies_stats;
681
682 public:
683 RGWStatAccount() = default;
684
685 int verify_permission() override;
686 void execute() override;
687
688 void send_response() override = 0;
689 const std::string name() override { return "stat_account"; }
690 RGWOpType get_type() override { return RGW_OP_STAT_ACCOUNT; }
691 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
692 };
693
694 class RGWListBucket : public RGWOp {
695 protected:
696 RGWBucketEnt bucket;
697 string prefix;
698 rgw_obj_key marker;
699 rgw_obj_key next_marker;
700 rgw_obj_key end_marker;
701 string max_keys;
702 string delimiter;
703 string encoding_type;
704 bool list_versions;
705 int max;
706 vector<rgw_bucket_dir_entry> objs;
707 map<string, bool> common_prefixes;
708
709 int default_max;
710 bool is_truncated;
711
712 int shard_id;
713
714 int parse_max_keys();
715
716 public:
717 RGWListBucket() : list_versions(false), max(0),
718 default_max(0), is_truncated(false), shard_id(-1) {}
719 int verify_permission() override;
720 void pre_exec() override;
721 void execute() override;
722
723 virtual int get_params() = 0;
724 void send_response() override = 0;
725 const string name() override { return "list_bucket"; }
726 RGWOpType get_type() override { return RGW_OP_LIST_BUCKET; }
727 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
728 virtual bool need_container_stats() { return false; }
729 };
730
731 class RGWGetBucketLogging : public RGWOp {
732 public:
733 RGWGetBucketLogging() {}
734 int verify_permission() override;
735 void execute() override { }
736
737 void send_response() override = 0;
738 const string name() override { return "get_bucket_logging"; }
739 RGWOpType get_type() override { return RGW_OP_GET_BUCKET_LOGGING; }
740 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
741 };
742
743 class RGWGetBucketLocation : public RGWOp {
744 public:
745 RGWGetBucketLocation() {}
746 ~RGWGetBucketLocation() override {}
747 int verify_permission() override;
748 void execute() override { }
749
750 void send_response() override = 0;
751 const string name() override { return "get_bucket_location"; }
752 RGWOpType get_type() override { return RGW_OP_GET_BUCKET_LOCATION; }
753 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
754 };
755
756 class RGWGetBucketVersioning : public RGWOp {
757 protected:
758 bool versioned;
759 bool versioning_enabled;
760 public:
761 RGWGetBucketVersioning() : versioned(false), versioning_enabled(false) {}
762
763 int verify_permission() override;
764 void pre_exec() override;
765 void execute() override;
766
767 void send_response() override = 0;
768 const string name() override { return "get_bucket_versioning"; }
769 RGWOpType get_type() override { return RGW_OP_GET_BUCKET_VERSIONING; }
770 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
771 };
772
773 class RGWSetBucketVersioning : public RGWOp {
774 protected:
775 bool enable_versioning;
776 bufferlist in_data;
777 public:
778 RGWSetBucketVersioning() : enable_versioning(false) {}
779
780 int verify_permission() override;
781 void pre_exec() override;
782 void execute() override;
783
784 virtual int get_params() { return 0; }
785
786 void send_response() override = 0;
787 const string name() override { return "set_bucket_versioning"; }
788 RGWOpType get_type() override { return RGW_OP_SET_BUCKET_VERSIONING; }
789 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
790 };
791
792 class RGWGetBucketWebsite : public RGWOp {
793 public:
794 RGWGetBucketWebsite() {}
795
796 int verify_permission() override;
797 void pre_exec() override;
798 void execute() override;
799
800 void send_response() override = 0;
801 const string name() override { return "get_bucket_website"; }
802 RGWOpType get_type() override { return RGW_OP_GET_BUCKET_WEBSITE; }
803 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
804 };
805
806 class RGWSetBucketWebsite : public RGWOp {
807 protected:
808 bufferlist in_data;
809 RGWBucketWebsiteConf website_conf;
810 public:
811 RGWSetBucketWebsite() {}
812
813 int verify_permission() override;
814 void pre_exec() override;
815 void execute() override;
816
817 virtual int get_params() { return 0; }
818
819 void send_response() override = 0;
820 const string name() override { return "set_bucket_website"; }
821 RGWOpType get_type() override { return RGW_OP_SET_BUCKET_WEBSITE; }
822 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
823 };
824
825 class RGWDeleteBucketWebsite : public RGWOp {
826 public:
827 RGWDeleteBucketWebsite() {}
828
829 int verify_permission() override;
830 void pre_exec() override;
831 void execute() override;
832
833 void send_response() override = 0;
834 const string name() override { return "delete_bucket_website"; }
835 RGWOpType get_type() override { return RGW_OP_SET_BUCKET_WEBSITE; }
836 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
837 };
838
839 class RGWStatBucket : public RGWOp {
840 protected:
841 RGWBucketEnt bucket;
842
843 public:
844 RGWStatBucket() {}
845 ~RGWStatBucket() override {}
846
847 int verify_permission() override;
848 void pre_exec() override;
849 void execute() override;
850
851 void send_response() override = 0;
852 const string name() override { return "stat_bucket"; }
853 RGWOpType get_type() override { return RGW_OP_STAT_BUCKET; }
854 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
855 };
856
857 class RGWCreateBucket : public RGWOp {
858 protected:
859 RGWAccessControlPolicy policy;
860 string location_constraint;
861 string placement_rule;
862 RGWBucketInfo info;
863 obj_version ep_objv;
864 bool has_cors;
865 RGWCORSConfiguration cors_config;
866 boost::optional<std::string> swift_ver_location;
867 map<string, buffer::list> attrs;
868 set<string> rmattr_names;
869
870 bufferlist in_data;
871
872 virtual bool need_metadata_upload() const { return false; }
873
874 public:
875 RGWCreateBucket() : has_cors(false) {}
876
877 void emplace_attr(std::string&& key, buffer::list&& bl) {
878 attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
879 }
880
881 int verify_permission() override;
882 void pre_exec() override;
883 void execute() override;
884 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
885 RGWOp::init(store, s, h);
886 policy.set_ctx(s->cct);
887 }
888 virtual int get_params() { return 0; }
889 void send_response() override = 0;
890 const string name() override { return "create_bucket"; }
891 RGWOpType get_type() override { return RGW_OP_CREATE_BUCKET; }
892 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
893 };
894
895 class RGWDeleteBucket : public RGWOp {
896 protected:
897 RGWObjVersionTracker objv_tracker;
898
899 public:
900 RGWDeleteBucket() {}
901
902 int verify_permission() override;
903 void pre_exec() override;
904 void execute() override;
905
906 void send_response() override = 0;
907 const string name() override { return "delete_bucket"; }
908 RGWOpType get_type() override { return RGW_OP_DELETE_BUCKET; }
909 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
910 };
911
912 struct rgw_slo_entry {
913 string path;
914 string etag;
915 uint64_t size_bytes;
916
917 rgw_slo_entry() : size_bytes(0) {}
918
919 void encode(bufferlist& bl) const {
920 ENCODE_START(1, 1, bl);
921 ::encode(path, bl);
922 ::encode(etag, bl);
923 ::encode(size_bytes, bl);
924 ENCODE_FINISH(bl);
925 }
926
927 void decode(bufferlist::iterator& bl) {
928 DECODE_START(1, bl);
929 ::decode(path, bl);
930 ::decode(etag, bl);
931 ::decode(size_bytes, bl);
932 DECODE_FINISH(bl);
933 }
934
935 void decode_json(JSONObj *obj);
936 };
937 WRITE_CLASS_ENCODER(rgw_slo_entry)
938
939 struct RGWSLOInfo {
940 vector<rgw_slo_entry> entries;
941 uint64_t total_size;
942
943 /* in memory only */
944 char *raw_data;
945 int raw_data_len;
946
947 RGWSLOInfo() : total_size(0), raw_data(NULL), raw_data_len(0) {}
948 ~RGWSLOInfo() {
949 free(raw_data);
950 }
951
952 void encode(bufferlist& bl) const {
953 ENCODE_START(1, 1, bl);
954 ::encode(entries, bl);
955 ::encode(total_size, bl);
956 ENCODE_FINISH(bl);
957 }
958
959 void decode(bufferlist::iterator& bl) {
960 DECODE_START(1, bl);
961 ::decode(entries, bl);
962 ::decode(total_size, bl);
963 DECODE_FINISH(bl);
964 }
965 };
966 WRITE_CLASS_ENCODER(RGWSLOInfo)
967
968 class RGWPutObj : public RGWOp {
969
970 friend class RGWPutObjProcessor;
971
972 protected:
973 seed torrent;
974 off_t ofs;
975 const char *supplied_md5_b64;
976 const char *supplied_etag;
977 const char *if_match;
978 const char *if_nomatch;
979 std::string copy_source;
980 const char *copy_source_range;
981 RGWBucketInfo copy_source_bucket_info;
982 string copy_source_tenant_name;
983 string copy_source_bucket_name;
984 string copy_source_object_name;
985 string copy_source_version_id;
986 off_t copy_source_range_fst;
987 off_t copy_source_range_lst;
988 string etag;
989 bool chunked_upload;
990 RGWAccessControlPolicy policy;
991 std::unique_ptr <RGWObjTags> obj_tags;
992 const char *dlo_manifest;
993 RGWSLOInfo *slo_info;
994 map<string, bufferlist> attrs;
995 ceph::real_time mtime;
996 uint64_t olh_epoch;
997 string version_id;
998 bufferlist bl_aux;
999 map<string, string> crypt_http_responses;
1000 string user_data;
1001
1002 boost::optional<ceph::real_time> delete_at;
1003
1004 public:
1005 RGWPutObj() : ofs(0),
1006 supplied_md5_b64(NULL),
1007 supplied_etag(NULL),
1008 if_match(NULL),
1009 if_nomatch(NULL),
1010 copy_source_range(NULL),
1011 copy_source_range_fst(0),
1012 copy_source_range_lst(0),
1013 chunked_upload(0),
1014 dlo_manifest(NULL),
1015 slo_info(NULL),
1016 olh_epoch(0) {}
1017
1018 ~RGWPutObj() override {
1019 delete slo_info;
1020 }
1021
1022 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1023 RGWOp::init(store, s, h);
1024 policy.set_ctx(s->cct);
1025 }
1026
1027 void emplace_attr(std::string&& key, buffer::list&& bl) {
1028 attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
1029 }
1030
1031 virtual RGWPutObjProcessor *select_processor(RGWObjectCtx& obj_ctx, bool *is_multipart);
1032 void dispose_processor(RGWPutObjDataProcessor *processor);
1033
1034 int verify_permission() override;
1035 void pre_exec() override;
1036 void execute() override;
1037
1038 /* this is for cases when copying data from other object */
1039 virtual int get_decrypt_filter(std::unique_ptr<RGWGetDataCB>* filter,
1040 RGWGetDataCB* cb,
1041 map<string, bufferlist>& attrs,
1042 bufferlist* manifest_bl) {
1043 *filter = nullptr;
1044 return 0;
1045 }
1046 virtual int get_encrypt_filter(std::unique_ptr<RGWPutObjDataProcessor> *filter, RGWPutObjDataProcessor* cb) {
1047 *filter = nullptr;
1048 return 0;
1049 }
1050
1051 int get_data_cb(bufferlist& bl, off_t bl_ofs, off_t bl_len);
1052 int get_data(const off_t fst, const off_t lst, bufferlist& bl);
1053
1054 virtual int get_params() = 0;
1055 virtual int get_data(bufferlist& bl) = 0;
1056 void send_response() override = 0;
1057 const string name() override { return "put_obj"; }
1058 RGWOpType get_type() override { return RGW_OP_PUT_OBJ; }
1059 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1060 };
1061
1062 class RGWPutObj_Filter : public RGWPutObjDataProcessor
1063 {
1064 protected:
1065 RGWPutObjDataProcessor* next;
1066 public:
1067 RGWPutObj_Filter(RGWPutObjDataProcessor* next) :
1068 next(next){}
1069 ~RGWPutObj_Filter() override {}
1070 int handle_data(bufferlist& bl, off_t ofs, void **phandle, rgw_raw_obj *pobj, bool *again) override {
1071 return next->handle_data(bl, ofs, phandle, pobj, again);
1072 }
1073 int throttle_data(void *handle, const rgw_raw_obj& obj, uint64_t size, bool need_to_wait) override {
1074 return next->throttle_data(handle, obj, size, need_to_wait);
1075 }
1076 }; /* RGWPutObj_Filter */
1077
1078 class RGWPostObj : public RGWOp {
1079 protected:
1080 off_t min_len;
1081 off_t max_len;
1082 int len;
1083 off_t ofs;
1084 const char *supplied_md5_b64;
1085 const char *supplied_etag;
1086 string etag;
1087 RGWAccessControlPolicy policy;
1088 map<string, bufferlist> attrs;
1089 boost::optional<ceph::real_time> delete_at;
1090
1091 /* Must be called after get_data() or the result is undefined. */
1092 virtual std::string get_current_filename() const = 0;
1093 virtual std::string get_current_content_type() const = 0;
1094 virtual bool is_next_file_to_upload() {
1095 return false;
1096 }
1097 public:
1098 RGWPostObj() : min_len(0),
1099 max_len(LLONG_MAX),
1100 len(0),
1101 ofs(0),
1102 supplied_md5_b64(nullptr),
1103 supplied_etag(nullptr) {
1104 }
1105
1106 void emplace_attr(std::string&& key, buffer::list&& bl) {
1107 attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
1108 }
1109
1110 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1111 RGWOp::init(store, s, h);
1112 policy.set_ctx(s->cct);
1113 }
1114
1115 int verify_permission() override;
1116 void pre_exec() override;
1117 void execute() override;
1118
1119 virtual int get_encrypt_filter(std::unique_ptr<RGWPutObjDataProcessor> *filter, RGWPutObjDataProcessor* cb) {
1120 *filter = nullptr;
1121 return 0;
1122 }
1123 virtual int get_params() = 0;
1124 virtual int get_data(ceph::bufferlist& bl, bool& again) = 0;
1125 void send_response() override = 0;
1126 const std::string name() override { return "post_obj"; }
1127 RGWOpType get_type() override { return RGW_OP_POST_OBJ; }
1128 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1129 };
1130
1131 class RGWPutMetadataAccount : public RGWOp {
1132 protected:
1133 std::set<std::string> rmattr_names;
1134 std::map<std::string, bufferlist> attrs, orig_attrs;
1135 std::map<int, std::string> temp_url_keys;
1136 RGWQuotaInfo new_quota;
1137 bool new_quota_extracted;
1138
1139 RGWObjVersionTracker acct_op_tracker;
1140
1141 RGWAccessControlPolicy policy;
1142 bool has_policy;
1143
1144 public:
1145 RGWPutMetadataAccount()
1146 : new_quota_extracted(false),
1147 has_policy(false) {
1148 }
1149
1150 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1151 RGWOp::init(store, s, h);
1152 policy.set_ctx(s->cct);
1153 }
1154 int init_processing() override;
1155 int verify_permission() override;
1156 void pre_exec() override { }
1157 void execute() override;
1158
1159 virtual int get_params() = 0;
1160 void send_response() override = 0;
1161 virtual void filter_out_temp_url(map<string, bufferlist>& add_attrs,
1162 const set<string>& rmattr_names,
1163 map<int, string>& temp_url_keys);
1164 const string name() override { return "put_account_metadata"; }
1165 RGWOpType get_type() override { return RGW_OP_PUT_METADATA_ACCOUNT; }
1166 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1167 };
1168
1169 class RGWPutMetadataBucket : public RGWOp {
1170 protected:
1171 map<string, buffer::list> attrs;
1172 set<string> rmattr_names;
1173 bool has_policy, has_cors;
1174 uint32_t policy_rw_mask;
1175 RGWAccessControlPolicy policy;
1176 RGWCORSConfiguration cors_config;
1177 string placement_rule;
1178 boost::optional<std::string> swift_ver_location;
1179
1180 public:
1181 RGWPutMetadataBucket()
1182 : has_policy(false), has_cors(false), policy_rw_mask(0)
1183 {}
1184
1185 void emplace_attr(std::string&& key, buffer::list&& bl) {
1186 attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
1187 }
1188
1189 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1190 RGWOp::init(store, s, h);
1191 policy.set_ctx(s->cct);
1192 }
1193
1194 int verify_permission() override;
1195 void pre_exec() override;
1196 void execute() override;
1197
1198 virtual int get_params() = 0;
1199 void send_response() override = 0;
1200 const string name() override { return "put_bucket_metadata"; }
1201 RGWOpType get_type() override { return RGW_OP_PUT_METADATA_BUCKET; }
1202 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1203 };
1204
1205 class RGWPutMetadataObject : public RGWOp {
1206 protected:
1207 RGWAccessControlPolicy policy;
1208 string placement_rule;
1209 boost::optional<ceph::real_time> delete_at;
1210 const char *dlo_manifest;
1211
1212 public:
1213 RGWPutMetadataObject()
1214 : dlo_manifest(NULL)
1215 {}
1216
1217 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1218 RGWOp::init(store, s, h);
1219 policy.set_ctx(s->cct);
1220 }
1221 int verify_permission() override;
1222 void pre_exec() override;
1223 void execute() override;
1224
1225 virtual int get_params() = 0;
1226 void send_response() override = 0;
1227 const string name() override { return "put_obj_metadata"; }
1228 RGWOpType get_type() override { return RGW_OP_PUT_METADATA_OBJECT; }
1229 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1230 virtual bool need_object_expiration() { return false; }
1231 };
1232
1233 class RGWDeleteObj : public RGWOp {
1234 protected:
1235 bool delete_marker;
1236 bool multipart_delete;
1237 string version_id;
1238 ceph::real_time unmod_since; /* if unmodified since */
1239 bool no_precondition_error;
1240 std::unique_ptr<RGWBulkDelete::Deleter> deleter;
1241
1242 public:
1243 RGWDeleteObj()
1244 : delete_marker(false),
1245 multipart_delete(false),
1246 no_precondition_error(false),
1247 deleter(nullptr) {
1248 }
1249
1250 int verify_permission() override;
1251 void pre_exec() override;
1252 void execute() override;
1253 int handle_slo_manifest(bufferlist& bl);
1254
1255 virtual int get_params() { return 0; }
1256 void send_response() override = 0;
1257 const string name() override { return "delete_obj"; }
1258 RGWOpType get_type() override { return RGW_OP_DELETE_OBJ; }
1259 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
1260 virtual bool need_object_expiration() { return false; }
1261 };
1262
1263 class RGWCopyObj : public RGWOp {
1264 protected:
1265 RGWAccessControlPolicy dest_policy;
1266 const char *if_mod;
1267 const char *if_unmod;
1268 const char *if_match;
1269 const char *if_nomatch;
1270 off_t ofs;
1271 off_t len;
1272 off_t end;
1273 ceph::real_time mod_time;
1274 ceph::real_time unmod_time;
1275 ceph::real_time *mod_ptr;
1276 ceph::real_time *unmod_ptr;
1277 map<string, buffer::list> attrs;
1278 string src_tenant_name, src_bucket_name;
1279 rgw_bucket src_bucket;
1280 rgw_obj_key src_object;
1281 string dest_tenant_name, dest_bucket_name;
1282 rgw_bucket dest_bucket;
1283 string dest_object;
1284 ceph::real_time src_mtime;
1285 ceph::real_time mtime;
1286 RGWRados::AttrsMod attrs_mod;
1287 RGWBucketInfo src_bucket_info;
1288 RGWBucketInfo dest_bucket_info;
1289 string source_zone;
1290 string client_id;
1291 string op_id;
1292 ceph::buffer::list etag;
1293
1294 off_t last_ofs;
1295
1296 string version_id;
1297 uint64_t olh_epoch;
1298
1299 boost::optional<ceph::real_time> delete_at;
1300 bool copy_if_newer;
1301
1302 int init_common();
1303
1304 public:
1305 RGWCopyObj() {
1306 if_mod = NULL;
1307 if_unmod = NULL;
1308 if_match = NULL;
1309 if_nomatch = NULL;
1310 ofs = 0;
1311 len = 0;
1312 end = -1;
1313 mod_ptr = NULL;
1314 unmod_ptr = NULL;
1315 attrs_mod = RGWRados::ATTRSMOD_NONE;
1316 last_ofs = 0;
1317 olh_epoch = 0;
1318 copy_if_newer = false;
1319 }
1320
1321 static bool parse_copy_location(const boost::string_view& src,
1322 string& bucket_name,
1323 rgw_obj_key& object);
1324
1325 void emplace_attr(std::string&& key, buffer::list&& bl) {
1326 attrs.emplace(std::move(key), std::move(bl));
1327 }
1328
1329 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1330 RGWOp::init(store, s, h);
1331 dest_policy.set_ctx(s->cct);
1332 }
1333 int verify_permission() override;
1334 void pre_exec() override;
1335 void execute() override;
1336 void progress_cb(off_t ofs);
1337
1338 virtual int init_dest_policy() { return 0; }
1339 virtual int get_params() = 0;
1340 virtual void send_partial_response(off_t ofs) {}
1341 void send_response() override = 0;
1342 const string name() override { return "copy_obj"; }
1343 RGWOpType get_type() override { return RGW_OP_COPY_OBJ; }
1344 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1345 };
1346
1347 class RGWGetACLs : public RGWOp {
1348 protected:
1349 string acls;
1350
1351 public:
1352 RGWGetACLs() {}
1353
1354 int verify_permission() override;
1355 void pre_exec() override;
1356 void execute() override;
1357
1358 void send_response() override = 0;
1359 const string name() override { return "get_acls"; }
1360 RGWOpType get_type() override { return RGW_OP_GET_ACLS; }
1361 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1362 };
1363
1364 class RGWPutACLs : public RGWOp {
1365 protected:
1366 int len;
1367 char *data;
1368 ACLOwner owner;
1369
1370 public:
1371 RGWPutACLs() {
1372 len = 0;
1373 data = NULL;
1374 }
1375 ~RGWPutACLs() override {
1376 free(data);
1377 }
1378
1379 int verify_permission() override;
1380 void pre_exec() override;
1381 void execute() override;
1382
1383 virtual int get_policy_from_state(RGWRados *store, struct req_state *s, stringstream& ss) { return 0; }
1384 virtual int get_params() = 0;
1385 void send_response() override = 0;
1386 const string name() override { return "put_acls"; }
1387 RGWOpType get_type() override { return RGW_OP_PUT_ACLS; }
1388 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1389 };
1390
1391 class RGWGetLC : public RGWOp {
1392 protected:
1393
1394 public:
1395 RGWGetLC() { }
1396 ~RGWGetLC() override { }
1397
1398 int verify_permission() override;
1399 void pre_exec() override;
1400 void execute() override = 0;
1401
1402 void send_response() override = 0;
1403 const string name() override { return "get_lifecycle"; }
1404 RGWOpType get_type() override { return RGW_OP_GET_LC; }
1405 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1406 };
1407
1408 class RGWPutLC : public RGWOp {
1409 protected:
1410 int len;
1411 char *data;
1412 const char *content_md5;
1413 string cookie;
1414
1415 public:
1416 RGWPutLC() {
1417 len = 0;
1418 data = nullptr;
1419 content_md5 = nullptr;
1420 }
1421 ~RGWPutLC() override {
1422 free(data);
1423 }
1424
1425 void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) override {
1426 #define COOKIE_LEN 16
1427 char buf[COOKIE_LEN + 1];
1428
1429 RGWOp::init(store, s, dialect_handler);
1430 gen_rand_alphanumeric(s->cct, buf, sizeof(buf) - 1);
1431 cookie = buf;
1432 }
1433
1434 int verify_permission() override;
1435 void pre_exec() override;
1436 void execute() override;
1437
1438 // virtual int get_policy_from_state(RGWRados *store, struct req_state *s, stringstream& ss) { return 0; }
1439 virtual int get_params() = 0;
1440 void send_response() override = 0;
1441 const string name() override { return "put_lifecycle"; }
1442 RGWOpType get_type() override { return RGW_OP_PUT_LC; }
1443 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1444 };
1445
1446 class RGWDeleteLC : public RGWOp {
1447 protected:
1448 size_t len;
1449 char *data;
1450
1451 public:
1452 RGWDeleteLC() {
1453 len = 0;
1454 data = NULL;
1455 }
1456 ~RGWDeleteLC() override {
1457 free(data);
1458 }
1459
1460 int verify_permission() override;
1461 void pre_exec() override;
1462 void execute() override;
1463
1464 void send_response() override = 0;
1465 const string name() override { return "delete_lifecycle"; }
1466 RGWOpType get_type() override { return RGW_OP_DELETE_LC; }
1467 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1468 };
1469
1470 class RGWGetCORS : public RGWOp {
1471 protected:
1472
1473 public:
1474 RGWGetCORS() {}
1475
1476 int verify_permission() override;
1477 void execute() override;
1478
1479 void send_response() override = 0;
1480 const string name() override { return "get_cors"; }
1481 RGWOpType get_type() override { return RGW_OP_GET_CORS; }
1482 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1483 };
1484
1485 class RGWPutCORS : public RGWOp {
1486 protected:
1487 bufferlist cors_bl;
1488 bufferlist in_data;
1489
1490 public:
1491 RGWPutCORS() {}
1492 ~RGWPutCORS() override {}
1493
1494 int verify_permission() override;
1495 void execute() override;
1496
1497 virtual int get_params() = 0;
1498 void send_response() override = 0;
1499 const string name() override { return "put_cors"; }
1500 RGWOpType get_type() override { return RGW_OP_PUT_CORS; }
1501 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1502 };
1503
1504 class RGWDeleteCORS : public RGWOp {
1505 protected:
1506
1507 public:
1508 RGWDeleteCORS() {}
1509
1510 int verify_permission() override;
1511 void execute() override;
1512
1513 void send_response() override = 0;
1514 const string name() override { return "delete_cors"; }
1515 RGWOpType get_type() override { return RGW_OP_DELETE_CORS; }
1516 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1517 };
1518
1519 class RGWOptionsCORS : public RGWOp {
1520 protected:
1521 RGWCORSRule *rule;
1522 const char *origin, *req_hdrs, *req_meth;
1523
1524 public:
1525 RGWOptionsCORS() : rule(NULL), origin(NULL),
1526 req_hdrs(NULL), req_meth(NULL) {
1527 }
1528
1529 int verify_permission() override {return 0;}
1530 int validate_cors_request(RGWCORSConfiguration *cc);
1531 void execute() override;
1532 void get_response_params(string& allowed_hdrs, string& exp_hdrs, unsigned *max_age);
1533 void send_response() override = 0;
1534 const string name() override { return "options_cors"; }
1535 RGWOpType get_type() override { return RGW_OP_OPTIONS_CORS; }
1536 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1537 };
1538
1539 class RGWGetRequestPayment : public RGWOp {
1540 protected:
1541 bool requester_pays;
1542
1543 public:
1544 RGWGetRequestPayment() : requester_pays(0) {}
1545
1546 int verify_permission() override;
1547 void pre_exec() override;
1548 void execute() override;
1549
1550 void send_response() override = 0;
1551 const string name() override { return "get_request_payment"; }
1552 RGWOpType get_type() override { return RGW_OP_GET_REQUEST_PAYMENT; }
1553 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1554 };
1555
1556 class RGWSetRequestPayment : public RGWOp {
1557 protected:
1558 bool requester_pays;
1559 public:
1560 RGWSetRequestPayment() : requester_pays(false) {}
1561
1562 int verify_permission() override;
1563 void pre_exec() override;
1564 void execute() override;
1565
1566 virtual int get_params() { return 0; }
1567
1568 void send_response() override = 0;
1569 const string name() override { return "set_request_payment"; }
1570 RGWOpType get_type() override { return RGW_OP_SET_REQUEST_PAYMENT; }
1571 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1572 };
1573
1574 class RGWInitMultipart : public RGWOp {
1575 protected:
1576 string upload_id;
1577 RGWAccessControlPolicy policy;
1578
1579 public:
1580 RGWInitMultipart() {}
1581
1582 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1583 RGWOp::init(store, s, h);
1584 policy.set_ctx(s->cct);
1585 }
1586 int verify_permission() override;
1587 void pre_exec() override;
1588 void execute() override;
1589
1590 virtual int get_params() = 0;
1591 void send_response() override = 0;
1592 const string name() override { return "init_multipart"; }
1593 RGWOpType get_type() override { return RGW_OP_INIT_MULTIPART; }
1594 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1595 virtual int prepare_encryption(map<string, bufferlist>& attrs) { return 0; }
1596 };
1597
1598 class RGWCompleteMultipart : public RGWOp {
1599 protected:
1600 string upload_id;
1601 string etag;
1602 char *data;
1603 int len;
1604
1605 struct MPSerializer {
1606 librados::IoCtx ioctx;
1607 rados::cls::lock::Lock lock;
1608 librados::ObjectWriteOperation op;
1609 std::string oid;
1610 bool locked;
1611
1612 MPSerializer() : lock("RGWCompleteMultipart"), locked(false)
1613 {}
1614
1615 int try_lock(const std::string& oid, utime_t dur);
1616
1617 int unlock() {
1618 return lock.unlock(&ioctx, oid);
1619 }
1620
1621 void clear_locked() {
1622 locked = false;
1623 }
1624 } serializer;
1625
1626 public:
1627 RGWCompleteMultipart() {
1628 data = NULL;
1629 len = 0;
1630 }
1631 ~RGWCompleteMultipart() override {
1632 free(data);
1633 }
1634
1635 int verify_permission() override;
1636 void pre_exec() override;
1637 void execute() override;
1638 void complete() override;
1639
1640 virtual int get_params() = 0;
1641 void send_response() override = 0;
1642 const string name() override { return "complete_multipart"; }
1643 RGWOpType get_type() override { return RGW_OP_COMPLETE_MULTIPART; }
1644 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1645 };
1646
1647 class RGWAbortMultipart : public RGWOp {
1648 public:
1649 RGWAbortMultipart() {}
1650
1651 int verify_permission() override;
1652 void pre_exec() override;
1653 void execute() override;
1654
1655 void send_response() override = 0;
1656 const string name() override { return "abort_multipart"; }
1657 RGWOpType get_type() override { return RGW_OP_ABORT_MULTIPART; }
1658 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
1659 };
1660
1661 class RGWListMultipart : public RGWOp {
1662 protected:
1663 string upload_id;
1664 map<uint32_t, RGWUploadPartInfo> parts;
1665 int max_parts;
1666 int marker;
1667 RGWAccessControlPolicy policy;
1668 bool truncated;
1669
1670 public:
1671 RGWListMultipart() {
1672 max_parts = 1000;
1673 marker = 0;
1674 truncated = false;
1675 }
1676
1677 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1678 RGWOp::init(store, s, h);
1679 policy = RGWAccessControlPolicy(s->cct);
1680 }
1681 int verify_permission() override;
1682 void pre_exec() override;
1683 void execute() override;
1684
1685 virtual int get_params() = 0;
1686 void send_response() override = 0;
1687 const string name() override { return "list_multipart"; }
1688 RGWOpType get_type() override { return RGW_OP_LIST_MULTIPART; }
1689 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1690 };
1691
1692 struct RGWMultipartUploadEntry {
1693 rgw_bucket_dir_entry obj;
1694 RGWMPObj mp;
1695 };
1696
1697 class RGWListBucketMultiparts : public RGWOp {
1698 protected:
1699 string prefix;
1700 RGWMPObj marker;
1701 RGWMultipartUploadEntry next_marker;
1702 int max_uploads;
1703 string delimiter;
1704 vector<RGWMultipartUploadEntry> uploads;
1705 map<string, bool> common_prefixes;
1706 bool is_truncated;
1707 int default_max;
1708
1709 public:
1710 RGWListBucketMultiparts() {
1711 max_uploads = 0;
1712 is_truncated = false;
1713 default_max = 0;
1714 }
1715
1716 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1717 RGWOp::init(store, s, h);
1718 max_uploads = default_max;
1719 }
1720
1721 int verify_permission() override;
1722 void pre_exec() override;
1723 void execute() override;
1724
1725 virtual int get_params() = 0;
1726 void send_response() override = 0;
1727 const string name() override { return "list_bucket_multiparts"; }
1728 RGWOpType get_type() override { return RGW_OP_LIST_BUCKET_MULTIPARTS; }
1729 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1730 };
1731
1732
1733 class RGWGetCrossDomainPolicy : public RGWOp {
1734 public:
1735 RGWGetCrossDomainPolicy() = default;
1736 ~RGWGetCrossDomainPolicy() override = default;
1737
1738 int verify_permission() override {
1739 return 0;
1740 }
1741
1742 void execute() override {
1743 op_ret = 0;
1744 }
1745
1746 const string name() override {
1747 return "get_crossdomain_policy";
1748 }
1749
1750 RGWOpType get_type() override {
1751 return RGW_OP_GET_CROSS_DOMAIN_POLICY;
1752 }
1753
1754 uint32_t op_mask() override {
1755 return RGW_OP_TYPE_READ;
1756 }
1757 };
1758
1759
1760 class RGWGetHealthCheck : public RGWOp {
1761 public:
1762 RGWGetHealthCheck() = default;
1763 ~RGWGetHealthCheck() override = default;
1764
1765 int verify_permission() override {
1766 return 0;
1767 }
1768
1769 void execute() override;
1770
1771 const string name() override {
1772 return "get_health_check";
1773 }
1774
1775 RGWOpType get_type() override {
1776 return RGW_OP_GET_HEALTH_CHECK;
1777 }
1778
1779 uint32_t op_mask() override {
1780 return RGW_OP_TYPE_READ;
1781 }
1782 };
1783
1784
1785 class RGWDeleteMultiObj : public RGWOp {
1786 protected:
1787 int max_to_delete;
1788 int len;
1789 char *data;
1790 rgw_bucket bucket;
1791 bool quiet;
1792 bool status_dumped;
1793 bool acl_allowed = false;
1794
1795 public:
1796 RGWDeleteMultiObj() {
1797 max_to_delete = 1000;
1798 len = 0;
1799 data = NULL;
1800 quiet = false;
1801 status_dumped = false;
1802 }
1803 int verify_permission() override;
1804 void pre_exec() override;
1805 void execute() override;
1806
1807 virtual int get_params() = 0;
1808 virtual void send_status() = 0;
1809 virtual void begin_response() = 0;
1810 virtual void send_partial_response(rgw_obj_key& key, bool delete_marker,
1811 const string& marker_version_id, int ret) = 0;
1812 virtual void end_response() = 0;
1813 const string name() override { return "multi_object_delete"; }
1814 RGWOpType get_type() override { return RGW_OP_DELETE_MULTI_OBJ; }
1815 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
1816 };
1817
1818 class RGWInfo: public RGWOp {
1819 public:
1820 RGWInfo() = default;
1821 ~RGWInfo() override = default;
1822
1823 int verify_permission() override { return 0; }
1824 const string name() override { return "get info"; }
1825 RGWOpType get_type() override { return RGW_OP_GET_INFO; }
1826 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1827 };
1828
1829 extern int rgw_build_bucket_policies(RGWRados* store, struct req_state* s);
1830 extern int rgw_build_object_policies(RGWRados *store, struct req_state *s,
1831 bool prefetch_data);
1832 extern rgw::IAM::Environment rgw_build_iam_environment(RGWRados* store,
1833 struct req_state* s);
1834
1835 static inline int put_data_and_throttle(RGWPutObjDataProcessor *processor,
1836 bufferlist& data, off_t ofs,
1837 bool need_to_wait)
1838 {
1839 bool again = false;
1840 do {
1841 void *handle = nullptr;
1842 rgw_raw_obj obj;
1843
1844 uint64_t size = data.length();
1845
1846 int ret = processor->handle_data(data, ofs, &handle, &obj, &again);
1847 if (ret < 0)
1848 return ret;
1849 if (handle != nullptr)
1850 {
1851 ret = processor->throttle_data(handle, obj, size, need_to_wait);
1852 if (ret < 0)
1853 return ret;
1854 }
1855 else
1856 break;
1857 need_to_wait = false; /* the need to wait only applies to the first
1858 * iteration */
1859 } while (again);
1860
1861 return 0;
1862 } /* put_data_and_throttle */
1863
1864
1865
1866
1867
1868 static inline int get_system_versioning_params(req_state *s,
1869 uint64_t *olh_epoch,
1870 string *version_id)
1871 {
1872 if (!s->system_request) {
1873 return 0;
1874 }
1875
1876 if (olh_epoch) {
1877 string epoch_str = s->info.args.get(RGW_SYS_PARAM_PREFIX "versioned-epoch");
1878 if (!epoch_str.empty()) {
1879 string err;
1880 *olh_epoch = strict_strtol(epoch_str.c_str(), 10, &err);
1881 if (!err.empty()) {
1882 lsubdout(s->cct, rgw, 0) << "failed to parse versioned-epoch param"
1883 << dendl;
1884 return -EINVAL;
1885 }
1886 }
1887 }
1888
1889 if (version_id) {
1890 *version_id = s->info.args.get(RGW_SYS_PARAM_PREFIX "version-id");
1891 }
1892
1893 return 0;
1894 } /* get_system_versioning_params */
1895
1896 static inline void format_xattr(std::string &xattr)
1897 {
1898 /* If the extended attribute is not valid UTF-8, we encode it using
1899 * quoted-printable encoding.
1900 */
1901 if ((check_utf8(xattr.c_str(), xattr.length()) != 0) ||
1902 (check_for_control_characters(xattr.c_str(), xattr.length()) != 0)) {
1903 static const char MIME_PREFIX_STR[] = "=?UTF-8?Q?";
1904 static const int MIME_PREFIX_LEN = sizeof(MIME_PREFIX_STR) - 1;
1905 static const char MIME_SUFFIX_STR[] = "?=";
1906 static const int MIME_SUFFIX_LEN = sizeof(MIME_SUFFIX_STR) - 1;
1907 int mlen = mime_encode_as_qp(xattr.c_str(), NULL, 0);
1908 char *mime = new char[MIME_PREFIX_LEN + mlen + MIME_SUFFIX_LEN + 1];
1909 strcpy(mime, MIME_PREFIX_STR);
1910 mime_encode_as_qp(xattr.c_str(), mime + MIME_PREFIX_LEN, mlen);
1911 strcpy(mime + MIME_PREFIX_LEN + (mlen - 1), MIME_SUFFIX_STR);
1912 xattr.assign(mime);
1913 delete [] mime;
1914 }
1915 } /* format_xattr */
1916
1917 /**
1918 * Get the HTTP request metadata out of the req_state as a
1919 * map(<attr_name, attr_contents>, where attr_name is RGW_ATTR_PREFIX.HTTP_NAME)
1920 * s: The request state
1921 * attrs: will be filled up with attrs mapped as <attr_name, attr_contents>
1922 * On success returns 0.
1923 * On failure returns a negative error code.
1924 *
1925 */
1926 static inline int rgw_get_request_metadata(CephContext* const cct,
1927 struct req_info& info,
1928 std::map<std::string, ceph::bufferlist>& attrs,
1929 const bool allow_empty_attrs = true)
1930 {
1931 static const std::set<std::string> blacklisted_headers = {
1932 "x-amz-server-side-encryption-customer-algorithm",
1933 "x-amz-server-side-encryption-customer-key",
1934 "x-amz-server-side-encryption-customer-key-md5"
1935 };
1936
1937 size_t valid_meta_count = 0;
1938 for (auto& kv : info.x_meta_map) {
1939 const std::string& name = kv.first;
1940 std::string& xattr = kv.second;
1941
1942 if (blacklisted_headers.count(name) == 1) {
1943 lsubdout(cct, rgw, 10) << "skipping x>> " << name << dendl;
1944 continue;
1945 } else if (allow_empty_attrs || !xattr.empty()) {
1946 lsubdout(cct, rgw, 10) << "x>> " << name << ":" << xattr << dendl;
1947 format_xattr(xattr);
1948
1949 std::string attr_name(RGW_ATTR_PREFIX);
1950 attr_name.append(name);
1951
1952 /* Check roughly whether we aren't going behind the limit on attribute
1953 * name. Passing here doesn't guarantee that an OSD will accept that
1954 * as ObjectStore::get_max_attr_name_length() can set the limit even
1955 * lower than the "osd_max_attr_name_len" configurable. */
1956 const size_t max_attr_name_len = \
1957 cct->_conf->get_val<size_t>("rgw_max_attr_name_len");
1958 if (max_attr_name_len && attr_name.length() > max_attr_name_len) {
1959 return -ENAMETOOLONG;
1960 }
1961
1962 /* Similar remarks apply to the check for value size. We're veryfing
1963 * it early at the RGW's side as it's being claimed in /info. */
1964 const size_t max_attr_size = \
1965 cct->_conf->get_val<size_t>("rgw_max_attr_size");
1966 if (max_attr_size && xattr.length() > max_attr_size) {
1967 return -EFBIG;
1968 }
1969
1970 /* Swift allows administrators to limit the number of metadats items
1971 * send _in a single request_. */
1972 const auto rgw_max_attrs_num_in_req = \
1973 cct->_conf->get_val<size_t>("rgw_max_attrs_num_in_req");
1974 if (rgw_max_attrs_num_in_req &&
1975 ++valid_meta_count > rgw_max_attrs_num_in_req) {
1976 return -E2BIG;
1977 }
1978
1979 auto rval = attrs.emplace(std::move(attr_name), ceph::bufferlist());
1980 /* At the moment the value of the freshly created attribute key-value
1981 * pair is an empty bufferlist. */
1982
1983 ceph::bufferlist& bl = rval.first->second;
1984 bl.append(xattr.c_str(), xattr.size() + 1);
1985 }
1986 }
1987
1988 return 0;
1989 } /* rgw_get_request_metadata */
1990
1991 static inline void encode_delete_at_attr(boost::optional<ceph::real_time> delete_at,
1992 map<string, bufferlist>& attrs)
1993 {
1994 if (delete_at == boost::none) {
1995 return;
1996 }
1997
1998 bufferlist delatbl;
1999 ::encode(*delete_at, delatbl);
2000 attrs[RGW_ATTR_DELETE_AT] = delatbl;
2001 } /* encode_delete_at_attr */
2002
2003 static inline void encode_obj_tags_attr(RGWObjTags* obj_tags, map<string, bufferlist>& attrs)
2004 {
2005 if (obj_tags == nullptr){
2006 // we assume the user submitted a tag format which we couldn't parse since
2007 // this wouldn't be parsed later by get/put obj tags, lets delete if the
2008 // attr was populated
2009 return;
2010 }
2011
2012 bufferlist tagsbl;
2013 obj_tags->encode(tagsbl);
2014 attrs[RGW_ATTR_TAGS] = tagsbl;
2015 }
2016
2017 static inline int encode_dlo_manifest_attr(const char * const dlo_manifest,
2018 map<string, bufferlist>& attrs)
2019 {
2020 string dm = dlo_manifest;
2021
2022 if (dm.find('/') == string::npos) {
2023 return -EINVAL;
2024 }
2025
2026 bufferlist manifest_bl;
2027 manifest_bl.append(dlo_manifest, strlen(dlo_manifest) + 1);
2028 attrs[RGW_ATTR_USER_MANIFEST] = manifest_bl;
2029
2030 return 0;
2031 } /* encode_dlo_manifest_attr */
2032
2033 static inline void complete_etag(MD5& hash, string *etag)
2034 {
2035 char etag_buf[CEPH_CRYPTO_MD5_DIGESTSIZE];
2036 char etag_buf_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16];
2037
2038 hash.Final((byte *)etag_buf);
2039 buf_to_hex((const unsigned char *)etag_buf, CEPH_CRYPTO_MD5_DIGESTSIZE,
2040 etag_buf_str);
2041
2042 *etag = etag_buf_str;
2043 } /* complete_etag */
2044
2045 class RGWSetAttrs : public RGWOp {
2046 protected:
2047 map<string, buffer::list> attrs;
2048
2049 public:
2050 RGWSetAttrs() {}
2051 ~RGWSetAttrs() override {}
2052
2053 void emplace_attr(std::string&& key, buffer::list&& bl) {
2054 attrs.emplace(std::move(key), std::move(bl));
2055 }
2056
2057 int verify_permission() override;
2058 void pre_exec() override;
2059 void execute() override;
2060
2061 virtual int get_params() = 0;
2062 void send_response() override = 0;
2063 const string name() override { return "set_attrs"; }
2064 RGWOpType get_type() override { return RGW_OP_SET_ATTRS; }
2065 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
2066 };
2067
2068 class RGWGetObjLayout : public RGWOp {
2069 protected:
2070 RGWObjManifest *manifest{nullptr};
2071 rgw_raw_obj head_obj;
2072
2073 public:
2074 RGWGetObjLayout() {
2075 }
2076
2077 int check_caps(RGWUserCaps& caps) {
2078 return caps.check_cap("admin", RGW_CAP_READ);
2079 }
2080 int verify_permission() {
2081 return check_caps(s->user->caps);
2082 }
2083 void pre_exec();
2084 void execute();
2085
2086 virtual void send_response() = 0;
2087 virtual const string name() { return "get_obj_layout"; }
2088 virtual RGWOpType get_type() { return RGW_OP_GET_OBJ_LAYOUT; }
2089 virtual uint32_t op_mask() { return RGW_OP_TYPE_READ; }
2090 };
2091
2092 class RGWPutBucketPolicy : public RGWOp {
2093 int len;
2094 char *data = nullptr;
2095 public:
2096 RGWPutBucketPolicy() = default;
2097 ~RGWPutBucketPolicy() {
2098 if (data) {
2099 free(static_cast<void*>(data));
2100 }
2101 }
2102 void send_response() override;
2103 int verify_permission() override;
2104 uint32_t op_mask() override {
2105 return RGW_OP_TYPE_WRITE;
2106 }
2107 void execute() override;
2108 int get_params();
2109 const std::string name() override {
2110 return "put_bucket_policy";
2111 }
2112 RGWOpType get_type() override {
2113 return RGW_OP_PUT_BUCKET_POLICY;
2114 }
2115 };
2116
2117 class RGWGetBucketPolicy : public RGWOp {
2118 buffer::list policy;
2119 public:
2120 RGWGetBucketPolicy() = default;
2121 void send_response() override;
2122 int verify_permission() override;
2123 uint32_t op_mask() override {
2124 return RGW_OP_TYPE_READ;
2125 }
2126 void execute() override;
2127 const std::string name() override {
2128 return "get_bucket_policy";
2129 }
2130 RGWOpType get_type() override {
2131 return RGW_OP_GET_BUCKET_POLICY;
2132 }
2133 };
2134
2135 class RGWDeleteBucketPolicy : public RGWOp {
2136 public:
2137 RGWDeleteBucketPolicy() = default;
2138 void send_response() override;
2139 int verify_permission() override;
2140 uint32_t op_mask() override {
2141 return RGW_OP_TYPE_WRITE;
2142 }
2143 void execute() override;
2144 int get_params();
2145 const std::string name() override {
2146 return "delete_bucket_policy";
2147 }
2148 RGWOpType get_type() override {
2149 return RGW_OP_DELETE_BUCKET_POLICY;
2150 }
2151 };
2152
2153
2154 class RGWConfigBucketMetaSearch : public RGWOp {
2155 protected:
2156 std::map<std::string, uint32_t> mdsearch_config;
2157 public:
2158 RGWConfigBucketMetaSearch() {}
2159
2160 int verify_permission();
2161 void pre_exec();
2162 void execute();
2163
2164 virtual int get_params() = 0;
2165 virtual void send_response() = 0;
2166 virtual const string name() { return "config_bucket_meta_search"; }
2167 virtual RGWOpType get_type() { return RGW_OP_CONFIG_BUCKET_META_SEARCH; }
2168 virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
2169 };
2170
2171 class RGWGetBucketMetaSearch : public RGWOp {
2172 public:
2173 RGWGetBucketMetaSearch() {}
2174
2175 int verify_permission();
2176 void pre_exec();
2177 void execute() {}
2178
2179 virtual void send_response() = 0;
2180 virtual const string name() { return "get_bucket_meta_search"; }
2181 virtual RGWOpType get_type() { return RGW_OP_GET_BUCKET_META_SEARCH; }
2182 virtual uint32_t op_mask() { return RGW_OP_TYPE_READ; }
2183 };
2184
2185 class RGWDelBucketMetaSearch : public RGWOp {
2186 public:
2187 RGWDelBucketMetaSearch() {}
2188
2189 int verify_permission();
2190 void pre_exec();
2191 void execute();
2192
2193 virtual void send_response() = 0;
2194 virtual const string name() { return "delete_bucket_meta_search"; }
2195 virtual RGWOpType delete_type() { return RGW_OP_DEL_BUCKET_META_SEARCH; }
2196 virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
2197 };
2198
2199 class RGWGetClusterStat : public RGWOp {
2200 protected:
2201 struct rados_cluster_stat_t stats_op;
2202 public:
2203 RGWGetClusterStat() {}
2204
2205 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
2206 RGWOp::init(store, s, h);
2207 }
2208 int verify_permission() override {return 0;}
2209 virtual void send_response() = 0;
2210 virtual int get_params() = 0;
2211 void execute() override;
2212 virtual const string name() { return "get_cluster_stat"; }
2213 };
2214
2215
2216
2217 #endif /* CEPH_RGW_OP_H */