]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_process.cc
import ceph pacific 16.2.5
[ceph.git] / ceph / src / rgw / rgw_process.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include "common/errno.h"
5 #include "common/Throttle.h"
6 #include "common/WorkQueue.h"
7 #include "include/scope_guard.h"
8
9 #include "rgw_dmclock_scheduler.h"
10 #include "rgw_rest.h"
11 #include "rgw_frontend.h"
12 #include "rgw_request.h"
13 #include "rgw_process.h"
14 #include "rgw_loadgen.h"
15 #include "rgw_client_io.h"
16 #include "rgw_opa.h"
17 #include "rgw_perf_counters.h"
18 #include "rgw_lua.h"
19 #include "rgw_lua_request.h"
20
21 #include "services/svc_zone_utils.h"
22
23 #define dout_subsys ceph_subsys_rgw
24
25 using rgw::dmclock::Scheduler;
26
27 void RGWProcess::RGWWQ::_dump_queue()
28 {
29 if (!g_conf()->subsys.should_gather<ceph_subsys_rgw, 20>()) {
30 return;
31 }
32 deque<RGWRequest *>::iterator iter;
33 if (process->m_req_queue.empty()) {
34 dout(20) << "RGWWQ: empty" << dendl;
35 return;
36 }
37 dout(20) << "RGWWQ:" << dendl;
38 for (iter = process->m_req_queue.begin();
39 iter != process->m_req_queue.end(); ++iter) {
40 dout(20) << "req: " << hex << *iter << dec << dendl;
41 }
42 } /* RGWProcess::RGWWQ::_dump_queue */
43
44 auto schedule_request(Scheduler *scheduler, req_state *s, RGWOp *op)
45 {
46 using rgw::dmclock::SchedulerCompleter;
47 if (!scheduler)
48 return std::make_pair(0,SchedulerCompleter{});
49
50 const auto client = op->dmclock_client();
51 const auto cost = op->dmclock_cost();
52 if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 10)) {
53 ldpp_dout(op,10) << "scheduling with "
54 << s->cct->_conf.get_val<std::string>("rgw_scheduler_type")
55 << " client=" << static_cast<int>(client)
56 << " cost=" << cost << dendl;
57 }
58 return scheduler->schedule_request(client, {},
59 req_state::Clock::to_double(s->time),
60 cost,
61 s->yield);
62 }
63
64 bool RGWProcess::RGWWQ::_enqueue(RGWRequest* req) {
65 process->m_req_queue.push_back(req);
66 perfcounter->inc(l_rgw_qlen);
67 dout(20) << "enqueued request req=" << hex << req << dec << dendl;
68 _dump_queue();
69 return true;
70 }
71
72 RGWRequest* RGWProcess::RGWWQ::_dequeue() {
73 if (process->m_req_queue.empty())
74 return NULL;
75 RGWRequest *req = process->m_req_queue.front();
76 process->m_req_queue.pop_front();
77 dout(20) << "dequeued request req=" << hex << req << dec << dendl;
78 _dump_queue();
79 perfcounter->inc(l_rgw_qlen, -1);
80 return req;
81 }
82
83 void RGWProcess::RGWWQ::_process(RGWRequest *req, ThreadPool::TPHandle &) {
84 perfcounter->inc(l_rgw_qactive);
85 process->handle_request(this, req);
86 process->req_throttle.put(1);
87 perfcounter->inc(l_rgw_qactive, -1);
88 }
89
90 int rgw_process_authenticated(RGWHandler_REST * const handler,
91 RGWOp *& op,
92 RGWRequest * const req,
93 req_state * const s,
94 optional_yield y,
95 const bool skip_retarget)
96 {
97 ldpp_dout(op, 2) << "init permissions" << dendl;
98 int ret = handler->init_permissions(op, y);
99 if (ret < 0) {
100 return ret;
101 }
102
103 /**
104 * Only some accesses support website mode, and website mode does NOT apply
105 * if you are using the REST endpoint either (ergo, no authenticated access)
106 */
107 if (! skip_retarget) {
108 ldpp_dout(op, 2) << "recalculating target" << dendl;
109 ret = handler->retarget(op, &op, y);
110 if (ret < 0) {
111 return ret;
112 }
113 req->op = op;
114 } else {
115 ldpp_dout(op, 2) << "retargeting skipped because of SubOp mode" << dendl;
116 }
117
118 /* If necessary extract object ACL and put them into req_state. */
119 ldpp_dout(op, 2) << "reading permissions" << dendl;
120 ret = handler->read_permissions(op, y);
121 if (ret < 0) {
122 return ret;
123 }
124
125 ldpp_dout(op, 2) << "init op" << dendl;
126 ret = op->init_processing(y);
127 if (ret < 0) {
128 return ret;
129 }
130
131 ldpp_dout(op, 2) << "verifying op mask" << dendl;
132 ret = op->verify_op_mask();
133 if (ret < 0) {
134 return ret;
135 }
136
137 /* Check if OPA is used to authorize requests */
138 if (s->cct->_conf->rgw_use_opa_authz) {
139 ret = rgw_opa_authorize(op, s);
140 if (ret < 0) {
141 return ret;
142 }
143 }
144
145 ldpp_dout(op, 2) << "verifying op permissions" << dendl;
146 ret = op->verify_permission(y);
147 if (ret < 0) {
148 if (s->system_request) {
149 dout(2) << "overriding permissions due to system operation" << dendl;
150 } else if (s->auth.identity->is_admin_of(s->user->get_id())) {
151 dout(2) << "overriding permissions due to admin operation" << dendl;
152 } else {
153 return ret;
154 }
155 }
156
157 ldpp_dout(op, 2) << "verifying op params" << dendl;
158 ret = op->verify_params();
159 if (ret < 0) {
160 return ret;
161 }
162
163 ldpp_dout(op, 2) << "pre-executing" << dendl;
164 op->pre_exec();
165
166 ldpp_dout(op, 2) << "executing" << dendl;
167 op->execute(y);
168
169 ldpp_dout(op, 2) << "completing" << dendl;
170 op->complete();
171
172 return 0;
173 }
174
175 int process_request(rgw::sal::RGWRadosStore* const store,
176 RGWREST* const rest,
177 RGWRequest* const req,
178 const std::string& frontend_prefix,
179 const rgw_auth_registry_t& auth_registry,
180 RGWRestfulIO* const client_io,
181 OpsLogSocket* const olog,
182 optional_yield yield,
183 rgw::dmclock::Scheduler *scheduler,
184 string* user,
185 ceph::coarse_real_clock::duration* latency,
186 int* http_ret)
187 {
188 int ret = client_io->init(g_ceph_context);
189
190 dout(1) << "====== starting new request req=" << hex << req << dec
191 << " =====" << dendl;
192 perfcounter->inc(l_rgw_req);
193
194 RGWEnv& rgw_env = client_io->get_env();
195
196 struct req_state rstate(g_ceph_context, &rgw_env, req->id);
197 struct req_state *s = &rstate;
198
199 std::unique_ptr<rgw::sal::RGWUser> u = store->get_user(rgw_user());
200 s->set_user(u);
201
202 RGWObjectCtx rados_ctx(store, s);
203 s->obj_ctx = &rados_ctx;
204
205 auto sysobj_ctx = store->svc()->sysobj->init_obj_ctx();
206 s->sysobj_ctx = &sysobj_ctx;
207
208 if (ret < 0) {
209 s->cio = client_io;
210 abort_early(s, nullptr, ret, nullptr, yield);
211 return ret;
212 }
213
214 s->req_id = store->svc()->zone_utils->unique_id(req->id);
215 s->trans_id = store->svc()->zone_utils->unique_trans_id(req->id);
216 s->host_id = store->getRados()->host_id;
217 s->yield = yield;
218
219 ldpp_dout(s, 2) << "initializing for trans_id = " << s->trans_id << dendl;
220
221 RGWOp* op = nullptr;
222 int init_error = 0;
223 bool should_log = false;
224 RGWRESTMgr *mgr;
225 RGWHandler_REST *handler = rest->get_handler(store, s,
226 auth_registry,
227 frontend_prefix,
228 client_io, &mgr, &init_error);
229 rgw::dmclock::SchedulerCompleter c;
230
231 if (init_error != 0) {
232 abort_early(s, nullptr, init_error, nullptr, yield);
233 goto done;
234 }
235 ldpp_dout(s, 10) << "handler=" << typeid(*handler).name() << dendl;
236
237 should_log = mgr->get_logging();
238
239 ldpp_dout(s, 2) << "getting op " << s->op << dendl;
240 op = handler->get_op();
241 if (!op) {
242 abort_early(s, NULL, -ERR_METHOD_NOT_ALLOWED, handler, yield);
243 goto done;
244 }
245 {
246 std::string script;
247 auto rc = rgw::lua::read_script(store, s->bucket_tenant, s->yield, rgw::lua::context::preRequest, script);
248 if (rc == -ENOENT) {
249 // no script, nothing to do
250 } else if (rc < 0) {
251 ldpp_dout(op, 5) << "WARNING: failed to read pre request script. error: " << rc << dendl;
252 } else {
253 rc = rgw::lua::request::execute(store, rest, olog, s, op->name(), script);
254 if (rc < 0) {
255 ldpp_dout(op, 5) << "WARNING: failed to execute pre request script. error: " << rc << dendl;
256 }
257 }
258 }
259 std::tie(ret,c) = schedule_request(scheduler, s, op);
260 if (ret < 0) {
261 if (ret == -EAGAIN) {
262 ret = -ERR_RATE_LIMITED;
263 }
264 ldpp_dout(op,0) << "Scheduling request failed with " << ret << dendl;
265 abort_early(s, op, ret, handler, yield);
266 goto done;
267 }
268 req->op = op;
269 ldpp_dout(op, 10) << "op=" << typeid(*op).name() << dendl;
270
271 s->op_type = op->get_type();
272
273 try {
274 ldpp_dout(op, 2) << "verifying requester" << dendl;
275 ret = op->verify_requester(auth_registry, yield);
276 if (ret < 0) {
277 dout(10) << "failed to authorize request" << dendl;
278 abort_early(s, op, ret, handler, yield);
279 goto done;
280 }
281
282 /* FIXME: remove this after switching all handlers to the new authentication
283 * infrastructure. */
284 if (nullptr == s->auth.identity) {
285 s->auth.identity = rgw::auth::transform_old_authinfo(s);
286 }
287
288 ldpp_dout(op, 2) << "normalizing buckets and tenants" << dendl;
289 ret = handler->postauth_init(yield);
290 if (ret < 0) {
291 dout(10) << "failed to run post-auth init" << dendl;
292 abort_early(s, op, ret, handler, yield);
293 goto done;
294 }
295
296 if (s->user->get_info().suspended) {
297 dout(10) << "user is suspended, uid=" << s->user->get_id() << dendl;
298 abort_early(s, op, -ERR_USER_SUSPENDED, handler, yield);
299 goto done;
300 }
301
302 ret = rgw_process_authenticated(handler, op, req, s, yield);
303 if (ret < 0) {
304 abort_early(s, op, ret, handler, yield);
305 goto done;
306 }
307 } catch (const ceph::crypto::DigestException& e) {
308 dout(0) << "authentication failed" << e.what() << dendl;
309 abort_early(s, op, -ERR_INVALID_SECRET_KEY, handler, yield);
310 }
311
312 done:
313 if (op) {
314 std::string script;
315 auto rc = rgw::lua::read_script(store, s->bucket_tenant, s->yield, rgw::lua::context::postRequest, script);
316 if (rc == -ENOENT) {
317 // no script, nothing to do
318 } else if (rc < 0) {
319 ldpp_dout(op, 5) << "WARNING: failed to read post request script. error: " << rc << dendl;
320 } else {
321 rc = rgw::lua::request::execute(store, rest, olog, s, op->name(), script);
322 if (rc < 0) {
323 ldpp_dout(op, 5) << "WARNING: failed to execute post request script. error: " << rc << dendl;
324 }
325 }
326 }
327
328 try {
329 client_io->complete_request();
330 } catch (rgw::io::Exception& e) {
331 dout(0) << "ERROR: client_io->complete_request() returned "
332 << e.what() << dendl;
333 }
334
335 if (should_log) {
336 rgw_log_op(store->getRados(), rest, s, (op ? op->name() : "unknown"), olog);
337 }
338
339 if (http_ret != nullptr) {
340 *http_ret = s->err.http_ret;
341 }
342 int op_ret = 0;
343
344 if (user && !rgw::sal::RGWUser::empty(s->user.get())) {
345 *user = s->user->get_id().to_str();
346 }
347
348 if (op) {
349 op_ret = op->get_ret();
350 ldpp_dout(op, 2) << "op status=" << op_ret << dendl;
351 ldpp_dout(op, 2) << "http status=" << s->err.http_ret << dendl;
352 } else {
353 ldpp_dout(s, 2) << "http status=" << s->err.http_ret << dendl;
354 }
355 if (handler)
356 handler->put_op(op);
357 rest->put_handler(handler);
358
359 const auto lat = s->time_elapsed();
360 if (latency) {
361 *latency = lat;
362 }
363
364 dout(1) << "====== req done req=" << hex << req << dec
365 << " op status=" << op_ret
366 << " http_status=" << s->err.http_ret
367 << " latency=" << lat
368 << " ======"
369 << dendl;
370
371 return (ret < 0 ? ret : s->err.ret);
372 } /* process_request */