]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/services/svc_rados.cc
1e1b12023f622049659954bf3986c0ac2b8667ff
[ceph.git] / ceph / src / rgw / services / svc_rados.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 "svc_rados.h"
5
6 #include "include/rados/librados.hpp"
7 #include "common/errno.h"
8 #include "osd/osd_types.h"
9 #include "rgw/rgw_tools.h"
10 #include "rgw/rgw_cr_rados.h"
11
12 #include "auth/AuthRegistry.h"
13
14 #define dout_subsys ceph_subsys_rgw
15
16 RGWSI_RADOS::RGWSI_RADOS(CephContext *cct) : RGWServiceInstance(cct)
17 {
18 }
19
20 RGWSI_RADOS::~RGWSI_RADOS()
21 {
22 }
23
24 int RGWSI_RADOS::do_start(optional_yield)
25 {
26 int ret = rados.init_with_context(cct);
27 if (ret < 0) {
28 return ret;
29 }
30 ret = rados.connect();
31 if (ret < 0) {
32 return ret;
33 }
34
35 async_processor.reset(new RGWAsyncRadosProcessor(cct, cct->_conf->rgw_num_async_rados_threads));
36 async_processor->start();
37
38 return 0;
39 }
40
41 void RGWSI_RADOS::shutdown()
42 {
43 if (async_processor) {
44 async_processor->stop();
45 }
46 }
47
48 librados::Rados* RGWSI_RADOS::get_rados_handle()
49 {
50 return &rados;
51 }
52
53 uint64_t RGWSI_RADOS::instance_id()
54 {
55 return get_rados_handle()->get_instance_id();
56 }
57
58 int RGWSI_RADOS::open_pool_ctx(const rgw_pool& pool, librados::IoCtx& io_ctx,
59 const OpenParams& params)
60 {
61 return rgw_init_ioctx(get_rados_handle(), pool, io_ctx,
62 params.create,
63 params.mostly_omap);
64 }
65
66 int RGWSI_RADOS::pool_iterate(librados::IoCtx& io_ctx,
67 librados::NObjectIterator& iter,
68 uint32_t num, vector<rgw_bucket_dir_entry>& objs,
69 RGWAccessListFilter *filter,
70 bool *is_truncated)
71 {
72 if (iter == io_ctx.nobjects_end())
73 return -ENOENT;
74
75 uint32_t i;
76
77 for (i = 0; i < num && iter != io_ctx.nobjects_end(); ++i, ++iter) {
78 rgw_bucket_dir_entry e;
79
80 string oid = iter->get_oid();
81 ldout(cct, 20) << "RGWRados::pool_iterate: got " << oid << dendl;
82
83 // fill it in with initial values; we may correct later
84 if (filter && !filter->filter(oid, oid))
85 continue;
86
87 e.key = oid;
88 objs.push_back(e);
89 }
90
91 if (is_truncated)
92 *is_truncated = (iter != io_ctx.nobjects_end());
93
94 return objs.size();
95 }
96
97 RGWSI_RADOS::Obj::Obj(Pool& pool, const string& oid) : rados_svc(pool.rados_svc)
98 {
99 ref.pool = pool;
100 ref.obj = rgw_raw_obj(pool.get_pool(), oid);
101 }
102
103 void RGWSI_RADOS::Obj::init(const rgw_raw_obj& obj)
104 {
105 ref.pool = RGWSI_RADOS::Pool(rados_svc, obj.pool);
106 ref.obj = obj;
107 }
108
109 int RGWSI_RADOS::Obj::open()
110 {
111 int r = ref.pool.open();
112 if (r < 0) {
113 return r;
114 }
115
116 ref.pool.ioctx().locator_set_key(ref.obj.loc);
117
118 return 0;
119 }
120
121 int RGWSI_RADOS::Obj::operate(librados::ObjectWriteOperation *op,
122 optional_yield y, int flags)
123 {
124 return rgw_rados_operate(ref.pool.ioctx(), ref.obj.oid, op, y, flags);
125 }
126
127 int RGWSI_RADOS::Obj::operate(librados::ObjectReadOperation *op,
128 bufferlist *pbl, optional_yield y, int flags)
129 {
130 return rgw_rados_operate(ref.pool.ioctx(), ref.obj.oid, op, pbl, y, flags);
131 }
132
133 int RGWSI_RADOS::Obj::aio_operate(librados::AioCompletion *c, librados::ObjectWriteOperation *op)
134 {
135 return ref.pool.ioctx().aio_operate(ref.obj.oid, c, op);
136 }
137
138 int RGWSI_RADOS::Obj::aio_operate(librados::AioCompletion *c, librados::ObjectReadOperation *op,
139 bufferlist *pbl)
140 {
141 return ref.pool.ioctx().aio_operate(ref.obj.oid, c, op, pbl);
142 }
143
144 int RGWSI_RADOS::Obj::watch(uint64_t *handle, librados::WatchCtx2 *ctx)
145 {
146 return ref.pool.ioctx().watch2(ref.obj.oid, handle, ctx);
147 }
148
149 int RGWSI_RADOS::Obj::aio_watch(librados::AioCompletion *c, uint64_t *handle, librados::WatchCtx2 *ctx)
150 {
151 return ref.pool.ioctx().aio_watch(ref.obj.oid, c, handle, ctx);
152 }
153
154 int RGWSI_RADOS::Obj::unwatch(uint64_t handle)
155 {
156 return ref.pool.ioctx().unwatch2(handle);
157 }
158
159 int RGWSI_RADOS::Obj::notify(bufferlist& bl, uint64_t timeout_ms,
160 bufferlist *pbl, optional_yield y)
161 {
162 return rgw_rados_notify(ref.pool.ioctx(), ref.obj.oid, bl, timeout_ms, pbl, y);
163 }
164
165 void RGWSI_RADOS::Obj::notify_ack(uint64_t notify_id,
166 uint64_t cookie,
167 bufferlist& bl)
168 {
169 ref.pool.ioctx().notify_ack(ref.obj.oid, notify_id, cookie, bl);
170 }
171
172 uint64_t RGWSI_RADOS::Obj::get_last_version()
173 {
174 return ref.pool.ioctx().get_last_version();
175 }
176
177 int RGWSI_RADOS::Pool::create()
178 {
179 librados::Rados *rad = rados_svc->get_rados_handle();
180 int r = rad->pool_create(pool.name.c_str());
181 if (r < 0) {
182 ldout(rados_svc->cct, 0) << "WARNING: pool_create returned " << r << dendl;
183 return r;
184 }
185 librados::IoCtx io_ctx;
186 r = rad->ioctx_create(pool.name.c_str(), io_ctx);
187 if (r < 0) {
188 ldout(rados_svc->cct, 0) << "WARNING: ioctx_create returned " << r << dendl;
189 return r;
190 }
191 r = io_ctx.application_enable(pg_pool_t::APPLICATION_NAME_RGW, false);
192 if (r < 0) {
193 ldout(rados_svc->cct, 0) << "WARNING: application_enable returned " << r << dendl;
194 return r;
195 }
196 return 0;
197 }
198
199 int RGWSI_RADOS::Pool::create(const vector<rgw_pool>& pools, vector<int> *retcodes)
200 {
201 vector<librados::PoolAsyncCompletion *> completions;
202 vector<int> rets;
203
204 librados::Rados *rad = rados_svc->get_rados_handle();
205 for (auto iter = pools.begin(); iter != pools.end(); ++iter) {
206 librados::PoolAsyncCompletion *c = librados::Rados::pool_async_create_completion();
207 completions.push_back(c);
208 auto& pool = *iter;
209 int ret = rad->pool_create_async(pool.name.c_str(), c);
210 rets.push_back(ret);
211 }
212
213 vector<int>::iterator riter;
214 vector<librados::PoolAsyncCompletion *>::iterator citer;
215
216 bool error = false;
217 ceph_assert(rets.size() == completions.size());
218 for (riter = rets.begin(), citer = completions.begin(); riter != rets.end(); ++riter, ++citer) {
219 int r = *riter;
220 librados::PoolAsyncCompletion *c = *citer;
221 if (r == 0) {
222 c->wait();
223 r = c->get_return_value();
224 if (r < 0) {
225 ldout(rados_svc->cct, 0) << "WARNING: async pool_create returned " << r << dendl;
226 error = true;
227 }
228 }
229 c->release();
230 retcodes->push_back(r);
231 }
232 if (error) {
233 return 0;
234 }
235
236 std::vector<librados::IoCtx> io_ctxs;
237 retcodes->clear();
238 for (auto pool : pools) {
239 io_ctxs.emplace_back();
240 int ret = rad->ioctx_create(pool.name.c_str(), io_ctxs.back());
241 if (ret < 0) {
242 ldout(rados_svc->cct, 0) << "WARNING: ioctx_create returned " << ret << dendl;
243 error = true;
244 }
245 retcodes->push_back(ret);
246 }
247 if (error) {
248 return 0;
249 }
250
251 completions.clear();
252 for (auto &io_ctx : io_ctxs) {
253 librados::PoolAsyncCompletion *c =
254 librados::Rados::pool_async_create_completion();
255 completions.push_back(c);
256 int ret = io_ctx.application_enable_async(pg_pool_t::APPLICATION_NAME_RGW,
257 false, c);
258 ceph_assert(ret == 0);
259 }
260
261 retcodes->clear();
262 for (auto c : completions) {
263 c->wait();
264 int ret = c->get_return_value();
265 if (ret == -EOPNOTSUPP) {
266 ret = 0;
267 } else if (ret < 0) {
268 ldout(rados_svc->cct, 0) << "WARNING: async application_enable returned " << ret
269 << dendl;
270 error = true;
271 }
272 c->release();
273 retcodes->push_back(ret);
274 }
275 return 0;
276 }
277
278 int RGWSI_RADOS::Pool::lookup()
279 {
280 librados::Rados *rad = rados_svc->get_rados_handle();
281 int ret = rad->pool_lookup(pool.name.c_str());
282 if (ret < 0) {
283 return ret;
284 }
285
286 return 0;
287 }
288
289 int RGWSI_RADOS::Pool::open(const OpenParams& params)
290 {
291 return rados_svc->open_pool_ctx(pool, state.ioctx, params);
292 }
293
294 int RGWSI_RADOS::Pool::List::init(const string& marker, RGWAccessListFilter *filter)
295 {
296 if (ctx.initialized) {
297 return -EINVAL;
298 }
299
300 if (!pool) {
301 return -EINVAL;
302 }
303
304 int r = pool->rados_svc->open_pool_ctx(pool->pool, ctx.ioctx);
305 if (r < 0) {
306 return r;
307 }
308
309 librados::ObjectCursor oc;
310 if (!oc.from_str(marker)) {
311 ldout(pool->rados_svc->cct, 10) << "failed to parse cursor: " << marker << dendl;
312 return -EINVAL;
313 }
314
315 ctx.iter = ctx.ioctx.nobjects_begin(oc);
316 ctx.filter = filter;
317 ctx.initialized = true;
318
319 return 0;
320 }
321
322 int RGWSI_RADOS::Pool::List::get_next(int max,
323 std::vector<string> *oids,
324 bool *is_truncated)
325 {
326 if (!ctx.initialized) {
327 return -EINVAL;
328 }
329 vector<rgw_bucket_dir_entry> objs;
330 int r = pool->rados_svc->pool_iterate(ctx.ioctx, ctx.iter, max, objs, ctx.filter, is_truncated);
331 if (r < 0) {
332 if(r != -ENOENT) {
333 ldout(pool->rados_svc->cct, 10) << "failed to list objects pool_iterate returned r=" << r << dendl;
334 }
335 return r;
336 }
337
338 for (auto& o : objs) {
339 oids->push_back(o.key.name);
340 }
341
342 return oids->size();
343 }
344
345 RGWSI_RADOS::Obj RGWSI_RADOS::Handle::obj(const rgw_raw_obj& o)
346 {
347 return RGWSI_RADOS::Obj(rados_svc, o);
348 }
349 int RGWSI_RADOS::Handle::watch_flush()
350 {
351 librados::Rados *rad = rados_svc->get_rados_handle();
352 return rad->watch_flush();
353 }
354
355 int RGWSI_RADOS::Handle::mon_command(std::string cmd,
356 const bufferlist& inbl,
357 bufferlist *outbl,
358 std::string *outs)
359 {
360 librados::Rados *rad = rados_svc->get_rados_handle();
361 return rad->mon_command(cmd, inbl, outbl, outs);
362 }
363
364 int RGWSI_RADOS::Pool::List::get_marker(string *marker)
365 {
366 if (!ctx.initialized) {
367 return -EINVAL;
368 }
369
370 *marker = ctx.iter.get_cursor().to_str();
371 return 0;
372 }
373
374 int RGWSI_RADOS::clog_warn(const string& msg)
375 {
376 string cmd =
377 "{"
378 "\"prefix\": \"log\", "
379 "\"level\": \"warn\", "
380 "\"logtext\": [\"" + msg + "\"]"
381 "}";
382
383 bufferlist inbl;
384 auto h = handle();
385 return h.mon_command(cmd, inbl, nullptr, nullptr);
386 }
387
388 bool RGWSI_RADOS::check_secure_mon_conn() const
389 {
390 AuthRegistry reg(cct);
391
392 reg.refresh_config();
393
394 std::vector<uint32_t> methods;
395 std::vector<uint32_t> modes;
396
397 reg.get_supported_methods(CEPH_ENTITY_TYPE_MON, &methods, &modes);
398 ldout(cct, 20) << __func__ << "(): auth registy supported: methods=" << methods << " modes=" << modes << dendl;
399
400 for (auto method : methods) {
401 if (!reg.is_secure_method(method)) {
402 ldout(cct, 20) << __func__ << "(): method " << method << " is insecure" << dendl;
403 return false;
404 }
405 }
406
407 for (auto mode : modes) {
408 if (!reg.is_secure_mode(mode)) {
409 ldout(cct, 20) << __func__ << "(): mode " << mode << " is insecure" << dendl;
410 return false;
411 }
412 }
413
414 return true;
415 }
416