]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "common/errno.h" | |
5 | #include "common/Throttle.h" | |
6 | #include "common/WorkQueue.h" | |
7 | ||
8 | #include "rgw_rados.h" | |
9 | #include "rgw_rest.h" | |
10 | #include "rgw_frontend.h" | |
11 | #include "rgw_request.h" | |
12 | #include "rgw_process.h" | |
13 | #include "rgw_loadgen.h" | |
14 | #include "rgw_client_io.h" | |
15 | ||
16 | #define dout_subsys ceph_subsys_rgw | |
17 | ||
18 | void RGWProcess::RGWWQ::_dump_queue() | |
19 | { | |
20 | if (!g_conf->subsys.should_gather(ceph_subsys_rgw, 20)) { | |
21 | return; | |
22 | } | |
23 | deque<RGWRequest *>::iterator iter; | |
24 | if (process->m_req_queue.empty()) { | |
25 | dout(20) << "RGWWQ: empty" << dendl; | |
26 | return; | |
27 | } | |
28 | dout(20) << "RGWWQ:" << dendl; | |
29 | for (iter = process->m_req_queue.begin(); | |
30 | iter != process->m_req_queue.end(); ++iter) { | |
31 | dout(20) << "req: " << hex << *iter << dec << dendl; | |
32 | } | |
33 | } /* RGWProcess::RGWWQ::_dump_queue */ | |
34 | ||
35 | ||
36 | int rgw_process_authenticated(RGWHandler_REST * const handler, | |
37 | RGWOp *& op, | |
38 | RGWRequest * const req, | |
39 | req_state * const s, | |
40 | const bool skip_retarget) | |
41 | { | |
42 | req->log(s, "init permissions"); | |
43 | int ret = handler->init_permissions(op); | |
44 | if (ret < 0) { | |
45 | return ret; | |
46 | } | |
47 | ||
48 | /** | |
49 | * Only some accesses support website mode, and website mode does NOT apply | |
50 | * if you are using the REST endpoint either (ergo, no authenticated access) | |
51 | */ | |
52 | if (! skip_retarget) { | |
53 | req->log(s, "recalculating target"); | |
54 | ret = handler->retarget(op, &op); | |
55 | if (ret < 0) { | |
56 | return ret; | |
57 | } | |
58 | req->op = op; | |
59 | } else { | |
60 | req->log(s, "retargeting skipped because of SubOp mode"); | |
61 | } | |
62 | ||
63 | /* If necessary extract object ACL and put them into req_state. */ | |
64 | req->log(s, "reading permissions"); | |
65 | ret = handler->read_permissions(op); | |
66 | if (ret < 0) { | |
67 | return ret; | |
68 | } | |
69 | ||
70 | req->log(s, "init op"); | |
71 | ret = op->init_processing(); | |
72 | if (ret < 0) { | |
73 | return ret; | |
74 | } | |
75 | ||
76 | req->log(s, "verifying op mask"); | |
77 | ret = op->verify_op_mask(); | |
78 | if (ret < 0) { | |
79 | return ret; | |
80 | } | |
81 | ||
82 | req->log(s, "verifying op permissions"); | |
83 | ret = op->verify_permission(); | |
84 | if (ret < 0) { | |
85 | if (s->system_request) { | |
86 | dout(2) << "overriding permissions due to system operation" << dendl; | |
87 | } else if (s->auth.identity->is_admin_of(s->user->user_id)) { | |
88 | dout(2) << "overriding permissions due to admin operation" << dendl; | |
89 | } else { | |
90 | return ret; | |
91 | } | |
92 | } | |
93 | ||
94 | req->log(s, "verifying op params"); | |
95 | ret = op->verify_params(); | |
96 | if (ret < 0) { | |
97 | return ret; | |
98 | } | |
99 | ||
100 | req->log(s, "pre-executing"); | |
101 | op->pre_exec(); | |
102 | ||
103 | req->log(s, "executing"); | |
104 | op->execute(); | |
105 | ||
106 | req->log(s, "completing"); | |
107 | op->complete(); | |
108 | ||
109 | return 0; | |
110 | } | |
111 | ||
112 | int process_request(RGWRados* const store, | |
113 | RGWREST* const rest, | |
114 | RGWRequest* const req, | |
115 | const std::string& frontend_prefix, | |
116 | const rgw_auth_registry_t& auth_registry, | |
117 | RGWRestfulIO* const client_io, | |
118 | OpsLogSocket* const olog) | |
119 | { | |
3a9019d9 | 120 | int ret = client_io->init(g_ceph_context); |
7c673cae FG |
121 | |
122 | req->log_init(); | |
123 | ||
124 | dout(1) << "====== starting new request req=" << hex << req << dec | |
125 | << " =====" << dendl; | |
126 | perfcounter->inc(l_rgw_req); | |
127 | ||
128 | RGWEnv& rgw_env = client_io->get_env(); | |
129 | ||
130 | RGWUserInfo userinfo; | |
131 | ||
132 | struct req_state rstate(g_ceph_context, &rgw_env, &userinfo); | |
133 | struct req_state *s = &rstate; | |
134 | ||
135 | RGWObjectCtx rados_ctx(store, s); | |
136 | s->obj_ctx = &rados_ctx; | |
137 | ||
3a9019d9 FG |
138 | if (ret < 0) { |
139 | s->cio = client_io; | |
140 | abort_early(s, nullptr, ret, nullptr); | |
141 | return ret; | |
142 | } | |
143 | ||
7c673cae FG |
144 | s->req_id = store->unique_id(req->id); |
145 | s->trans_id = store->unique_trans_id(req->id); | |
146 | s->host_id = store->host_id; | |
147 | ||
148 | req->log_format(s, "initializing for trans_id = %s", s->trans_id.c_str()); | |
149 | ||
3a9019d9 | 150 | RGWOp* op = nullptr; |
7c673cae FG |
151 | int init_error = 0; |
152 | bool should_log = false; | |
153 | RGWRESTMgr *mgr; | |
154 | RGWHandler_REST *handler = rest->get_handler(store, s, | |
155 | auth_registry, | |
156 | frontend_prefix, | |
157 | client_io, &mgr, &init_error); | |
158 | if (init_error != 0) { | |
3a9019d9 | 159 | abort_early(s, nullptr, init_error, nullptr); |
7c673cae FG |
160 | goto done; |
161 | } | |
162 | dout(10) << "handler=" << typeid(*handler).name() << dendl; | |
163 | ||
164 | should_log = mgr->get_logging(); | |
165 | ||
166 | req->log_format(s, "getting op %d", s->op); | |
167 | op = handler->get_op(store); | |
168 | if (!op) { | |
169 | abort_early(s, NULL, -ERR_METHOD_NOT_ALLOWED, handler); | |
170 | goto done; | |
171 | } | |
172 | ||
173 | req->op = op; | |
174 | dout(10) << "op=" << typeid(*op).name() << dendl; | |
175 | ||
176 | s->op_type = op->get_type(); | |
177 | ||
178 | req->log(s, "verifying requester"); | |
179 | ret = op->verify_requester(auth_registry); | |
180 | if (ret < 0) { | |
181 | dout(10) << "failed to authorize request" << dendl; | |
182 | abort_early(s, NULL, ret, handler); | |
183 | goto done; | |
184 | } | |
185 | ||
186 | /* FIXME: remove this after switching all handlers to the new authentication | |
187 | * infrastructure. */ | |
188 | if (nullptr == s->auth.identity) { | |
189 | s->auth.identity = rgw::auth::transform_old_authinfo(s); | |
190 | } | |
191 | ||
192 | req->log(s, "normalizing buckets and tenants"); | |
193 | ret = handler->postauth_init(); | |
194 | if (ret < 0) { | |
195 | dout(10) << "failed to run post-auth init" << dendl; | |
196 | abort_early(s, op, ret, handler); | |
197 | goto done; | |
198 | } | |
199 | ||
200 | if (s->user->suspended) { | |
201 | dout(10) << "user is suspended, uid=" << s->user->user_id << dendl; | |
202 | abort_early(s, op, -ERR_USER_SUSPENDED, handler); | |
203 | goto done; | |
204 | } | |
205 | ||
206 | ret = rgw_process_authenticated(handler, op, req, s); | |
207 | if (ret < 0) { | |
208 | abort_early(s, op, ret, handler); | |
209 | goto done; | |
210 | } | |
211 | done: | |
212 | try { | |
213 | client_io->complete_request(); | |
214 | } catch (rgw::io::Exception& e) { | |
215 | dout(0) << "ERROR: client_io->complete_request() returned " | |
216 | << e.what() << dendl; | |
217 | } | |
218 | ||
219 | if (should_log) { | |
220 | rgw_log_op(store, rest, s, (op ? op->name() : "unknown"), olog); | |
221 | } | |
222 | ||
223 | int http_ret = s->err.http_ret; | |
224 | int op_ret = 0; | |
225 | if (op) { | |
226 | op_ret = op->get_ret(); | |
227 | } | |
228 | ||
229 | req->log_format(s, "op status=%d", op_ret); | |
230 | req->log_format(s, "http status=%d", http_ret); | |
231 | ||
232 | if (handler) | |
233 | handler->put_op(op); | |
234 | rest->put_handler(handler); | |
235 | ||
236 | dout(1) << "====== req done req=" << hex << req << dec | |
237 | << " op status=" << op_ret | |
238 | << " http_status=" << http_ret | |
239 | << " ======" | |
240 | << dendl; | |
241 | ||
242 | return (ret < 0 ? ret : s->err.ret); | |
243 | } /* process_request */ |