From: Jason Dillaman Date: Tue, 4 Feb 2020 02:53:21 +0000 (-0500) Subject: librbd: expose mirror uuid via the API X-Git-Tag: v15.1.1~417^2~6 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=3ca9fe44e60e55854986f8532b8da29eaa33d9ff;p=ceph-ci.git librbd: expose mirror uuid via the API The mirror snapshot primary vs non-primary state can be determined by looking at the primary_mirror_uuid within the mirror snapshot namespace. Signed-off-by: Jason Dillaman --- diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index a0f727ef3f9..c4c8c5ddaef 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -498,6 +498,9 @@ CEPH_RBD_API int rbd_mirror_mode_get(rados_ioctx_t io_ctx, CEPH_RBD_API int rbd_mirror_mode_set(rados_ioctx_t io_ctx, rbd_mirror_mode_t mirror_mode); +CEPH_RBD_API int rbd_mirror_uuid_get(rados_ioctx_t io_ctx, + char *uuid, size_t *max_len); + CEPH_RBD_API int rbd_mirror_peer_bootstrap_create( rados_ioctx_t io_ctx, char *token, size_t *max_len); CEPH_RBD_API int rbd_mirror_peer_bootstrap_import( diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 7e72055b6b6..3fb8f7cda05 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -315,6 +315,8 @@ public: int mirror_mode_get(IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode); int mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode); + int mirror_uuid_get(IoCtx& io_ctx, std::string* mirror_uuid); + int mirror_peer_bootstrap_create(IoCtx& io_ctx, std::string* token); int mirror_peer_bootstrap_import(IoCtx& io_ctx, mirror_peer_direction_t direction, diff --git a/src/librbd/CMakeLists.txt b/src/librbd/CMakeLists.txt index 60920aa39d3..48419541dc0 100644 --- a/src/librbd/CMakeLists.txt +++ b/src/librbd/CMakeLists.txt @@ -103,6 +103,7 @@ set(librbd_internal_srcs mirror/EnableRequest.cc mirror/GetInfoRequest.cc mirror/GetStatusRequest.cc + mirror/GetUuidRequest.cc mirror/ImageRemoveRequest.cc mirror/ImageStateUpdateRequest.cc mirror/PromoteRequest.cc diff --git a/src/librbd/api/Mirror.cc b/src/librbd/api/Mirror.cc index 72a465d6d8a..3b1d47072ae 100644 --- a/src/librbd/api/Mirror.cc +++ b/src/librbd/api/Mirror.cc @@ -21,6 +21,7 @@ #include "librbd/mirror/EnableRequest.h" #include "librbd/mirror/GetInfoRequest.h" #include "librbd/mirror/GetStatusRequest.h" +#include "librbd/mirror/GetUuidRequest.h" #include "librbd/mirror/PromoteRequest.h" #include "librbd/mirror/Types.h" #include "librbd/MirroringWatcher.h" @@ -1097,6 +1098,35 @@ int Mirror::mode_set(librados::IoCtx& io_ctx, return 0; } +template +int Mirror::uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid) { + CephContext *cct = reinterpret_cast(io_ctx.cct()); + ldout(cct, 20) << dendl; + + C_SaferCond ctx; + uuid_get(io_ctx, mirror_uuid, &ctx); + int r = ctx.wait(); + if (r < 0) { + if (r != -ENOENT) { + lderr(cct) << "failed to retrieve mirroring uuid: " << cpp_strerror(r) + << dendl; + } + return r; + } + + return 0; +} + +template +void Mirror::uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid, + Context* on_finish) { + CephContext *cct = reinterpret_cast(io_ctx.cct()); + ldout(cct, 20) << dendl; + + auto req = mirror::GetUuidRequest::create(io_ctx, mirror_uuid, on_finish); + req->send(); +} + template int Mirror::peer_bootstrap_create(librados::IoCtx& io_ctx, std::string* token) { diff --git a/src/librbd/api/Mirror.h b/src/librbd/api/Mirror.h index fba6cba365d..b0dae99bc4a 100644 --- a/src/librbd/api/Mirror.h +++ b/src/librbd/api/Mirror.h @@ -32,6 +32,10 @@ struct Mirror { static int mode_get(librados::IoCtx& io_ctx, rbd_mirror_mode_t *mirror_mode); static int mode_set(librados::IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode); + static int uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid); + static void uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid, + Context* on_finish); + static int peer_bootstrap_create(librados::IoCtx& io_ctx, std::string* token); static int peer_bootstrap_import(librados::IoCtx& io_ctx, rbd_mirror_peer_direction_t direction, diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 07470045b65..28f00367d9d 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -994,6 +994,14 @@ namespace librbd { return librbd::api::Mirror<>::mode_get(io_ctx, mirror_mode); } + int RBD::mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode) { + return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode); + } + + int RBD::mirror_uuid_get(IoCtx& io_ctx, std::string* mirror_uuid) { + return librbd::api::Mirror<>::uuid_get(io_ctx, mirror_uuid); + } + int RBD::mirror_site_name_get(librados::Rados& rados, std::string* site_name) { return librbd::api::Mirror<>::site_name_get(rados, site_name); @@ -1004,10 +1012,6 @@ namespace librbd { return librbd::api::Mirror<>::site_name_set(rados, site_name); } - int RBD::mirror_mode_set(IoCtx& io_ctx, rbd_mirror_mode_t mirror_mode) { - return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode); - } - int RBD::mirror_peer_bootstrap_create(IoCtx& io_ctx, std::string* token) { return librbd::api::Mirror<>::peer_bootstrap_create(io_ctx, token); } @@ -3139,6 +3143,28 @@ extern "C" int rbd_mirror_mode_set(rados_ioctx_t p, return librbd::api::Mirror<>::mode_set(io_ctx, mirror_mode); } +extern "C" int rbd_mirror_uuid_get(rados_ioctx_t p, + char *mirror_uuid, size_t *max_len) { + librados::IoCtx io_ctx; + librados::IoCtx::from_rados_ioctx_t(p, io_ctx); + + std::string mirror_uuid_str; + int r = librbd::api::Mirror<>::uuid_get(io_ctx, &mirror_uuid_str); + if (r < 0) { + return r; + } + + auto total_len = mirror_uuid_str.size() + 1; + if (*max_len < total_len) { + *max_len = total_len; + return -ERANGE; + } + *max_len = total_len; + + strcpy(mirror_uuid, mirror_uuid_str.c_str()); + return 0; +} + extern "C" int rbd_mirror_peer_bootstrap_create(rados_ioctx_t p, char *token, size_t *max_len) { librados::IoCtx io_ctx; diff --git a/src/librbd/mirror/GetUuidRequest.cc b/src/librbd/mirror/GetUuidRequest.cc new file mode 100644 index 00000000000..f8209f90512 --- /dev/null +++ b/src/librbd/mirror/GetUuidRequest.cc @@ -0,0 +1,86 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "librbd/mirror/GetUuidRequest.h" +#include "common/dout.h" +#include "common/errno.h" +#include "cls/rbd/cls_rbd_client.h" +#include "librbd/ImageCtx.h" +#include "librbd/Utils.h" + +#define dout_subsys ceph_subsys_rbd + +#undef dout_prefix +#define dout_prefix *_dout << "librbd::mirror::GetUuidRequest: " \ + << this << " " << __func__ << ": " + +namespace librbd { +namespace mirror { + +using librbd::util::create_rados_callback; + +template +GetUuidRequest::GetUuidRequest( + librados::IoCtx& io_ctx, std::string* mirror_uuid, Context* on_finish) + : m_mirror_uuid(mirror_uuid), m_on_finish(on_finish), + m_cct(reinterpret_cast(io_ctx.cct())) { + m_io_ctx.dup(io_ctx); + m_io_ctx.set_namespace(""); +} + +template +void GetUuidRequest::send() { + get_mirror_uuid(); +} + +template +void GetUuidRequest::get_mirror_uuid() { + ldout(m_cct, 20) << dendl; + + librados::ObjectReadOperation op; + librbd::cls_client::mirror_uuid_get_start(&op); + + auto aio_comp = create_rados_callback< + GetUuidRequest, &GetUuidRequest::handle_get_mirror_uuid>(this); + int r = m_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op, &m_out_bl); + ceph_assert(r == 0); + aio_comp->release(); +} + +template +void GetUuidRequest::handle_get_mirror_uuid(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + if (r >= 0) { + auto it = m_out_bl.cbegin(); + r = librbd::cls_client::mirror_uuid_get_finish(&it, m_mirror_uuid); + if (r >= 0 && m_mirror_uuid->empty()) { + r = -ENOENT; + } + } + + if (r < 0) { + if (r == -ENOENT) { + ldout(m_cct, 5) << "mirror uuid missing" << dendl; + } else { + lderr(m_cct) << "failed to retrieve mirror uuid: " << cpp_strerror(r) + << dendl; + } + *m_mirror_uuid = ""; + } + + finish(r); +} + +template +void GetUuidRequest::finish(int r) { + ldout(m_cct, 20) << "r=" << r << dendl; + + m_on_finish->complete(r); + delete this; +} + +} // namespace mirror +} // namespace librbd + +template class librbd::mirror::GetUuidRequest; diff --git a/src/librbd/mirror/GetUuidRequest.h b/src/librbd/mirror/GetUuidRequest.h new file mode 100644 index 00000000000..73cc2d5b2c5 --- /dev/null +++ b/src/librbd/mirror/GetUuidRequest.h @@ -0,0 +1,69 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#ifndef CEPH_LIBRBD_MIRROR_GET_UUID_REQUEST_H +#define CEPH_LIBRBD_MIRROR_GET_UUID_REQUEST_H + +#include "include/buffer.h" +#include "include/rados/librados.hpp" +#include "cls/rbd/cls_rbd_types.h" + +#include +#include + +struct Context; + +namespace librbd { + +struct ImageCtx; + +namespace mirror { + +template +class GetUuidRequest { +public: + static GetUuidRequest *create(librados::IoCtx& io_ctx, + std::string* mirror_uuid, Context* on_finish) { + return new GetUuidRequest(io_ctx, mirror_uuid, on_finish); + } + + GetUuidRequest(librados::IoCtx& io_ctx, std::string* mirror_uuid, + Context* on_finish); + + void send(); + +private: + /** + * @verbatim + * + * + * | + * v + * GET_MIRROR_UUID + * | + * v + * + * + * @endverbatim + */ + + librados::IoCtx m_io_ctx; + std::string* m_mirror_uuid; + Context* m_on_finish; + + CephContext* m_cct; + + bufferlist m_out_bl; + + void get_mirror_uuid(); + void handle_get_mirror_uuid(int r); + + void finish(int r); +}; + +} // namespace mirror +} // namespace librbd + +extern template class librbd::mirror::GetUuidRequest; + +#endif // CEPH_LIBRBD_MIRROR_GET_UUID_REQUEST_H diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 2021d8abe2f..958f646045f 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -381,6 +381,9 @@ cdef extern from "rbd/librbd.h" nogil: int rbd_mirror_mode_get(rados_ioctx_t io, rbd_mirror_mode_t *mirror_mode) int rbd_mirror_mode_set(rados_ioctx_t io, rbd_mirror_mode_t mirror_mode) + int rbd_mirror_uuid_get(rados_ioctx_t io_ctx, char *mirror_uuid, + size_t *max_len) + int rbd_mirror_peer_bootstrap_create(rados_ioctx_t io_ctx, char *token, size_t *max_len) int rbd_mirror_peer_bootstrap_import( @@ -1863,6 +1866,31 @@ class RBD(object): if ret != 0: raise make_ex(ret, 'error setting mirror mode') + def mirror_uuid_get(self, ioctx): + """ + Get pool mirror uuid + + :param ioctx: determines which RADOS pool is read + :type ioctx: :class:`rados.Ioctx` + :returns: ste - pool mirror uuid + """ + cdef: + rados_ioctx_t _ioctx = convert_ioctx(ioctx) + char *_uuid = NULL + size_t _max_size = 512 + try: + while True: + _uuid = realloc_chk(_uuid, _max_size) + with nogil: + ret = rbd_mirror_uuid_get(_ioctx, _uuid, &_max_size) + if ret >= 0: + break + elif ret != -errno.ERANGE: + raise make_ex(ret, 'error retrieving mirror uuid') + return decode_cstr(_uuid) + finally: + free(_uuid) + def mirror_peer_bootstrap_create(self, ioctx): """ Creates a new RBD mirroring bootstrap token for an diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index 10707ea50ad..f09b2bc0761 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -1905,6 +1905,10 @@ class TestMirroring(object): remove_image() self.rbd.mirror_mode_set(ioctx, self.initial_mirror_mode) + def test_uuid(self): + mirror_uuid = self.rbd.mirror_uuid_get(ioctx) + assert(mirror_uuid) + def test_site_name(self): site_name = "us-west-1" self.rbd.mirror_site_name_set(rados, site_name)