diff options
Diffstat (limited to '')
-rw-r--r-- | src/rgw/services/svc_rados.cc | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/src/rgw/services/svc_rados.cc b/src/rgw/services/svc_rados.cc new file mode 100644 index 000000000..99f400f42 --- /dev/null +++ b/src/rgw/services/svc_rados.cc @@ -0,0 +1,445 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +#include "svc_rados.h" + +#include "include/rados/librados.hpp" +#include "common/errno.h" +#include "osd/osd_types.h" +#include "rgw_tools.h" +#include "rgw_cr_rados.h" + +#include "auth/AuthRegistry.h" + +#define dout_subsys ceph_subsys_rgw + +using namespace std; + +RGWSI_RADOS::RGWSI_RADOS(CephContext *cct) : RGWServiceInstance(cct) +{ +} + +RGWSI_RADOS::~RGWSI_RADOS() +{ +} + +int RGWSI_RADOS::do_start(optional_yield, const DoutPrefixProvider *dpp) +{ + int ret = rados.init_with_context(cct); + if (ret < 0) { + return ret; + } + ret = rados.connect(); + if (ret < 0) { + return ret; + } + + async_processor.reset(new RGWAsyncRadosProcessor(cct, cct->_conf->rgw_num_async_rados_threads)); + async_processor->start(); + + return 0; +} + +void RGWSI_RADOS::shutdown() +{ + if (async_processor) { + async_processor->stop(); + } + rados.shutdown(); +} + +void RGWSI_RADOS::stop_processor() +{ + if (async_processor) { + async_processor->stop(); + } +} + +librados::Rados* RGWSI_RADOS::get_rados_handle() +{ + return &rados; +} + +std::string RGWSI_RADOS::cluster_fsid() +{ + std::string fsid; + (void) get_rados_handle()->cluster_fsid(&fsid); + return fsid; +} + +uint64_t RGWSI_RADOS::instance_id() +{ + return get_rados_handle()->get_instance_id(); +} + +int RGWSI_RADOS::open_pool_ctx(const DoutPrefixProvider *dpp, const rgw_pool& pool, librados::IoCtx& io_ctx, + const OpenParams& params) +{ + return rgw_init_ioctx(dpp, get_rados_handle(), pool, io_ctx, + params.create, + params.mostly_omap); +} + +int RGWSI_RADOS::pool_iterate(const DoutPrefixProvider *dpp, + librados::IoCtx& io_ctx, + librados::NObjectIterator& iter, + uint32_t num, vector<rgw_bucket_dir_entry>& objs, + RGWAccessListFilter *filter, + bool *is_truncated) +{ + if (iter == io_ctx.nobjects_end()) + return -ENOENT; + + uint32_t i; + + for (i = 0; i < num && iter != io_ctx.nobjects_end(); ++i, ++iter) { + rgw_bucket_dir_entry e; + + string oid = iter->get_oid(); + ldpp_dout(dpp, 20) << "RGWRados::pool_iterate: got " << oid << dendl; + + // fill it in with initial values; we may correct later + if (filter && !filter->filter(oid, oid)) + continue; + + e.key = oid; + objs.push_back(e); + } + + if (is_truncated) + *is_truncated = (iter != io_ctx.nobjects_end()); + + return objs.size(); +} + +RGWSI_RADOS::Obj::Obj(Pool& pool, const string& oid) : rados_svc(pool.rados_svc) +{ + ref.pool = pool; + ref.obj = rgw_raw_obj(pool.get_pool(), oid); +} + +void RGWSI_RADOS::Obj::init(const rgw_raw_obj& obj) +{ + ref.pool = RGWSI_RADOS::Pool(rados_svc, obj.pool); + ref.obj = obj; +} + +int RGWSI_RADOS::Obj::open(const DoutPrefixProvider *dpp) +{ + int r = ref.pool.open(dpp); + if (r < 0) { + return r; + } + + ref.pool.ioctx().locator_set_key(ref.obj.loc); + + return 0; +} + +int RGWSI_RADOS::Obj::operate(const DoutPrefixProvider *dpp, librados::ObjectWriteOperation *op, + optional_yield y, int flags) +{ + return rgw_rados_operate(dpp, ref.pool.ioctx(), ref.obj.oid, op, y, flags); +} + +int RGWSI_RADOS::Obj::operate(const DoutPrefixProvider *dpp, librados::ObjectReadOperation *op, + bufferlist *pbl, optional_yield y, int flags) +{ + return rgw_rados_operate(dpp, ref.pool.ioctx(), ref.obj.oid, op, pbl, y, flags); +} + +int RGWSI_RADOS::Obj::aio_operate(librados::AioCompletion *c, librados::ObjectWriteOperation *op) +{ + return ref.pool.ioctx().aio_operate(ref.obj.oid, c, op); +} + +int RGWSI_RADOS::Obj::aio_operate(librados::AioCompletion *c, librados::ObjectReadOperation *op, + bufferlist *pbl) +{ + return ref.pool.ioctx().aio_operate(ref.obj.oid, c, op, pbl); +} + +int RGWSI_RADOS::Obj::watch(uint64_t *handle, librados::WatchCtx2 *ctx) +{ + return ref.pool.ioctx().watch2(ref.obj.oid, handle, ctx); +} + +int RGWSI_RADOS::Obj::aio_watch(librados::AioCompletion *c, uint64_t *handle, librados::WatchCtx2 *ctx) +{ + return ref.pool.ioctx().aio_watch(ref.obj.oid, c, handle, ctx); +} + +int RGWSI_RADOS::Obj::unwatch(uint64_t handle) +{ + return ref.pool.ioctx().unwatch2(handle); +} + +int RGWSI_RADOS::Obj::notify(const DoutPrefixProvider *dpp, bufferlist& bl, uint64_t timeout_ms, + bufferlist *pbl, optional_yield y) +{ + return rgw_rados_notify(dpp, ref.pool.ioctx(), ref.obj.oid, bl, timeout_ms, pbl, y); +} + +void RGWSI_RADOS::Obj::notify_ack(uint64_t notify_id, + uint64_t cookie, + bufferlist& bl) +{ + ref.pool.ioctx().notify_ack(ref.obj.oid, notify_id, cookie, bl); +} + +uint64_t RGWSI_RADOS::Obj::get_last_version() +{ + return ref.pool.ioctx().get_last_version(); +} + +int RGWSI_RADOS::Pool::create(const DoutPrefixProvider *dpp) +{ + librados::Rados *rad = rados_svc->get_rados_handle(); + int r = rad->pool_create(pool.name.c_str()); + if (r < 0) { + ldpp_dout(dpp, 0) << "WARNING: pool_create returned " << r << dendl; + return r; + } + librados::IoCtx io_ctx; + r = rad->ioctx_create(pool.name.c_str(), io_ctx); + if (r < 0) { + ldpp_dout(dpp, 0) << "WARNING: ioctx_create returned " << r << dendl; + return r; + } + r = io_ctx.application_enable(pg_pool_t::APPLICATION_NAME_RGW, false); + if (r < 0) { + ldpp_dout(dpp, 0) << "WARNING: application_enable returned " << r << dendl; + return r; + } + return 0; +} + +int RGWSI_RADOS::Pool::create(const DoutPrefixProvider *dpp, const vector<rgw_pool>& pools, vector<int> *retcodes) +{ + vector<librados::PoolAsyncCompletion *> completions; + vector<int> rets; + + librados::Rados *rad = rados_svc->get_rados_handle(); + for (auto iter = pools.begin(); iter != pools.end(); ++iter) { + librados::PoolAsyncCompletion *c = librados::Rados::pool_async_create_completion(); + completions.push_back(c); + auto& pool = *iter; + int ret = rad->pool_create_async(pool.name.c_str(), c); + rets.push_back(ret); + } + + vector<int>::iterator riter; + vector<librados::PoolAsyncCompletion *>::iterator citer; + + bool error = false; + ceph_assert(rets.size() == completions.size()); + for (riter = rets.begin(), citer = completions.begin(); riter != rets.end(); ++riter, ++citer) { + int r = *riter; + librados::PoolAsyncCompletion *c = *citer; + if (r == 0) { + c->wait(); + r = c->get_return_value(); + if (r < 0) { + ldpp_dout(dpp, 0) << "WARNING: async pool_create returned " << r << dendl; + error = true; + } + } + c->release(); + retcodes->push_back(r); + } + if (error) { + return 0; + } + + std::vector<librados::IoCtx> io_ctxs; + retcodes->clear(); + for (auto pool : pools) { + io_ctxs.emplace_back(); + int ret = rad->ioctx_create(pool.name.c_str(), io_ctxs.back()); + if (ret < 0) { + ldpp_dout(dpp, 0) << "WARNING: ioctx_create returned " << ret << dendl; + error = true; + } + retcodes->push_back(ret); + } + if (error) { + return 0; + } + + completions.clear(); + for (auto &io_ctx : io_ctxs) { + librados::PoolAsyncCompletion *c = + librados::Rados::pool_async_create_completion(); + completions.push_back(c); + int ret = io_ctx.application_enable_async(pg_pool_t::APPLICATION_NAME_RGW, + false, c); + ceph_assert(ret == 0); + } + + retcodes->clear(); + for (auto c : completions) { + c->wait(); + int ret = c->get_return_value(); + if (ret == -EOPNOTSUPP) { + ret = 0; + } else if (ret < 0) { + ldpp_dout(dpp, 0) << "WARNING: async application_enable returned " << ret + << dendl; + error = true; + } + c->release(); + retcodes->push_back(ret); + } + return 0; +} + +int RGWSI_RADOS::Pool::lookup() +{ + librados::Rados *rad = rados_svc->get_rados_handle(); + int ret = rad->pool_lookup(pool.name.c_str()); + if (ret < 0) { + return ret; + } + + return 0; +} + +int RGWSI_RADOS::Pool::open(const DoutPrefixProvider *dpp, const OpenParams& params) +{ + return rados_svc->open_pool_ctx(dpp, pool, state.ioctx, params); +} + +int RGWSI_RADOS::Pool::List::init(const DoutPrefixProvider *dpp, const string& marker, RGWAccessListFilter *filter) +{ + if (ctx.initialized) { + return -EINVAL; + } + + if (!pool) { + return -EINVAL; + } + + int r = pool->rados_svc->open_pool_ctx(dpp, pool->pool, ctx.ioctx); + if (r < 0) { + return r; + } + + librados::ObjectCursor oc; + if (!oc.from_str(marker)) { + ldpp_dout(dpp, 10) << "failed to parse cursor: " << marker << dendl; + return -EINVAL; + } + + try { + ctx.iter = ctx.ioctx.nobjects_begin(oc); + ctx.filter = filter; + ctx.initialized = true; + return 0; + } catch (const std::system_error& e) { + r = -e.code().value(); + ldpp_dout(dpp, 10) << "nobjects_begin threw " << e.what() + << ", returning " << r << dendl; + return r; + } catch (const std::exception& e) { + ldpp_dout(dpp, 10) << "nobjects_begin threw " << e.what() + << ", returning -5" << dendl; + return -EIO; + } +} + +int RGWSI_RADOS::Pool::List::get_next(const DoutPrefixProvider *dpp, + int max, + std::vector<string> *oids, + bool *is_truncated) +{ + if (!ctx.initialized) { + return -EINVAL; + } + vector<rgw_bucket_dir_entry> objs; + int r = pool->rados_svc->pool_iterate(dpp, ctx.ioctx, ctx.iter, max, objs, ctx.filter, is_truncated); + if (r < 0) { + if(r != -ENOENT) { + ldpp_dout(dpp, 10) << "failed to list objects pool_iterate returned r=" << r << dendl; + } + return r; + } + + for (auto& o : objs) { + oids->push_back(o.key.name); + } + + return oids->size(); +} + +RGWSI_RADOS::Obj RGWSI_RADOS::Handle::obj(const rgw_raw_obj& o) +{ + return RGWSI_RADOS::Obj(rados_svc, o); +} +int RGWSI_RADOS::Handle::watch_flush() +{ + librados::Rados *rad = rados_svc->get_rados_handle(); + return rad->watch_flush(); +} + +int RGWSI_RADOS::Handle::mon_command(std::string cmd, + const bufferlist& inbl, + bufferlist *outbl, + std::string *outs) +{ + librados::Rados *rad = rados_svc->get_rados_handle(); + return rad->mon_command(cmd, inbl, outbl, outs); +} + +int RGWSI_RADOS::Pool::List::get_marker(string *marker) +{ + if (!ctx.initialized) { + return -EINVAL; + } + + *marker = ctx.iter.get_cursor().to_str(); + return 0; +} + +int RGWSI_RADOS::clog_warn(const string& msg) +{ + string cmd = + "{" + "\"prefix\": \"log\", " + "\"level\": \"warn\", " + "\"logtext\": [\"" + msg + "\"]" + "}"; + + bufferlist inbl; + auto h = handle(); + return h.mon_command(cmd, inbl, nullptr, nullptr); +} + +bool RGWSI_RADOS::check_secure_mon_conn(const DoutPrefixProvider *dpp) const +{ + AuthRegistry reg(cct); + + reg.refresh_config(); + + std::vector<uint32_t> methods; + std::vector<uint32_t> modes; + + reg.get_supported_methods(CEPH_ENTITY_TYPE_MON, &methods, &modes); + ldpp_dout(dpp, 20) << __func__ << "(): auth registy supported: methods=" << methods << " modes=" << modes << dendl; + + for (auto method : methods) { + if (!reg.is_secure_method(method)) { + ldpp_dout(dpp, 20) << __func__ << "(): method " << method << " is insecure" << dendl; + return false; + } + } + + for (auto mode : modes) { + if (!reg.is_secure_mode(mode)) { + ldpp_dout(dpp, 20) << __func__ << "(): mode " << mode << " is insecure" << dendl; + return false; + } + } + + return true; +} + |