]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
librbd: expose mirror uuid via the API
authorJason Dillaman <dillaman@redhat.com>
Tue, 4 Feb 2020 02:53:21 +0000 (21:53 -0500)
committerJason Dillaman <dillaman@redhat.com>
Thu, 13 Feb 2020 13:11:16 +0000 (08:11 -0500)
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 <dillaman@redhat.com>
src/include/rbd/librbd.h
src/include/rbd/librbd.hpp
src/librbd/CMakeLists.txt
src/librbd/api/Mirror.cc
src/librbd/api/Mirror.h
src/librbd/librbd.cc
src/librbd/mirror/GetUuidRequest.cc [new file with mode: 0644]
src/librbd/mirror/GetUuidRequest.h [new file with mode: 0644]
src/pybind/rbd/rbd.pyx
src/test/pybind/test_rbd.py

index a0f727ef3f95a4c23f6a0cfc9082c5aef1fecc94..c4c8c5ddaef10025e757cff648f31063e9848507 100644 (file)
@@ -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(
index 7e72055b6b650773d8dac00acd8805b788f14f0f..3fb8f7cda055753bb16ef3773a80f4376a5fb14c 100644 (file)
@@ -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,
index 60920aa39d3e6161d88ea3bb15fee7b5fc8933c2..48419541dc0ec078b6b4082f0280c5e42dbfe7bf 100644 (file)
@@ -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
index 72a465d6d8a894ce62399887c0b94e137ec7d21f..3b1d47072ae3d91921c47f48393fdbb1b51ecf2b 100644 (file)
@@ -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<I>::mode_set(librados::IoCtx& io_ctx,
   return 0;
 }
 
+template <typename I>
+int Mirror<I>::uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid) {
+  CephContext *cct = reinterpret_cast<CephContext *>(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 <typename I>
+void Mirror<I>::uuid_get(librados::IoCtx& io_ctx, std::string* mirror_uuid,
+                         Context* on_finish) {
+  CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+  ldout(cct, 20) << dendl;
+
+  auto req = mirror::GetUuidRequest<I>::create(io_ctx, mirror_uuid, on_finish);
+  req->send();
+}
+
 template <typename I>
 int Mirror<I>::peer_bootstrap_create(librados::IoCtx& io_ctx,
                                      std::string* token) {
index fba6cba365da56f02565d81dbe92dd0b74eabc88..b0dae99bc4a1e3e6e3ce94ac7d06b58ceb1c2498 100644 (file)
@@ -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,
index 07470045b65e69b677e4ae189de58ad6298a7989..28f00367d9d8291738f3f7cc399fe940c7ba4bff 100644 (file)
@@ -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 (file)
index 0000000..f8209f9
--- /dev/null
@@ -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 <typename I>
+GetUuidRequest<I>::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<CephContext*>(io_ctx.cct())) {
+  m_io_ctx.dup(io_ctx);
+  m_io_ctx.set_namespace("");
+}
+
+template <typename I>
+void GetUuidRequest<I>::send() {
+  get_mirror_uuid();
+}
+
+template <typename I>
+void GetUuidRequest<I>::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<I>, &GetUuidRequest<I>::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 <typename I>
+void GetUuidRequest<I>::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 <typename I>
+void GetUuidRequest<I>::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<librbd::ImageCtx>;
diff --git a/src/librbd/mirror/GetUuidRequest.h b/src/librbd/mirror/GetUuidRequest.h
new file mode 100644 (file)
index 0000000..73cc2d5
--- /dev/null
@@ -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 <string>
+#include <set>
+
+struct Context;
+
+namespace librbd {
+
+struct ImageCtx;
+
+namespace mirror {
+
+template <typename ImageCtxT = librbd::ImageCtx>
+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
+   *
+   * <start>
+   *    |
+   *    v
+   * GET_MIRROR_UUID
+   *    |
+   *    v
+   * <finish>
+   *
+   * @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<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_MIRROR_GET_UUID_REQUEST_H
index 2021d8abe2f833cf9bb54b92a22f8aa90d6b3be7..958f646045f665d3d1b2bc86deb800ea4f9f45da 100644 (file)
@@ -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 = <char *>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
index 10707ea50ad5695eebc3688bd426e5e1f67b1796..f09b2bc07612dd2a78910053dad05419f79f3e1a 100644 (file)
@@ -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)