]>
Commit | Line | Data |
---|---|---|
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 | |
11fdf7f2 | 4 | #include "rgw_zone.h" |
7c673cae | 5 | #include "rgw_rest_conn.h" |
f67539c2 TL |
6 | #include "rgw_sal.h" |
7 | #include "rgw_rados.h" | |
7c673cae | 8 | |
11fdf7f2 TL |
9 | #include "services/svc_zone.h" |
10 | ||
7c673cae FG |
11 | #define dout_subsys ceph_subsys_rgw |
12 | ||
11fdf7f2 | 13 | RGWRESTConn::RGWRESTConn(CephContext *_cct, RGWSI_Zone *zone_svc, |
7c673cae | 14 | const string& _remote_id, |
11fdf7f2 TL |
15 | const list<string>& remote_endpoints, |
16 | HostStyle _host_style) | |
7c673cae FG |
17 | : cct(_cct), |
18 | endpoints(remote_endpoints.begin(), remote_endpoints.end()), | |
11fdf7f2 | 19 | remote_id(_remote_id), host_style(_host_style) |
7c673cae | 20 | { |
11fdf7f2 TL |
21 | if (zone_svc) { |
22 | key = zone_svc->get_zone_params().system_key; | |
23 | self_zone_group = zone_svc->get_zonegroup().get_id(); | |
24 | } | |
25 | } | |
26 | ||
27 | RGWRESTConn::RGWRESTConn(CephContext *_cct, RGWSI_Zone *zone_svc, | |
28 | const string& _remote_id, | |
29 | const list<string>& remote_endpoints, | |
30 | RGWAccessKey _cred, | |
31 | HostStyle _host_style) | |
32 | : cct(_cct), | |
33 | endpoints(remote_endpoints.begin(), remote_endpoints.end()), | |
34 | key(std::move(_cred)), | |
35 | remote_id(_remote_id), host_style(_host_style) | |
36 | { | |
37 | if (zone_svc) { | |
38 | self_zone_group = zone_svc->get_zonegroup().get_id(); | |
7c673cae FG |
39 | } |
40 | } | |
41 | ||
42 | RGWRESTConn::RGWRESTConn(RGWRESTConn&& other) | |
43 | : cct(other.cct), | |
44 | endpoints(std::move(other.endpoints)), | |
45 | key(std::move(other.key)), | |
46 | self_zone_group(std::move(other.self_zone_group)), | |
47 | remote_id(std::move(other.remote_id)), | |
48 | counter(other.counter.load()) | |
49 | { | |
50 | } | |
51 | ||
52 | RGWRESTConn& RGWRESTConn::operator=(RGWRESTConn&& other) | |
53 | { | |
54 | cct = other.cct; | |
55 | endpoints = std::move(other.endpoints); | |
56 | key = std::move(other.key); | |
57 | self_zone_group = std::move(other.self_zone_group); | |
58 | remote_id = std::move(other.remote_id); | |
59 | counter = other.counter.load(); | |
60 | return *this; | |
61 | } | |
62 | ||
63 | int RGWRESTConn::get_url(string& endpoint) | |
64 | { | |
65 | if (endpoints.empty()) { | |
66 | ldout(cct, 0) << "ERROR: endpoints not configured for upstream zone" << dendl; | |
67 | return -EIO; | |
68 | } | |
69 | ||
70 | int i = ++counter; | |
71 | endpoint = endpoints[i % endpoints.size()]; | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
76 | string RGWRESTConn::get_url() | |
77 | { | |
78 | string endpoint; | |
f67539c2 | 79 | get_url(endpoint); |
7c673cae FG |
80 | return endpoint; |
81 | } | |
82 | ||
11fdf7f2 | 83 | void RGWRESTConn::populate_params(param_vec_t& params, const rgw_user *uid, const string& zonegroup) |
7c673cae | 84 | { |
11fdf7f2 TL |
85 | populate_uid(params, uid); |
86 | populate_zonegroup(params, zonegroup); | |
7c673cae FG |
87 | } |
88 | ||
b3b6e05e | 89 | int RGWRESTConn::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 FG |
90 | { |
91 | string url; | |
92 | int ret = get_url(url); | |
93 | if (ret < 0) | |
94 | return ret; | |
95 | param_vec_t params; | |
96 | populate_params(params, &uid, self_zone_group); | |
97 | if (objv) { | |
98 | params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "tag", objv->tag)); | |
99 | char buf[16]; | |
100 | snprintf(buf, sizeof(buf), "%lld", (long long)objv->ver); | |
101 | params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "ver", buf)); | |
102 | } | |
11fdf7f2 | 103 | RGWRESTSimpleRequest req(cct, info.method, url, NULL, ¶ms); |
b3b6e05e | 104 | return req.forward_request(dpp, key, info, max_response, inbl, outbl, y); |
7c673cae FG |
105 | } |
106 | ||
107 | class StreamObjData : public RGWGetDataCB { | |
108 | rgw_obj obj; | |
109 | public: | |
110 | explicit StreamObjData(rgw_obj& _obj) : obj(_obj) {} | |
111 | }; | |
112 | ||
f67539c2 | 113 | int RGWRESTConn::put_obj_send_init(rgw::sal::RGWObject* obj, const rgw_http_param_pair *extra_params, RGWRESTStreamS3PutObj **req) |
7c673cae FG |
114 | { |
115 | string url; | |
116 | int ret = get_url(url); | |
117 | if (ret < 0) | |
118 | return ret; | |
119 | ||
11fdf7f2 | 120 | rgw_user uid; |
7c673cae FG |
121 | param_vec_t params; |
122 | populate_params(params, &uid, self_zone_group); | |
11fdf7f2 TL |
123 | |
124 | if (extra_params) { | |
125 | append_param_list(params, extra_params); | |
126 | } | |
127 | ||
128 | RGWRESTStreamS3PutObj *wr = new RGWRESTStreamS3PutObj(cct, "PUT", url, NULL, ¶ms, host_style); | |
129 | wr->send_init(obj); | |
130 | *req = wr; | |
131 | return 0; | |
132 | } | |
133 | ||
b3b6e05e TL |
134 | int RGWRESTConn::put_obj_async(const DoutPrefixProvider *dpp, |
135 | const rgw_user& uid, rgw::sal::RGWObject* obj, uint64_t obj_size, | |
11fdf7f2 TL |
136 | map<string, bufferlist>& attrs, bool send, |
137 | RGWRESTStreamS3PutObj **req) | |
138 | { | |
139 | string url; | |
140 | int ret = get_url(url); | |
141 | if (ret < 0) | |
142 | return ret; | |
143 | ||
144 | param_vec_t params; | |
145 | populate_params(params, &uid, self_zone_group); | |
146 | RGWRESTStreamS3PutObj *wr = new RGWRESTStreamS3PutObj(cct, "PUT", url, NULL, ¶ms, host_style); | |
b3b6e05e | 147 | ret = wr->put_obj_init(dpp, key, obj, obj_size, attrs, send); |
c07f9fc5 FG |
148 | if (ret < 0) { |
149 | delete wr; | |
150 | return ret; | |
151 | } | |
152 | *req = wr; | |
153 | return 0; | |
7c673cae FG |
154 | } |
155 | ||
f67539c2 TL |
156 | int RGWRESTConn::complete_request(RGWRESTStreamS3PutObj *req, string& etag, |
157 | real_time *mtime, optional_yield y) | |
7c673cae | 158 | { |
f67539c2 | 159 | int ret = req->complete_request(y, &etag, mtime); |
7c673cae FG |
160 | delete req; |
161 | ||
162 | return ret; | |
163 | } | |
164 | ||
11fdf7f2 | 165 | static void set_date_header(const real_time *t, map<string, string>& headers, bool high_precision_time, const string& header_name) |
7c673cae FG |
166 | { |
167 | if (!t) { | |
168 | return; | |
169 | } | |
170 | stringstream s; | |
171 | utime_t tm = utime_t(*t); | |
11fdf7f2 TL |
172 | if (high_precision_time) { |
173 | tm.gmtime_nsec(s); | |
174 | } else { | |
175 | tm.gmtime(s); | |
176 | } | |
7c673cae FG |
177 | headers[header_name] = s.str(); |
178 | } | |
179 | ||
180 | template <class T> | |
181 | static void set_header(T val, map<string, string>& headers, const string& header_name) | |
182 | { | |
183 | stringstream s; | |
184 | s << val; | |
185 | headers[header_name] = s.str(); | |
186 | } | |
187 | ||
188 | ||
b3b6e05e | 189 | int RGWRESTConn::get_obj(const DoutPrefixProvider *dpp, const rgw_user& uid, req_info *info /* optional */, const rgw::sal::RGWObject* obj, |
7c673cae FG |
190 | const real_time *mod_ptr, const real_time *unmod_ptr, |
191 | uint32_t mod_zone_id, uint64_t mod_pg_ver, | |
192 | bool prepend_metadata, bool get_op, bool rgwx_stat, | |
11fdf7f2 TL |
193 | bool sync_manifest, bool skip_decrypt, |
194 | bool send, RGWHTTPStreamRWRequest::ReceiveCB *cb, RGWRESTStreamRWRequest **req) | |
195 | { | |
196 | get_obj_params params; | |
197 | params.uid = uid; | |
198 | params.info = info; | |
199 | params.mod_ptr = mod_ptr; | |
200 | params.mod_pg_ver = mod_pg_ver; | |
201 | params.prepend_metadata = prepend_metadata; | |
202 | params.get_op = get_op; | |
203 | params.rgwx_stat = rgwx_stat; | |
204 | params.sync_manifest = sync_manifest; | |
205 | params.skip_decrypt = skip_decrypt; | |
206 | params.cb = cb; | |
b3b6e05e | 207 | return get_obj(dpp, obj, params, send, req); |
11fdf7f2 TL |
208 | } |
209 | ||
b3b6e05e | 210 | int RGWRESTConn::get_obj(const DoutPrefixProvider *dpp, const rgw::sal::RGWObject* obj, const get_obj_params& in_params, bool send, RGWRESTStreamRWRequest **req) |
7c673cae FG |
211 | { |
212 | string url; | |
213 | int ret = get_url(url); | |
214 | if (ret < 0) | |
215 | return ret; | |
216 | ||
217 | param_vec_t params; | |
11fdf7f2 TL |
218 | populate_params(params, &in_params.uid, self_zone_group); |
219 | if (in_params.prepend_metadata) { | |
220 | params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "prepend-metadata", "true")); | |
7c673cae | 221 | } |
11fdf7f2 | 222 | if (in_params.rgwx_stat) { |
7c673cae FG |
223 | params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "stat", "true")); |
224 | } | |
11fdf7f2 | 225 | if (in_params.sync_manifest) { |
7c673cae FG |
226 | params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "sync-manifest", "")); |
227 | } | |
11fdf7f2 | 228 | if (in_params.skip_decrypt) { |
181888fb FG |
229 | params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "skip-decrypt", "")); |
230 | } | |
f67539c2 TL |
231 | if (!obj->get_instance().empty()) { |
232 | const string& instance = obj->get_instance(); | |
7c673cae FG |
233 | params.push_back(param_pair_t("versionId", instance)); |
234 | } | |
11fdf7f2 TL |
235 | if (in_params.get_op) { |
236 | *req = new RGWRESTStreamReadRequest(cct, url, in_params.cb, NULL, ¶ms, host_style); | |
7c673cae | 237 | } else { |
11fdf7f2 | 238 | *req = new RGWRESTStreamHeadRequest(cct, url, in_params.cb, NULL, ¶ms); |
7c673cae FG |
239 | } |
240 | map<string, string> extra_headers; | |
11fdf7f2 TL |
241 | if (in_params.info) { |
242 | const auto& orig_map = in_params.info->env->get_map(); | |
7c673cae FG |
243 | |
244 | /* add original headers that start with HTTP_X_AMZ_ */ | |
31f18b77 FG |
245 | static constexpr char SEARCH_AMZ_PREFIX[] = "HTTP_X_AMZ_"; |
246 | for (auto iter= orig_map.lower_bound(SEARCH_AMZ_PREFIX); iter != orig_map.end(); ++iter) { | |
7c673cae | 247 | const string& name = iter->first; |
11fdf7f2 | 248 | if (name == "HTTP_X_AMZ_DATE") /* don't forward date from original request */ |
7c673cae | 249 | continue; |
31f18b77 | 250 | if (name.compare(0, strlen(SEARCH_AMZ_PREFIX), SEARCH_AMZ_PREFIX) != 0) |
7c673cae FG |
251 | break; |
252 | extra_headers[iter->first] = iter->second; | |
253 | } | |
254 | } | |
255 | ||
11fdf7f2 TL |
256 | set_date_header(in_params.mod_ptr, extra_headers, in_params.high_precision_time, "HTTP_IF_MODIFIED_SINCE"); |
257 | set_date_header(in_params.unmod_ptr, extra_headers, in_params.high_precision_time, "HTTP_IF_UNMODIFIED_SINCE"); | |
258 | if (!in_params.etag.empty()) { | |
259 | set_header(in_params.etag, extra_headers, "HTTP_IF_MATCH"); | |
7c673cae | 260 | } |
11fdf7f2 TL |
261 | if (in_params.mod_zone_id != 0) { |
262 | set_header(in_params.mod_zone_id, extra_headers, "HTTP_DEST_ZONE_SHORT_ID"); | |
263 | } | |
264 | if (in_params.mod_pg_ver != 0) { | |
265 | set_header(in_params.mod_pg_ver, extra_headers, "HTTP_DEST_PG_VER"); | |
266 | } | |
267 | if (in_params.range_is_set) { | |
268 | char buf[64]; | |
269 | snprintf(buf, sizeof(buf), "bytes=%lld-%lld", (long long)in_params.range_start, (long long)in_params.range_end); | |
270 | set_header(buf, extra_headers, "RANGE"); | |
7c673cae FG |
271 | } |
272 | ||
b3b6e05e | 273 | int r = (*req)->send_prepare(dpp, key, extra_headers, obj->get_obj()); |
7c673cae | 274 | if (r < 0) { |
11fdf7f2 | 275 | goto done_err; |
7c673cae FG |
276 | } |
277 | ||
11fdf7f2 TL |
278 | if (!send) { |
279 | return 0; | |
280 | } | |
281 | ||
282 | r = (*req)->send(nullptr); | |
283 | if (r < 0) { | |
284 | goto done_err; | |
285 | } | |
286 | return 0; | |
287 | done_err: | |
288 | delete *req; | |
289 | *req = nullptr; | |
7c673cae FG |
290 | return r; |
291 | } | |
292 | ||
11fdf7f2 TL |
293 | int RGWRESTConn::complete_request(RGWRESTStreamRWRequest *req, |
294 | string *etag, | |
295 | real_time *mtime, | |
296 | uint64_t *psize, | |
297 | map<string, string> *pattrs, | |
f67539c2 TL |
298 | map<string, string> *pheaders, |
299 | optional_yield y) | |
7c673cae | 300 | { |
f67539c2 | 301 | int ret = req->complete_request(y, etag, mtime, psize, pattrs, pheaders); |
7c673cae FG |
302 | delete req; |
303 | ||
304 | return ret; | |
305 | } | |
306 | ||
b3b6e05e TL |
307 | int RGWRESTConn::get_resource(const DoutPrefixProvider *dpp, |
308 | const string& resource, | |
7c673cae FG |
309 | param_vec_t *extra_params, |
310 | map<string, string> *extra_headers, | |
311 | bufferlist& bl, | |
31f18b77 | 312 | bufferlist *send_data, |
f67539c2 TL |
313 | RGWHTTPManager *mgr, |
314 | optional_yield y) | |
7c673cae FG |
315 | { |
316 | string url; | |
317 | int ret = get_url(url); | |
318 | if (ret < 0) | |
319 | return ret; | |
320 | ||
321 | param_vec_t params; | |
322 | ||
323 | if (extra_params) { | |
324 | params.insert(params.end(), extra_params->begin(), extra_params->end()); | |
325 | } | |
326 | ||
327 | populate_params(params, nullptr, self_zone_group); | |
328 | ||
329 | RGWStreamIntoBufferlist cb(bl); | |
330 | ||
11fdf7f2 | 331 | RGWRESTStreamReadRequest req(cct, url, &cb, NULL, ¶ms, host_style); |
7c673cae FG |
332 | |
333 | map<string, string> headers; | |
334 | if (extra_headers) { | |
335 | headers.insert(extra_headers->begin(), extra_headers->end()); | |
336 | } | |
337 | ||
b3b6e05e | 338 | ret = req.send_request(dpp, &key, headers, resource, mgr, send_data); |
7c673cae | 339 | if (ret < 0) { |
b3b6e05e | 340 | ldpp_dout(dpp, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl; |
7c673cae FG |
341 | return ret; |
342 | } | |
343 | ||
f67539c2 | 344 | return req.complete_request(y); |
7c673cae FG |
345 | } |
346 | ||
347 | RGWRESTReadResource::RGWRESTReadResource(RGWRESTConn *_conn, | |
348 | const string& _resource, | |
349 | const rgw_http_param_pair *pp, | |
350 | param_vec_t *extra_headers, | |
351 | RGWHTTPManager *_mgr) | |
352 | : cct(_conn->get_ctx()), conn(_conn), resource(_resource), | |
353 | params(make_param_list(pp)), cb(bl), mgr(_mgr), | |
354 | req(cct, conn->get_url(), &cb, NULL, NULL) | |
355 | { | |
356 | init_common(extra_headers); | |
357 | } | |
358 | ||
359 | RGWRESTReadResource::RGWRESTReadResource(RGWRESTConn *_conn, | |
360 | const string& _resource, | |
361 | param_vec_t& _params, | |
362 | param_vec_t *extra_headers, | |
363 | RGWHTTPManager *_mgr) | |
364 | : cct(_conn->get_ctx()), conn(_conn), resource(_resource), params(_params), | |
365 | cb(bl), mgr(_mgr), req(cct, conn->get_url(), &cb, NULL, NULL) | |
366 | { | |
367 | init_common(extra_headers); | |
368 | } | |
369 | ||
370 | void RGWRESTReadResource::init_common(param_vec_t *extra_headers) | |
371 | { | |
11fdf7f2 | 372 | conn->populate_params(params, nullptr, conn->get_self_zonegroup()); |
7c673cae FG |
373 | |
374 | if (extra_headers) { | |
375 | headers.insert(extra_headers->begin(), extra_headers->end()); | |
376 | } | |
377 | ||
378 | req.set_params(¶ms); | |
379 | } | |
380 | ||
b3b6e05e | 381 | int RGWRESTReadResource::read(const DoutPrefixProvider *dpp, optional_yield y) |
7c673cae | 382 | { |
b3b6e05e | 383 | int ret = req.send_request(dpp, &conn->get_key(), headers, resource, mgr); |
7c673cae | 384 | if (ret < 0) { |
b3b6e05e | 385 | ldpp_dout(dpp, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl; |
7c673cae FG |
386 | return ret; |
387 | } | |
388 | ||
f67539c2 | 389 | return req.complete_request(y); |
7c673cae FG |
390 | } |
391 | ||
b3b6e05e | 392 | int RGWRESTReadResource::aio_read(const DoutPrefixProvider *dpp) |
7c673cae | 393 | { |
b3b6e05e | 394 | int ret = req.send_request(dpp, &conn->get_key(), headers, resource, mgr); |
7c673cae | 395 | if (ret < 0) { |
b3b6e05e | 396 | ldpp_dout(dpp, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl; |
7c673cae FG |
397 | return ret; |
398 | } | |
399 | ||
400 | return 0; | |
401 | } | |
402 | ||
403 | RGWRESTSendResource::RGWRESTSendResource(RGWRESTConn *_conn, | |
404 | const string& _method, | |
405 | const string& _resource, | |
406 | const rgw_http_param_pair *pp, | |
407 | param_vec_t *extra_headers, | |
408 | RGWHTTPManager *_mgr) | |
409 | : cct(_conn->get_ctx()), conn(_conn), method(_method), resource(_resource), | |
410 | params(make_param_list(pp)), cb(bl), mgr(_mgr), | |
11fdf7f2 | 411 | req(cct, method.c_str(), conn->get_url(), &cb, NULL, NULL, _conn->get_host_style()) |
7c673cae FG |
412 | { |
413 | init_common(extra_headers); | |
414 | } | |
415 | ||
416 | RGWRESTSendResource::RGWRESTSendResource(RGWRESTConn *_conn, | |
417 | const string& _method, | |
418 | const string& _resource, | |
419 | param_vec_t& params, | |
420 | param_vec_t *extra_headers, | |
421 | RGWHTTPManager *_mgr) | |
422 | : cct(_conn->get_ctx()), conn(_conn), method(_method), resource(_resource), params(params), | |
11fdf7f2 | 423 | cb(bl), mgr(_mgr), req(cct, method.c_str(), conn->get_url(), &cb, NULL, NULL, _conn->get_host_style()) |
7c673cae FG |
424 | { |
425 | init_common(extra_headers); | |
426 | } | |
427 | ||
428 | void RGWRESTSendResource::init_common(param_vec_t *extra_headers) | |
429 | { | |
11fdf7f2 | 430 | conn->populate_params(params, nullptr, conn->get_self_zonegroup()); |
7c673cae FG |
431 | |
432 | if (extra_headers) { | |
433 | headers.insert(extra_headers->begin(), extra_headers->end()); | |
434 | } | |
435 | ||
436 | req.set_params(¶ms); | |
437 | } | |
438 | ||
b3b6e05e | 439 | int RGWRESTSendResource::send(const DoutPrefixProvider *dpp, bufferlist& outbl, optional_yield y) |
7c673cae | 440 | { |
11fdf7f2 | 441 | req.set_send_length(outbl.length()); |
7c673cae | 442 | req.set_outbl(outbl); |
11fdf7f2 | 443 | |
b3b6e05e | 444 | int ret = req.send_request(dpp, &conn->get_key(), headers, resource, mgr); |
7c673cae | 445 | if (ret < 0) { |
b3b6e05e | 446 | ldpp_dout(dpp, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl; |
7c673cae FG |
447 | return ret; |
448 | } | |
449 | ||
f67539c2 | 450 | return req.complete_request(y); |
7c673cae FG |
451 | } |
452 | ||
b3b6e05e | 453 | int RGWRESTSendResource::aio_send(const DoutPrefixProvider *dpp, bufferlist& outbl) |
7c673cae | 454 | { |
11fdf7f2 | 455 | req.set_send_length(outbl.length()); |
7c673cae | 456 | req.set_outbl(outbl); |
11fdf7f2 | 457 | |
b3b6e05e | 458 | int ret = req.send_request(dpp, &conn->get_key(), headers, resource, mgr); |
7c673cae | 459 | if (ret < 0) { |
b3b6e05e | 460 | ldpp_dout(dpp, 5) << __func__ << ": send_request() resource=" << resource << " returned ret=" << ret << dendl; |
7c673cae FG |
461 | return ret; |
462 | } | |
463 | ||
464 | return 0; | |
465 | } |