]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_rest_conn.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_rest_conn.h
CommitLineData
7c673cae 1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
9f95a23c 2// vim: ts=8 sw=2 smarttab ft=cpp
7c673cae 3
9f95a23c 4#pragma once
7c673cae 5
7c673cae
FG
6#include "rgw_rest_client.h"
7#include "common/ceph_json.h"
8#include "common/RefCountedObj.h"
9f95a23c 9#include "include/common_fwd.h"
7c673cae
FG
10
11#include <atomic>
12
20effc67
TL
13namespace rgw { namespace sal {
14 class Store;
15} }
16
11fdf7f2 17class RGWSI_Zone;
7c673cae
FG
18
19template <class T>
81eedcae 20static int parse_decode_json(T& t, bufferlist& bl)
7c673cae
FG
21{
22 JSONParser p;
81eedcae
TL
23 if (!p.parse(bl.c_str(), bl.length())) {
24 return -EINVAL;
7c673cae
FG
25 }
26
27 try {
28 decode_json_obj(t, &p);
29 } catch (JSONDecoder::err& e) {
30 return -EINVAL;
31 }
32 return 0;
33}
34
35struct rgw_http_param_pair {
36 const char *key;
37 const char *val;
38};
39
11fdf7f2
TL
40// append a null-terminated rgw_http_param_pair list into a list of string pairs
41inline void append_param_list(param_vec_t& params, const rgw_http_param_pair* pp)
7c673cae 42{
7c673cae 43 while (pp && pp->key) {
20effc67
TL
44 std::string k = pp->key;
45 std::string v = (pp->val ? pp->val : "");
7c673cae
FG
46 params.emplace_back(make_pair(std::move(k), std::move(v)));
47 ++pp;
48 }
11fdf7f2
TL
49}
50
20effc67 51// copy a null-terminated rgw_http_param_pair list into a list of std::string pairs
11fdf7f2
TL
52inline param_vec_t make_param_list(const rgw_http_param_pair* pp)
53{
54 param_vec_t params;
55 append_param_list(params, pp);
7c673cae
FG
56 return params;
57}
58
20effc67 59inline param_vec_t make_param_list(const std::map<std::string, std::string> *pp)
a8e16298
TL
60{
61 param_vec_t params;
62 if (!pp) {
63 return params;
64 }
65 for (auto iter : *pp) {
66 params.emplace_back(make_pair(iter.first, iter.second));
67 }
68 return params;
69}
70
7c673cae
FG
71class RGWRESTConn
72{
73 CephContext *cct;
20effc67 74 std::vector<std::string> endpoints;
7c673cae 75 RGWAccessKey key;
20effc67
TL
76 std::string self_zone_group;
77 std::string remote_id;
78 std::optional<std::string> api_name;
11fdf7f2 79 HostStyle host_style;
7c673cae
FG
80 std::atomic<int64_t> counter = { 0 };
81
82public:
83
20effc67
TL
84 RGWRESTConn(CephContext *_cct,
85 RGWSI_Zone *zone_svc,
86 const std::string& _remote_id,
87 const std::list<std::string>& endpoints,
88 std::optional<std::string> _api_name,
89 HostStyle _host_style = PathStyle);
90 RGWRESTConn(CephContext *_cct,
91 rgw::sal::Store* store,
92 const std::string& _remote_id,
93 const std::list<std::string>& endpoints,
94 std::optional<std::string> _api_name,
95 HostStyle _host_style = PathStyle);
96 RGWRESTConn(CephContext *_cct,
97 RGWSI_Zone *zone_svc,
98 const std::string& _remote_id,
99 const std::list<std::string>& endpoints,
100 RGWAccessKey _cred,
101 std::optional<std::string> _api_name,
102 HostStyle _host_style = PathStyle);
103 RGWRESTConn(CephContext *_cct,
104 rgw::sal::Store* store,
105 const std::string& _remote_id,
106 const std::list<std::string>& endpoints,
107 RGWAccessKey _cred,
108 std::optional<std::string> _api_name,
109 HostStyle _host_style = PathStyle);
11fdf7f2 110
7c673cae
FG
111 // custom move needed for atomic
112 RGWRESTConn(RGWRESTConn&& other);
113 RGWRESTConn& operator=(RGWRESTConn&& other);
11fdf7f2 114 virtual ~RGWRESTConn() = default;
7c673cae 115
20effc67
TL
116 int get_url(std::string& endpoint);
117 std::string get_url();
118 const std::string& get_self_zonegroup() {
7c673cae
FG
119 return self_zone_group;
120 }
20effc67 121 const std::string& get_remote_id() {
7c673cae
FG
122 return remote_id;
123 }
124 RGWAccessKey& get_key() {
125 return key;
126 }
127
20effc67
TL
128 std::optional<std::string> get_api_name() const {
129 return api_name;
130 }
131
11fdf7f2
TL
132 HostStyle get_host_style() {
133 return host_style;
134 }
135
7c673cae
FG
136 CephContext *get_ctx() {
137 return cct;
138 }
139 size_t get_endpoint_count() const { return endpoints.size(); }
140
20effc67 141 virtual void populate_params(param_vec_t& params, const rgw_user *uid, const std::string& zonegroup);
11fdf7f2 142
7c673cae 143 /* sync request */
b3b6e05e 144 int forward(const DoutPrefixProvider *dpp, const rgw_user& uid, req_info& info, obj_version *objv, size_t max_response, bufferlist *inbl, bufferlist *outbl, optional_yield y);
7c673cae 145
7c673cae 146
11fdf7f2 147 /* async requests */
20effc67
TL
148 int put_obj_send_init(rgw::sal::Object* obj, const rgw_http_param_pair *extra_params, RGWRESTStreamS3PutObj **req);
149 int put_obj_async_init(const DoutPrefixProvider *dpp, const rgw_user& uid, rgw::sal::Object* obj,
150 std::map<std::string, bufferlist>& attrs, RGWRESTStreamS3PutObj **req);
151 int complete_request(RGWRESTStreamS3PutObj *req, std::string& etag,
f67539c2 152 ceph::real_time *mtime, optional_yield y);
11fdf7f2
TL
153
154 struct get_obj_params {
155 rgw_user uid;
156 req_info *info{nullptr};
157 const ceph::real_time *mod_ptr{nullptr};
158 const ceph::real_time *unmod_ptr{nullptr};
159 bool high_precision_time{true};
160
20effc67 161 std::string etag;
11fdf7f2
TL
162
163 uint32_t mod_zone_id{0};
164 uint64_t mod_pg_ver{0};
165
166 bool prepend_metadata{false};
167 bool get_op{false};
168 bool rgwx_stat{false};
169 bool sync_manifest{false};
170
171 bool skip_decrypt{true};
172 RGWHTTPStreamRWRequest::ReceiveCB *cb{nullptr};
173
174 bool range_is_set{false};
175 uint64_t range_start{0};
176 uint64_t range_end{0};
177 };
178
20effc67 179 int get_obj(const DoutPrefixProvider *dpp, const rgw::sal::Object* obj, const get_obj_params& params, bool send, RGWRESTStreamRWRequest **req);
11fdf7f2 180
20effc67 181 int get_obj(const DoutPrefixProvider *dpp, const rgw_user& uid, req_info *info /* optional */, const rgw::sal::Object* obj,
7c673cae
FG
182 const ceph::real_time *mod_ptr, const ceph::real_time *unmod_ptr,
183 uint32_t mod_zone_id, uint64_t mod_pg_ver,
184 bool prepend_metadata, bool get_op, bool rgwx_stat, bool sync_manifest,
11fdf7f2
TL
185 bool skip_decrypt, bool send, RGWHTTPStreamRWRequest::ReceiveCB *cb, RGWRESTStreamRWRequest **req);
186 int complete_request(RGWRESTStreamRWRequest *req,
20effc67 187 std::string *etag,
11fdf7f2
TL
188 ceph::real_time *mtime,
189 uint64_t *psize,
20effc67
TL
190 std::map<std::string, std::string> *pattrs,
191 std::map<std::string, std::string> *pheaders,
f67539c2 192 optional_yield y);
7c673cae 193
b3b6e05e 194 int get_resource(const DoutPrefixProvider *dpp,
20effc67 195 const std::string& resource,
7c673cae 196 param_vec_t *extra_params,
20effc67
TL
197 std::map<std::string, std::string>* extra_headers,
198 bufferlist& bl,
199 bufferlist *send_data,
200 RGWHTTPManager *mgr,
201 optional_yield y);
202
203 int send_resource(const DoutPrefixProvider *dpp,
204 const std::string& method,
205 const std::string& resource,
206 rgw_http_param_pair *extra_params,
207 std::map<std::string, std::string>* extra_headers,
31f18b77 208 bufferlist& bl,
f67539c2
TL
209 bufferlist *send_data,
210 RGWHTTPManager *mgr,
211 optional_yield y);
7c673cae 212
31f18b77 213 template <class T>
20effc67 214 int get_json_resource(const DoutPrefixProvider *dpp, const std::string& resource, param_vec_t *params,
f67539c2 215 bufferlist *in_data, optional_yield y, T& t);
7c673cae 216 template <class T>
20effc67 217 int get_json_resource(const DoutPrefixProvider *dpp, const std::string& resource, param_vec_t *params,
f67539c2 218 optional_yield y, T& t);
7c673cae 219 template <class T>
20effc67 220 int get_json_resource(const DoutPrefixProvider *dpp, const std::string& resource, const rgw_http_param_pair *pp,
f67539c2 221 optional_yield y, T& t);
11fdf7f2
TL
222
223private:
20effc67 224 void populate_zonegroup(param_vec_t& params, const std::string& zonegroup) {
11fdf7f2
TL
225 if (!zonegroup.empty()) {
226 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "zonegroup", zonegroup));
227 }
228 }
229 void populate_uid(param_vec_t& params, const rgw_user *uid) {
230 if (uid) {
20effc67 231 std::string uid_str = uid->to_str();
11fdf7f2
TL
232 if (!uid->empty()){
233 params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "uid", uid_str));
234 }
235 }
236 }
237};
238
239class S3RESTConn : public RGWRESTConn {
240
241public:
242
20effc67
TL
243 S3RESTConn(CephContext *_cct, RGWSI_Zone *svc_zone, const std::string& _remote_id, const std::list<std::string>& endpoints, std::optional<std::string> _api_name, HostStyle _host_style = PathStyle) :
244 RGWRESTConn(_cct, svc_zone, _remote_id, endpoints, _api_name, _host_style) {}
245
246 S3RESTConn(CephContext *_cct, rgw::sal::Store* store, const std::string& _remote_id, const std::list<std::string>& endpoints, std::optional<std::string> _api_name, HostStyle _host_style = PathStyle) :
247 RGWRESTConn(_cct, store, _remote_id, endpoints, _api_name, _host_style) {}
248
249 S3RESTConn(CephContext *_cct, RGWSI_Zone *svc_zone, const std::string& _remote_id, const std::list<std::string>& endpoints, RGWAccessKey _cred, std::optional<std::string> _api_name, HostStyle _host_style = PathStyle):
250 RGWRESTConn(_cct, svc_zone, _remote_id, endpoints, _cred, _api_name, _host_style) {}
11fdf7f2 251
20effc67
TL
252 S3RESTConn(CephContext *_cct, rgw::sal::Store* store, const std::string& _remote_id, const std::list<std::string>& endpoints, RGWAccessKey _cred, std::optional<std::string> _api_name, HostStyle _host_style = PathStyle):
253 RGWRESTConn(_cct, store, _remote_id, endpoints, _cred, _api_name, _host_style) {}
11fdf7f2
TL
254 ~S3RESTConn() override = default;
255
20effc67 256 void populate_params(param_vec_t& params, const rgw_user *uid, const std::string& zonegroup) override {
11fdf7f2
TL
257 // do not populate any params in S3 REST Connection.
258 return;
259 }
7c673cae
FG
260};
261
262
263template<class T>
20effc67 264int RGWRESTConn::get_json_resource(const DoutPrefixProvider *dpp, const std::string& resource, param_vec_t *params,
f67539c2 265 bufferlist *in_data, optional_yield y, T& t)
7c673cae
FG
266{
267 bufferlist bl;
b3b6e05e 268 int ret = get_resource(dpp, resource, params, nullptr, bl, in_data, nullptr, y);
7c673cae
FG
269 if (ret < 0) {
270 return ret;
271 }
272
81eedcae 273 ret = parse_decode_json(t, bl);
7c673cae
FG
274 if (ret < 0) {
275 return ret;
276 }
277
278 return 0;
279}
280
31f18b77 281template<class T>
20effc67 282int RGWRESTConn::get_json_resource(const DoutPrefixProvider *dpp, const std::string& resource, param_vec_t *params,
f67539c2 283 optional_yield y, T& t)
31f18b77 284{
b3b6e05e 285 return get_json_resource(dpp, resource, params, nullptr, y, t);
31f18b77
FG
286}
287
7c673cae 288template<class T>
20effc67 289int RGWRESTConn::get_json_resource(const DoutPrefixProvider *dpp, const std::string& resource, const rgw_http_param_pair *pp,
f67539c2 290 optional_yield y, T& t)
7c673cae
FG
291{
292 param_vec_t params = make_param_list(pp);
b3b6e05e 293 return get_json_resource(dpp, resource, &params, y, t);
7c673cae
FG
294}
295
11fdf7f2 296class RGWStreamIntoBufferlist : public RGWHTTPStreamRWRequest::ReceiveCB {
7c673cae
FG
297 bufferlist& bl;
298public:
11fdf7f2
TL
299 explicit RGWStreamIntoBufferlist(bufferlist& _bl) : bl(_bl) {}
300 int handle_data(bufferlist& inbl, bool *pause) override {
7c673cae 301 bl.claim_append(inbl);
11fdf7f2 302 return inbl.length();
7c673cae
FG
303 }
304};
305
11fdf7f2 306class RGWRESTReadResource : public RefCountedObject, public RGWIOProvider {
7c673cae
FG
307 CephContext *cct;
308 RGWRESTConn *conn;
20effc67 309 std::string resource;
7c673cae 310 param_vec_t params;
20effc67 311 std::map<std::string, std::string> headers;
7c673cae
FG
312 bufferlist bl;
313 RGWStreamIntoBufferlist cb;
314
315 RGWHTTPManager *mgr;
316 RGWRESTStreamReadRequest req;
317
318 void init_common(param_vec_t *extra_headers);
319
320public:
321 RGWRESTReadResource(RGWRESTConn *_conn,
20effc67 322 const std::string& _resource,
7c673cae
FG
323 const rgw_http_param_pair *pp,
324 param_vec_t *extra_headers,
325 RGWHTTPManager *_mgr);
326
327 RGWRESTReadResource(RGWRESTConn *_conn,
20effc67 328 const std::string& _resource,
7c673cae
FG
329 param_vec_t& _params,
330 param_vec_t *extra_headers,
331 RGWHTTPManager *_mgr);
11fdf7f2 332 ~RGWRESTReadResource() = default;
7c673cae 333
11fdf7f2
TL
334 rgw_io_id get_io_id(int io_type) {
335 return req.get_io_id(io_type);
7c673cae 336 }
11fdf7f2
TL
337
338 void set_io_user_info(void *user_info) override {
339 req.set_io_user_info(user_info);
340 }
341
342 void *get_io_user_info() override {
343 return req.get_io_user_info();
7c673cae
FG
344 }
345
346 template <class T>
347 int decode_resource(T *dest);
348
b3b6e05e 349 int read(const DoutPrefixProvider *dpp, optional_yield y);
7c673cae 350
b3b6e05e 351 int aio_read(const DoutPrefixProvider *dpp);
7c673cae 352
20effc67 353 std::string to_str() {
7c673cae
FG
354 return req.to_str();
355 }
356
357 int get_http_status() {
358 return req.get_http_status();
359 }
360
9f95a23c
TL
361 int wait(bufferlist *pbl, optional_yield y) {
362 int ret = req.wait(y);
7c673cae
FG
363 if (ret < 0) {
364 return ret;
365 }
366
367 if (req.get_status() < 0) {
368 return req.get_status();
369 }
370 *pbl = bl;
371 return 0;
372 }
373
374 template <class T>
9f95a23c 375 int wait(T *dest, optional_yield y);
7c673cae
FG
376
377 template <class T>
b3b6e05e 378 int fetch(const DoutPrefixProvider *dpp, T *dest, optional_yield y);
7c673cae
FG
379};
380
381
382template <class T>
383int RGWRESTReadResource::decode_resource(T *dest)
384{
385 int ret = req.get_status();
386 if (ret < 0) {
387 return ret;
388 }
81eedcae 389 ret = parse_decode_json(*dest, bl);
7c673cae
FG
390 if (ret < 0) {
391 return ret;
392 }
393 return 0;
394}
395
396template <class T>
b3b6e05e 397int RGWRESTReadResource::fetch(const DoutPrefixProvider *dpp, T *dest, optional_yield y)
7c673cae 398{
b3b6e05e 399 int ret = read(dpp, y);
7c673cae
FG
400 if (ret < 0) {
401 return ret;
402 }
403
404 ret = decode_resource(dest);
405 if (ret < 0) {
406 return ret;
407 }
408 return 0;
409}
410
411template <class T>
9f95a23c 412int RGWRESTReadResource::wait(T *dest, optional_yield y)
7c673cae 413{
9f95a23c 414 int ret = req.wait(y);
7c673cae
FG
415 if (ret < 0) {
416 return ret;
417 }
418
419 ret = decode_resource(dest);
420 if (ret < 0) {
421 return ret;
422 }
423 return 0;
424}
425
11fdf7f2 426class RGWRESTSendResource : public RefCountedObject, public RGWIOProvider {
7c673cae
FG
427 CephContext *cct;
428 RGWRESTConn *conn;
20effc67
TL
429 std::string method;
430 std::string resource;
7c673cae 431 param_vec_t params;
20effc67 432 std::map<std::string, std::string> headers;
7c673cae
FG
433 bufferlist bl;
434 RGWStreamIntoBufferlist cb;
435
436 RGWHTTPManager *mgr;
437 RGWRESTStreamRWRequest req;
438
439 void init_common(param_vec_t *extra_headers);
440
441public:
442 RGWRESTSendResource(RGWRESTConn *_conn,
20effc67
TL
443 const std::string& _method,
444 const std::string& _resource,
7c673cae
FG
445 const rgw_http_param_pair *pp,
446 param_vec_t *extra_headers,
447 RGWHTTPManager *_mgr);
448
449 RGWRESTSendResource(RGWRESTConn *_conn,
20effc67
TL
450 const std::string& _method,
451 const std::string& _resource,
7c673cae
FG
452 param_vec_t& params,
453 param_vec_t *extra_headers,
454 RGWHTTPManager *_mgr);
455
11fdf7f2
TL
456 ~RGWRESTSendResource() = default;
457
458 rgw_io_id get_io_id(int io_type) {
459 return req.get_io_id(io_type);
7c673cae 460 }
11fdf7f2
TL
461
462 void set_io_user_info(void *user_info) override {
463 req.set_io_user_info(user_info);
464 }
465
466 void *get_io_user_info() override {
467 return req.get_io_user_info();
7c673cae
FG
468 }
469
b3b6e05e 470 int send(const DoutPrefixProvider *dpp, bufferlist& bl, optional_yield y);
7c673cae 471
b3b6e05e 472 int aio_send(const DoutPrefixProvider *dpp, bufferlist& bl);
7c673cae 473
20effc67 474 std::string to_str() {
7c673cae
FG
475 return req.to_str();
476 }
477
478 int get_http_status() {
479 return req.get_http_status();
480 }
481
81eedcae 482 template <class E = int>
9f95a23c
TL
483 int wait(bufferlist *pbl, optional_yield y, E *err_result = nullptr) {
484 int ret = req.wait(y);
11fdf7f2 485 *pbl = bl;
7c673cae 486
81eedcae
TL
487 if (ret < 0 && err_result ) {
488 ret = parse_decode_json(*err_result, bl);
7c673cae 489 }
81eedcae
TL
490
491 return req.get_status();
7c673cae
FG
492 }
493
11fdf7f2 494 template <class T, class E = int>
9f95a23c 495 int wait(T *dest, optional_yield y, E *err_result = nullptr);
7c673cae
FG
496};
497
92f5a8d4 498template <class T, class E>
9f95a23c 499int RGWRESTSendResource::wait(T *dest, optional_yield y, E *err_result)
7c673cae 500{
9f95a23c 501 int ret = req.wait(y);
81eedcae
TL
502 if (ret >= 0) {
503 ret = req.get_status();
7c673cae 504 }
a8e16298 505
81eedcae
TL
506 if (ret < 0 && err_result) {
507 ret = parse_decode_json(*err_result, bl);
a8e16298
TL
508 }
509
7c673cae
FG
510 if (ret < 0) {
511 return ret;
512 }
7c673cae 513
81eedcae 514 ret = parse_decode_json(*dest, bl);
7c673cae
FG
515 if (ret < 0) {
516 return ret;
517 }
518 return 0;
81eedcae 519
7c673cae
FG
520}
521
522class RGWRESTPostResource : public RGWRESTSendResource {
523public:
524 RGWRESTPostResource(RGWRESTConn *_conn,
20effc67 525 const std::string& _resource,
7c673cae
FG
526 const rgw_http_param_pair *pp,
527 param_vec_t *extra_headers,
528 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "POST", _resource,
529 pp, extra_headers, _mgr) {}
530
531 RGWRESTPostResource(RGWRESTConn *_conn,
20effc67 532 const std::string& _resource,
7c673cae
FG
533 param_vec_t& params,
534 param_vec_t *extra_headers,
535 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "POST", _resource,
536 params, extra_headers, _mgr) {}
537
538};
539
540class RGWRESTPutResource : public RGWRESTSendResource {
541public:
542 RGWRESTPutResource(RGWRESTConn *_conn,
20effc67 543 const std::string& _resource,
7c673cae
FG
544 const rgw_http_param_pair *pp,
545 param_vec_t *extra_headers,
546 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "PUT", _resource,
547 pp, extra_headers, _mgr) {}
548
549 RGWRESTPutResource(RGWRESTConn *_conn,
20effc67 550 const std::string& _resource,
7c673cae
FG
551 param_vec_t& params,
552 param_vec_t *extra_headers,
553 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "PUT", _resource,
554 params, extra_headers, _mgr) {}
555
556};
557
558class RGWRESTDeleteResource : public RGWRESTSendResource {
559public:
560 RGWRESTDeleteResource(RGWRESTConn *_conn,
20effc67 561 const std::string& _resource,
7c673cae
FG
562 const rgw_http_param_pair *pp,
563 param_vec_t *extra_headers,
564 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "DELETE", _resource,
565 pp, extra_headers, _mgr) {}
566
567 RGWRESTDeleteResource(RGWRESTConn *_conn,
20effc67 568 const std::string& _resource,
7c673cae
FG
569 param_vec_t& params,
570 param_vec_t *extra_headers,
571 RGWHTTPManager *_mgr) : RGWRESTSendResource(_conn, "DELETE", _resource,
572 params, extra_headers, _mgr) {}
573
574};