From f91f13c2aa4580f60db3bd5c4568ce3d0bcc45c8 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 3 Feb 2020 15:09:28 -0500 Subject: [PATCH] librbd: collapse API mirror primary/non-primary namespaces to single type Eventually we will want to be able to chain multiple peers together. In order to avoid special logic for syncing non-primary snapshots from a peer, just treat all mirror snapshots the same. This also clears some confusion for how to handle demoted snapshots since otherwise it would involve creating a primary-snapshot on the non-primary image before the image was fully synced. Finally, the copied flag was renamed to completed since we should eventually only set this to true on primary snapshots after the image state has been created. Signed-off-by: Jason Dillaman --- src/include/rbd/librbd.h | 40 ++++----- src/include/rbd/librbd.hpp | 18 ++-- src/librbd/api/Snapshot.cc | 65 +++++---------- src/librbd/api/Snapshot.h | 8 +- src/librbd/librbd.cc | 81 ++++-------------- src/pybind/rbd/rbd.pyx | 123 ++++++++++------------------ src/test/librbd/test_mirroring.cc | 36 ++++---- src/test/pybind/test_rbd.py | 36 ++++---- src/tools/rbd/action/MirrorImage.cc | 29 ++++--- src/tools/rbd/action/Snap.cc | 94 +++++++++++---------- 10 files changed, 216 insertions(+), 314 deletions(-) diff --git a/src/include/rbd/librbd.h b/src/include/rbd/librbd.h index c4c8c5ddaef..25068dbf4e5 100644 --- a/src/include/rbd/librbd.h +++ b/src/include/rbd/librbd.h @@ -75,11 +75,10 @@ typedef int (*librbd_progress_fn_t)(uint64_t offset, uint64_t total, void *ptr); typedef void (*rbd_update_callback_t)(void *arg); typedef enum { - RBD_SNAP_NAMESPACE_TYPE_USER = 0, - RBD_SNAP_NAMESPACE_TYPE_GROUP = 1, - RBD_SNAP_NAMESPACE_TYPE_TRASH = 2, - RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY = 3, - RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY = 4, + RBD_SNAP_NAMESPACE_TYPE_USER = 0, + RBD_SNAP_NAMESPACE_TYPE_GROUP = 1, + RBD_SNAP_NAMESPACE_TYPE_TRASH = 2, + RBD_SNAP_NAMESPACE_TYPE_MIRROR = 3, } rbd_snap_namespace_type_t; typedef struct { @@ -254,18 +253,22 @@ typedef struct { char *group_snap_name; } rbd_snap_group_namespace_t; +typedef enum { + RBD_SNAP_MIRROR_STATE_PRIMARY, + RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED, + RBD_SNAP_MIRROR_STATE_NON_PRIMARY, + RBD_SNAP_MIRROR_STATE_NON_PRIMARY_DEMOTED +} rbd_snap_mirror_state_t; + typedef struct { - bool demoted; + rbd_snap_mirror_state_t state; size_t mirror_peer_uuids_count; char *mirror_peer_uuids; -} rbd_snap_mirror_primary_namespace_t; - -typedef struct { + bool complete; char *primary_mirror_uuid; uint64_t primary_snap_id; - bool copied; uint64_t last_copied_object_number; -} rbd_snap_mirror_non_primary_namespace_t; +} rbd_snap_mirror_namespace_t; typedef enum { RBD_LOCK_MODE_EXCLUSIVE = 0, @@ -857,18 +860,11 @@ CEPH_RBD_API int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id, char* original_name, size_t max_length); -CEPH_RBD_API int rbd_snap_get_mirror_primary_namespace( - rbd_image_t image, uint64_t snap_id, - rbd_snap_mirror_primary_namespace_t *mirror_snap, size_t mirror_snap_size); -CEPH_RBD_API int rbd_snap_mirror_primary_namespace_cleanup( - rbd_snap_mirror_primary_namespace_t *mirror_snap, size_t mirror_snap_size); -CEPH_RBD_API int rbd_snap_get_mirror_non_primary_namespace( +CEPH_RBD_API int rbd_snap_get_mirror_namespace( rbd_image_t image, uint64_t snap_id, - rbd_snap_mirror_non_primary_namespace_t *mirror_snap, - size_t mirror_snap_size); -CEPH_RBD_API int rbd_snap_mirror_non_primary_namespace_cleanup( - rbd_snap_mirror_non_primary_namespace_t *mirror_snap, - size_t mirror_snap_size); + rbd_snap_mirror_namespace_t *mirror_snap, size_t mirror_snap_size); +CEPH_RBD_API int rbd_snap_mirror_namespace_cleanup( + rbd_snap_mirror_namespace_t *mirror_snap, size_t mirror_snap_size); CEPH_RBD_API int rbd_flatten(rbd_image_t image); diff --git a/src/include/rbd/librbd.hpp b/src/include/rbd/librbd.hpp index 3fb8f7cda05..ca2d7449baf 100644 --- a/src/include/rbd/librbd.hpp +++ b/src/include/rbd/librbd.hpp @@ -73,17 +73,16 @@ namespace librbd { std::string group_snap_name; } snap_group_namespace_t; - typedef struct { - bool demoted; - std::set mirror_peer_uuids; - } snap_mirror_primary_namespace_t; + typedef rbd_snap_mirror_state_t snap_mirror_state_t; typedef struct { + snap_mirror_state_t state; + std::set mirror_peer_uuids; + bool complete; std::string primary_mirror_uuid; uint64_t primary_snap_id; - bool copied; uint64_t last_copied_object_number; - } snap_mirror_non_primary_namespace_t; + } snap_mirror_namespace_t; typedef struct { std::string client; @@ -621,11 +620,8 @@ public: snap_group_namespace_t *group_namespace, size_t snap_group_namespace_size); int snap_get_trash_namespace(uint64_t snap_id, std::string* original_name); - int snap_get_mirror_primary_namespace( - uint64_t snap_id, snap_mirror_primary_namespace_t *mirror_namespace, - size_t snap_mirror_namespace_size); - int snap_get_mirror_non_primary_namespace( - uint64_t snap_id, snap_mirror_non_primary_namespace_t *mirror_namespace, + int snap_get_mirror_namespace( + uint64_t snap_id, snap_mirror_namespace_t *mirror_namespace, size_t snap_mirror_namespace_size); /* I/O */ diff --git a/src/librbd/api/Snapshot.cc b/src/librbd/api/Snapshot.cc index 20f4bf8c404..d13ac775816 100644 --- a/src/librbd/api/Snapshot.cc +++ b/src/librbd/api/Snapshot.cc @@ -10,6 +10,7 @@ #include "librbd/Operations.h" #include "librbd/Utils.h" #include "librbd/api/Image.h" +#include "librbd/api/Mirror.h" #include #include "include/Context.h" #include "common/Cond.h" @@ -99,12 +100,14 @@ public: } }; -class GetMirrorPrimaryVisitor : public boost::static_visitor { +class GetMirrorVisitor : public boost::static_visitor { public: - snap_mirror_primary_namespace_t *mirror_snap; + snap_mirror_namespace_t *mirror_snap; + std::string mirror_uuid; - explicit GetMirrorPrimaryVisitor(snap_mirror_primary_namespace_t *mirror_snap) - : mirror_snap(mirror_snap) { + explicit GetMirrorVisitor(snap_mirror_namespace_t *mirror_snap, + const std::string& mirror_uuid) + : mirror_snap(mirror_snap), mirror_uuid(mirror_uuid) { } template @@ -114,31 +117,22 @@ public: inline int operator()( const cls::rbd::MirrorPrimarySnapshotNamespace& snap_namespace) { - mirror_snap->demoted = snap_namespace.demoted; + if (snap_namespace.demoted) { + mirror_snap->state = RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED; + } else { + mirror_snap->state = RBD_SNAP_MIRROR_STATE_PRIMARY; + } mirror_snap->mirror_peer_uuids = snap_namespace.mirror_peer_uuids; + mirror_snap->complete = true; return 0; } -}; - -class GetMirrorNonPrimaryVisitor : public boost::static_visitor { -public: - snap_mirror_non_primary_namespace_t *mirror_snap; - - explicit GetMirrorNonPrimaryVisitor( - snap_mirror_non_primary_namespace_t *mirror_snap) - : mirror_snap(mirror_snap) { - } - - template - inline int operator()(const T&) const { - return -EINVAL; - } inline int operator()( const cls::rbd::MirrorNonPrimarySnapshotNamespace& snap_namespace) { + mirror_snap->state = RBD_SNAP_MIRROR_STATE_NON_PRIMARY; mirror_snap->primary_mirror_uuid = snap_namespace.primary_mirror_uuid; mirror_snap->primary_snap_id = snap_namespace.primary_snap_id; - mirror_snap->copied = snap_namespace.copied; + mirror_snap->complete = snap_namespace.copied; mirror_snap->last_copied_object_number = snap_namespace.last_copied_object_number; return 0; @@ -194,8 +188,8 @@ int Snapshot::get_trash_namespace(I *ictx, uint64_t snap_id, } template -int Snapshot::get_mirror_primary_namespace( - I *ictx, uint64_t snap_id, snap_mirror_primary_namespace_t *mirror_snap) { +int Snapshot::get_mirror_namespace( + I *ictx, uint64_t snap_id, snap_mirror_namespace_t *mirror_snap) { int r = ictx->state->refresh_if_required(); if (r < 0) { return r; @@ -207,31 +201,14 @@ int Snapshot::get_mirror_primary_namespace( return -ENOENT; } - auto gmv = GetMirrorPrimaryVisitor(mirror_snap); - r = boost::apply_visitor(gmv, snap_info->snap_namespace); + // TODO temporary + std::string mirror_uuid; + r = Mirror::uuid_get(ictx->md_ctx, &mirror_uuid); if (r < 0) { return r; } - return 0; -} - -template -int Snapshot::get_mirror_non_primary_namespace( - I *ictx, uint64_t snap_id, - snap_mirror_non_primary_namespace_t *mirror_snap) { - int r = ictx->state->refresh_if_required(); - if (r < 0) { - return r; - } - - std::shared_lock image_locker{ictx->image_lock}; - auto snap_info = ictx->get_snap_info(snap_id); - if (snap_info == nullptr) { - return -ENOENT; - } - - auto gmv = GetMirrorNonPrimaryVisitor(mirror_snap); + auto gmv = GetMirrorVisitor(mirror_snap, mirror_uuid); r = boost::apply_visitor(gmv, snap_info->snap_namespace); if (r < 0) { return r; diff --git a/src/librbd/api/Snapshot.h b/src/librbd/api/Snapshot.h index a791a481a2f..ce5252c78d8 100644 --- a/src/librbd/api/Snapshot.h +++ b/src/librbd/api/Snapshot.h @@ -23,13 +23,9 @@ struct Snapshot { static int get_trash_namespace(ImageCtxT *ictx, uint64_t snap_id, std::string *original_name); - static int get_mirror_primary_namespace( + static int get_mirror_namespace( ImageCtxT *ictx, uint64_t snap_id, - snap_mirror_primary_namespace_t *mirror_snap); - - static int get_mirror_non_primary_namespace( - ImageCtxT *ictx, uint64_t snap_id, - snap_mirror_non_primary_namespace_t *mirror_snap); + snap_mirror_namespace_t *mirror_snap); static int get_namespace_type(ImageCtxT *ictx, uint64_t snap_id, snap_namespace_type_t *namespace_type); diff --git a/src/librbd/librbd.cc b/src/librbd/librbd.cc index 28f00367d9d..ca1009e0ee5 100644 --- a/src/librbd/librbd.cc +++ b/src/librbd/librbd.cc @@ -2347,30 +2347,16 @@ namespace librbd { original_name); } - int Image::snap_get_mirror_primary_namespace( - uint64_t snap_id, snap_mirror_primary_namespace_t *mirror_snap, + int Image::snap_get_mirror_namespace( + uint64_t snap_id, snap_mirror_namespace_t *mirror_snap, size_t mirror_snap_size) { ImageCtx *ictx = (ImageCtx *)ctx; - if (mirror_snap_size != sizeof(snap_mirror_primary_namespace_t)) { + if (mirror_snap_size != sizeof(snap_mirror_namespace_t)) { return -ERANGE; } - int r = librbd::api::Snapshot<>::get_mirror_primary_namespace( - ictx, snap_id, mirror_snap); - return r; - } - - int Image::snap_get_mirror_non_primary_namespace( - uint64_t snap_id, snap_mirror_non_primary_namespace_t *mirror_snap, - size_t mirror_snap_size) { - ImageCtx *ictx = (ImageCtx *)ctx; - - if (mirror_snap_size != sizeof(snap_mirror_non_primary_namespace_t)) { - return -ERANGE; - } - - int r = librbd::api::Snapshot<>::get_mirror_non_primary_namespace( + int r = librbd::api::Snapshot<>::get_mirror_namespace( ictx, snap_id, mirror_snap); return r; } @@ -6985,24 +6971,27 @@ extern "C" int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id, return 0; } -extern "C" int rbd_snap_get_mirror_primary_namespace( +extern "C" int rbd_snap_get_mirror_namespace( rbd_image_t image, uint64_t snap_id, - rbd_snap_mirror_primary_namespace_t *mirror_snap, + rbd_snap_mirror_namespace_t *mirror_snap, size_t mirror_snap_size) { librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; - if (mirror_snap_size != sizeof(rbd_snap_mirror_primary_namespace_t)) { + if (mirror_snap_size != sizeof(rbd_snap_mirror_namespace_t)) { return -ERANGE; } - librbd::snap_mirror_primary_namespace_t mirror_namespace; - int r = librbd::api::Snapshot<>::get_mirror_primary_namespace( + librbd::snap_mirror_namespace_t mirror_namespace; + int r = librbd::api::Snapshot<>::get_mirror_namespace( ictx, snap_id, &mirror_namespace); if (r < 0) { return r; } - mirror_snap->demoted = mirror_namespace.demoted; + mirror_snap->state = mirror_namespace.state; + mirror_snap->primary_mirror_uuid = + strdup(mirror_namespace.primary_mirror_uuid.c_str()); + mirror_snap->primary_snap_id = mirror_namespace.primary_snap_id; mirror_snap->mirror_peer_uuids_count = mirror_namespace.mirror_peer_uuids.size(); size_t len = 0; @@ -7015,56 +7004,22 @@ extern "C" int rbd_snap_get_mirror_primary_namespace( strncpy(p, peer.c_str(), peer.size() + 1); p += peer.size() + 1; } - - return 0; -} - -extern "C" int rbd_snap_mirror_primary_namespace_cleanup( - rbd_snap_mirror_primary_namespace_t *mirror_snap, - size_t mirror_snap_size) { - if (mirror_snap_size != sizeof(rbd_snap_mirror_primary_namespace_t)) { - return -ERANGE; - } - - free(mirror_snap->mirror_peer_uuids); - return 0; -} - -extern "C" int rbd_snap_get_mirror_non_primary_namespace( - rbd_image_t image, uint64_t snap_id, - rbd_snap_mirror_non_primary_namespace_t *mirror_snap, - size_t mirror_snap_size) { - librbd::ImageCtx *ictx = (librbd::ImageCtx *)image; - - if (mirror_snap_size != sizeof(rbd_snap_mirror_non_primary_namespace_t)) { - return -ERANGE; - } - - librbd::snap_mirror_non_primary_namespace_t mirror_namespace; - int r = librbd::api::Snapshot<>::get_mirror_non_primary_namespace( - ictx, snap_id, &mirror_namespace); - if (r < 0) { - return r; - } - - mirror_snap->primary_mirror_uuid = - strdup(mirror_namespace.primary_mirror_uuid.c_str()); - mirror_snap->primary_snap_id = mirror_namespace.primary_snap_id; - mirror_snap->copied = mirror_namespace.copied; + mirror_snap->complete = mirror_namespace.complete; mirror_snap->last_copied_object_number = mirror_namespace.last_copied_object_number; return 0; } -extern "C" int rbd_snap_mirror_non_primary_namespace_cleanup( - rbd_snap_mirror_non_primary_namespace_t *mirror_snap, +extern "C" int rbd_snap_mirror_namespace_cleanup( + rbd_snap_mirror_namespace_t *mirror_snap, size_t mirror_snap_size) { - if (mirror_snap_size != sizeof(rbd_snap_mirror_non_primary_namespace_t)) { + if (mirror_snap_size != sizeof(rbd_snap_mirror_namespace_t)) { return -ERANGE; } free(mirror_snap->primary_mirror_uuid); + free(mirror_snap->mirror_peer_uuids); return 0; } diff --git a/src/pybind/rbd/rbd.pyx b/src/pybind/rbd/rbd.pyx index 958f646045f..34e1d92cbaa 100644 --- a/src/pybind/rbd/rbd.pyx +++ b/src/pybind/rbd/rbd.pyx @@ -127,15 +127,19 @@ cdef extern from "rbd/librbd.h" nogil: char *group_name char *group_snap_name - ctypedef struct rbd_snap_mirror_primary_namespace_t: - bint demoted + ctypedef enum rbd_snap_mirror_state_t: + _RBD_SNAP_MIRROR_STATE_PRIMARY "RBD_SNAP_MIRROR_STATE_PRIMARY" + _RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED "RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED" + _RBD_SNAP_MIRROR_STATE_NON_PRIMARY "RBD_SNAP_MIRROR_STATE_NON_PRIMARY" + _RBD_SNAP_MIRROR_STATE_NON_PRIMARY_DEMOTED "RBD_SNAP_MIRROR_STATE_NON_PRIMARY_DEMOTED" + + ctypedef struct rbd_snap_mirror_namespace_t: + rbd_snap_mirror_state_t state size_t mirror_peer_uuids_count char *mirror_peer_uuids - - ctypedef struct rbd_snap_mirror_non_primary_namespace_t: + bint complete char *primary_mirror_uuid uint64_t primary_snap_id - bint copied uint64_t last_copied_object_number ctypedef struct rbd_group_info_t: @@ -158,8 +162,7 @@ cdef extern from "rbd/librbd.h" nogil: _RBD_SNAP_NAMESPACE_TYPE_USER "RBD_SNAP_NAMESPACE_TYPE_USER" _RBD_SNAP_NAMESPACE_TYPE_GROUP "RBD_SNAP_NAMESPACE_TYPE_GROUP" _RBD_SNAP_NAMESPACE_TYPE_TRASH "RBD_SNAP_NAMESPACE_TYPE_TRASH" - _RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY "RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY" - _RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY "RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY" + _RBD_SNAP_NAMESPACE_TYPE_MIRROR "RBD_SNAP_NAMESPACE_TYPE_MIRROR" ctypedef struct rbd_snap_spec_t: uint64_t id @@ -535,20 +538,13 @@ cdef extern from "rbd/librbd.h" nogil: size_t snap_group_namespace_size) int rbd_snap_get_trash_namespace(rbd_image_t image, uint64_t snap_id, char *original_name, size_t max_length) - int rbd_snap_get_mirror_primary_namespace( - rbd_image_t image, uint64_t snap_id, - rbd_snap_mirror_primary_namespace_t *mirror_ns, - size_t snap_mirror_primary_namespace_size) - void rbd_snap_mirror_primary_namespace_cleanup( - rbd_snap_mirror_primary_namespace_t *mirror_ns, - size_t snap_mirror_primary_namespace_size) - int rbd_snap_get_mirror_non_primary_namespace( + int rbd_snap_get_mirror_namespace( rbd_image_t image, uint64_t snap_id, - rbd_snap_mirror_non_primary_namespace_t *mirror_ns, - size_t snap_mirror_non_primary_namespace_size) - void rbd_snap_mirror_non_primary_namespace_cleanup( - rbd_snap_mirror_non_primary_namespace_t *mirror_ns, - size_t snap_mirror_non_primary_namespace_size) + rbd_snap_mirror_namespace_t *mirror_ns, + size_t snap_mirror_namespace_size) + void rbd_snap_mirror_namespace_cleanup( + rbd_snap_mirror_namespace_t *mirror_ns, + size_t snap_mirror_namespace_size) int rbd_flatten_with_progress(rbd_image_t image, librbd_progress_fn_t cb, void *cbdata) @@ -769,8 +765,12 @@ RBD_IMAGE_OPTION_DATA_POOL = _RBD_IMAGE_OPTION_DATA_POOL RBD_SNAP_NAMESPACE_TYPE_USER = _RBD_SNAP_NAMESPACE_TYPE_USER RBD_SNAP_NAMESPACE_TYPE_GROUP = _RBD_SNAP_NAMESPACE_TYPE_GROUP RBD_SNAP_NAMESPACE_TYPE_TRASH = _RBD_SNAP_NAMESPACE_TYPE_TRASH -RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY = _RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY -RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY = _RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY +RBD_SNAP_NAMESPACE_TYPE_MIRROR = _RBD_SNAP_NAMESPACE_TYPE_MIRROR + +RBD_SNAP_MIRROR_STATE_PRIMARY = _RBD_SNAP_MIRROR_STATE_PRIMARY +RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED = _RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED +RBD_SNAP_MIRROR_STATE_NON_PRIMARY = _RBD_SNAP_MIRROR_STATE_NON_PRIMARY +RBD_SNAP_MIRROR_STATE_NON_PRIMARY_DEMOTED = _RBD_SNAP_MIRROR_STATE_NON_PRIMARY_DEMOTED RBD_GROUP_IMAGE_STATE_ATTACHED = _RBD_GROUP_IMAGE_STATE_ATTACHED RBD_GROUP_IMAGE_STATE_INCOMPLETE = _RBD_GROUP_IMAGE_STATE_INCOMPLETE @@ -5264,26 +5264,34 @@ written." % (self.name, ret, length)) finally: free(_name) - def snap_get_mirror_primary_namespace(self, snap_id): + def snap_get_mirror_namespace(self, snap_id): """ - get the mirror primary namespace details. + get the mirror namespace details. :param snap_id: the snapshot id of the mirror snapshot :type key: int :returns: dict - contains the following keys: - * ``demoted`` (bool) - True if snapshot is in demoted state + * ``state`` (int) - the snapshot state * ``mirror_peer_uuids`` (list) - mirror peer uuids + + * ``complete`` (bool) - True if snapshot is complete + + * ``primary_mirror_uuid`` (str) - primary mirror uuid + + * ``primary_snap_id`` (int) - primary snapshot Id + + * ``last_copied_object_number`` (int) - last copied object number """ cdef: - rbd_snap_mirror_primary_namespace_t sn + rbd_snap_mirror_namespace_t sn uint64_t _snap_id = snap_id with nogil: - ret = rbd_snap_get_mirror_primary_namespace( + ret = rbd_snap_get_mirror_namespace( self.image, _snap_id, &sn, - sizeof(rbd_snap_mirror_primary_namespace_t)) + sizeof(rbd_snap_mirror_namespace_t)) if ret != 0: - raise make_ex(ret, 'error getting snapshot mirror primary ' + raise make_ex(ret, 'error getting snapshot mirror ' 'namespace for image: %s, snap_id: %d' % (self.name, snap_id)) uuids = [] @@ -5293,47 +5301,15 @@ written." % (self.name, ret, length)) uuids.append(uuid) p += len(uuid) + 1 info = { - 'demoted' : sn.demoted, + 'state' : sn.state, 'mirror_peer_uuids' : uuids, - } - rbd_snap_mirror_primary_namespace_cleanup( - &sn, sizeof(rbd_snap_mirror_primary_namespace_t)) - return info - - def snap_get_mirror_non_primary_namespace(self, snap_id): - """ - get the mirror non-primary namespace details. - :param snap_id: the snapshot id of the mirror snapshot - :type key: int - :returns: dict - contains the following keys: - - * ``primary_mirror_uuid`` (str) - primary mirror uuid - - * ``primary_snap_id`` (int) - primary snapshot Id - - * ``copied`` (bool) - True if snapsho is copied - - * ``last_copied_object_number`` (int) - last copied object number - """ - cdef: - rbd_snap_mirror_non_primary_namespace_t sn - uint64_t _snap_id = snap_id - with nogil: - ret = rbd_snap_get_mirror_non_primary_namespace( - self.image, _snap_id, &sn, - sizeof(rbd_snap_mirror_non_primary_namespace_t)) - if ret != 0: - raise make_ex(ret, 'error getting snapshot mirror non-primary ' - 'namespace for image: %s, snap_id: %d' % - (self.name, snap_id)) - info = { + 'complete' : sn.complete, 'primary_mirror_uuid' : decode_cstr(sn.primary_mirror_uuid), 'primary_snap_id' : sn.primary_snap_id, - 'copied' : sn.copied, 'last_copied_object_number' : sn.last_copied_object_number, } - rbd_snap_mirror_non_primary_namespace_cleanup( - &sn, sizeof(rbd_snap_mirror_non_primary_namespace_t)) + rbd_snap_mirror_namespace_cleanup( + &sn, sizeof(rbd_snap_mirror_namespace_t)) return info @@ -5518,9 +5494,7 @@ cdef class SnapIterator(object): * ``trash`` (dict) - optional for trash namespace snapshots - * ``mirror_primary`` (dict) - optional for mirror primary namespace snapshots - - * ``mirror_non_primary`` (dict) - optional for mirror non-primary namespace snapshots + * ``mirror`` (dict) - optional for mirror namespace snapshots """ cdef rbd_snap_info_t *snaps @@ -5563,20 +5537,13 @@ cdef class SnapIterator(object): except: trash = None s['trash'] = trash - elif s['namespace'] == RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY: - try: - mirror = self.image.snap_get_mirror_primary_namespace( - self.snaps[i].id) - except: - mirror = None - s['mirror_primary'] = mirror - elif s['namespace'] == RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY: + elif s['namespace'] == RBD_SNAP_NAMESPACE_TYPE_MIRROR: try: - mirror = self.image.snap_get_mirror_non_primary_namespace( + mirror = self.image.snap_get_mirror_namespace( self.snaps[i].id) except: mirror = None - s['mirror_non_primary'] = mirror + s['mirror'] = mirror yield s def __dealloc__(self): diff --git a/src/test/librbd/test_mirroring.cc b/src/test/librbd/test_mirroring.cc index c018bee35ad..e0145c889d0 100644 --- a/src/test/librbd/test_mirroring.cc +++ b/src/test/librbd/test_mirroring.cc @@ -1159,10 +1159,10 @@ TEST_F(TestMirroring, Snapshot) librbd::snap_namespace_type_t snap_ns_type; ASSERT_EQ(0, image.snap_get_namespace_type(snap_id, &snap_ns_type)); - ASSERT_EQ(RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY, snap_ns_type); - librbd::snap_mirror_primary_namespace_t mirror_snap; - ASSERT_EQ(0, image.snap_get_mirror_primary_namespace(snap_id, &mirror_snap, - sizeof(mirror_snap))); + ASSERT_EQ(RBD_SNAP_NAMESPACE_TYPE_MIRROR, snap_ns_type); + librbd::snap_mirror_namespace_t mirror_snap; + ASSERT_EQ(0, image.snap_get_mirror_namespace(snap_id, &mirror_snap, + sizeof(mirror_snap))); ASSERT_EQ(1U, mirror_snap.mirror_peer_uuids.size()); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer_uuid)); @@ -1242,9 +1242,9 @@ TEST_F(TestMirroring, SnapshotUnlinkPeer) ASSERT_EQ(0, image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT)); uint64_t snap_id; ASSERT_EQ(0, image.mirror_image_create_snapshot(&snap_id)); - librbd::snap_mirror_primary_namespace_t mirror_snap; - ASSERT_EQ(0, image.snap_get_mirror_primary_namespace(snap_id, &mirror_snap, - sizeof(mirror_snap))); + librbd::snap_mirror_namespace_t mirror_snap; + ASSERT_EQ(0, image.snap_get_mirror_namespace(snap_id, &mirror_snap, + sizeof(mirror_snap))); ASSERT_EQ(3U, mirror_snap.mirror_peer_uuids.size()); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer1_uuid)); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer2_uuid)); @@ -1264,8 +1264,8 @@ TEST_F(TestMirroring, SnapshotUnlinkPeer) req->send(); ASSERT_EQ(0, cond1.wait()); - ASSERT_EQ(0, image.snap_get_mirror_primary_namespace(snap_id, &mirror_snap, - sizeof(mirror_snap))); + ASSERT_EQ(0, image.snap_get_mirror_namespace(snap_id, &mirror_snap, + sizeof(mirror_snap))); ASSERT_EQ(2U, mirror_snap.mirror_peer_uuids.size()); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer2_uuid)); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer3_uuid)); @@ -1283,22 +1283,22 @@ TEST_F(TestMirroring, SnapshotUnlinkPeer) ASSERT_EQ(0, ns_image.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT)); uint64_t ns_snap_id; ASSERT_EQ(0, ns_image.mirror_image_create_snapshot(&ns_snap_id)); - ASSERT_EQ(0, ns_image.snap_get_mirror_primary_namespace( - ns_snap_id, &mirror_snap, sizeof(mirror_snap))); + ASSERT_EQ(0, ns_image.snap_get_mirror_namespace(ns_snap_id, &mirror_snap, + sizeof(mirror_snap))); ASSERT_EQ(3U, mirror_snap.mirror_peer_uuids.size()); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer1_uuid)); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer2_uuid)); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer3_uuid)); - + ASSERT_EQ(0, m_rbd.mirror_peer_site_remove(m_ioctx, peer3_uuid)); - ASSERT_EQ(0, image.snap_get_mirror_primary_namespace(snap_id, &mirror_snap, - sizeof(mirror_snap))); + ASSERT_EQ(0, image.snap_get_mirror_namespace(snap_id, &mirror_snap, + sizeof(mirror_snap))); ASSERT_EQ(1U, mirror_snap.mirror_peer_uuids.size()); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer2_uuid)); - ASSERT_EQ(0, ns_image.snap_get_mirror_primary_namespace( - ns_snap_id, &mirror_snap, sizeof(mirror_snap))); + ASSERT_EQ(0, ns_image.snap_get_mirror_namespace(ns_snap_id, &mirror_snap, + sizeof(mirror_snap))); ASSERT_EQ(2U, mirror_snap.mirror_peer_uuids.size()); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer1_uuid)); ASSERT_EQ(1, mirror_snap.mirror_peer_uuids.count(peer2_uuid)); @@ -1309,8 +1309,8 @@ TEST_F(TestMirroring, SnapshotUnlinkPeer) req->send(); ASSERT_EQ(0, cond2.wait()); - ASSERT_EQ(-ENOENT, image.snap_get_mirror_primary_namespace(snap_id, &mirror_snap, - sizeof(mirror_snap))); + ASSERT_EQ(-ENOENT, image.snap_get_mirror_namespace(snap_id, &mirror_snap, + sizeof(mirror_snap))); ictx->state->close(); ictx = nullptr; ASSERT_EQ(0, image.close()); diff --git a/src/test/pybind/test_rbd.py b/src/test/pybind/test_rbd.py index f09b2bc0761..836cc7f5bac 100644 --- a/src/test/pybind/test_rbd.py +++ b/src/test/pybind/test_rbd.py @@ -31,14 +31,14 @@ from rbd import (RBD, Group, Image, ImageNotFound, InvalidArgument, ImageExists, RBD_MIRROR_IMAGE_MODE_JOURNAL, RBD_MIRROR_IMAGE_MODE_SNAPSHOT, RBD_LOCK_MODE_EXCLUSIVE, RBD_OPERATION_FEATURE_GROUP, RBD_SNAP_NAMESPACE_TYPE_TRASH, - RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY, - RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY, + RBD_SNAP_NAMESPACE_TYPE_MIRROR, RBD_IMAGE_MIGRATION_STATE_PREPARED, RBD_CONFIG_SOURCE_CONFIG, RBD_CONFIG_SOURCE_POOL, RBD_CONFIG_SOURCE_IMAGE, RBD_MIRROR_PEER_ATTRIBUTE_NAME_MON_HOST, RBD_MIRROR_PEER_ATTRIBUTE_NAME_KEY, RBD_MIRROR_PEER_DIRECTION_RX, RBD_MIRROR_PEER_DIRECTION_RX_TX, - RBD_SNAP_REMOVE_UNPROTECT) + RBD_SNAP_REMOVE_UNPROTECT, RBD_SNAP_MIRROR_STATE_PRIMARY, + RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED) rados = None ioctx = None @@ -2083,8 +2083,8 @@ class TestMirroring(object): snaps = list(self.image.list_snaps()) eq(1, len(snaps)) snap = snaps[0] - eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY) - eq(False, snap['mirror_primary']['demoted']) + eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR) + eq(RBD_SNAP_MIRROR_STATE_PRIMARY, snap['mirror']['state']) info = self.image.mirror_image_get_info() eq(True, info['primary']) @@ -2099,19 +2099,19 @@ class TestMirroring(object): snaps = list(self.image.list_snaps()) eq(2, len(snaps)) snap = snaps[0] - eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY) - eq(False, snap['mirror_primary']['demoted']) + eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR) + eq(RBD_SNAP_MIRROR_STATE_PRIMARY, snap['mirror']['state']) snap = snaps[1] eq(snap['id'], snap_id) - eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY) - eq(False, snap['mirror_primary']['demoted']) + eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR) + eq(RBD_SNAP_MIRROR_STATE_PRIMARY, snap['mirror']['state']) eq(sorted([peer1_uuid, peer2_uuid]), - sorted(snap['mirror_primary']['mirror_peer_uuids'])) + sorted(snap['mirror']['mirror_peer_uuids'])) - eq(RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY, + eq(RBD_SNAP_NAMESPACE_TYPE_MIRROR, self.image.snap_get_namespace_type(snap_id)) - mirror_snap = self.image.snap_get_mirror_primary_namespace(snap_id) - eq(mirror_snap, snap['mirror_primary']) + mirror_snap = self.image.snap_get_mirror_namespace(snap_id) + eq(mirror_snap, snap['mirror']) self.image.mirror_image_demote() @@ -2120,15 +2120,15 @@ class TestMirroring(object): snaps = list(self.image.list_snaps()) eq(3, len(snaps)) snap = snaps[0] - eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY) + eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR) snap = snaps[1] eq(snap['id'], snap_id) - eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY) + eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR) snap = snaps[2] - eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY) - eq(True, snap['mirror_primary']['demoted']) + eq(snap['namespace'], RBD_SNAP_NAMESPACE_TYPE_MIRROR) + eq(RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED, snap['mirror']['state']) eq(sorted([peer1_uuid, peer2_uuid]), - sorted(snap['mirror_primary']['mirror_peer_uuids'])) + sorted(snap['mirror']['mirror_peer_uuids'])) self.rbd.mirror_peer_remove(ioctx, peer1_uuid) self.rbd.mirror_peer_remove(ioctx, peer2_uuid) diff --git a/src/tools/rbd/action/MirrorImage.cc b/src/tools/rbd/action/MirrorImage.cc index 833c7658e07..02fdbf3a7e0 100644 --- a/src/tools/rbd/action/MirrorImage.cc +++ b/src/tools/rbd/action/MirrorImage.cc @@ -316,6 +316,7 @@ int execute_status(const po::variables_map &vm, librados::IoCtx default_ns_io_ctx; default_ns_io_ctx.dup(io_ctx); default_ns_io_ctx.set_namespace(""); + std::vector mirror_peers; utils::get_mirror_peer_sites(default_ns_io_ctx, &mirror_peers); @@ -384,7 +385,7 @@ int execute_status(const po::variables_map &vm, if (r < 0) { return false; } - return type != RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY; + return type != RBD_SNAP_NAMESPACE_TYPE_MIRROR; }), snaps.end()); } @@ -428,16 +429,18 @@ int execute_status(const po::variables_map &vm, if (!snaps.empty()) { formatter->open_array_section("snapshots"); for (auto &snap : snaps) { - librbd::snap_mirror_primary_namespace_t info; - r = image.snap_get_mirror_primary_namespace(snap.id, &info, - sizeof(info)); - if (r < 0) { + librbd::snap_mirror_namespace_t info; + r = image.snap_get_mirror_namespace(snap.id, &info, sizeof(info)); + if (r < 0 || + (info.state != RBD_SNAP_MIRROR_STATE_PRIMARY && + info.state != RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED)) { continue; } formatter->open_object_section("snapshot"); formatter->dump_unsigned("id", snap.id); formatter->dump_string("name", snap.name); - formatter->dump_bool("demoted", info.demoted); + formatter->dump_bool("demoted", + info.state == RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED); formatter->open_array_section("mirror_peer_uuids"); for (auto &peer : info.mirror_peer_uuids) { formatter->dump_string("peer_uuid", peer); @@ -490,10 +493,11 @@ int execute_status(const po::variables_map &vm, bool first_site = true; for (auto &snap : snaps) { - librbd::snap_mirror_primary_namespace_t info; - r = image.snap_get_mirror_primary_namespace(snap.id, &info, - sizeof(info)); - if (r < 0) { + librbd::snap_mirror_namespace_t info; + r = image.snap_get_mirror_namespace(snap.id, &info, sizeof(info)); + if (r < 0 || + (info.state != RBD_SNAP_MIRROR_STATE_PRIMARY && + info.state != RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED)) { continue; } @@ -503,8 +507,9 @@ int execute_status(const po::variables_map &vm, first_site = false; std::cout << " " << snap.id << " " << snap.name << " (" - << (info.demoted ? "demoted " : "") << "peer_uuids:[" - << info.mirror_peer_uuids << "])"; + << (info.state == RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED ? + "demoted " : "") + << "peer_uuids:[" << info.mirror_peer_uuids << "])"; } std::cout << std::endl; } diff --git a/src/tools/rbd/action/Snap.cc b/src/tools/rbd/action/Snap.cc index b2e6b665c6e..9fe8806d8ac 100644 --- a/src/tools/rbd/action/Snap.cc +++ b/src/tools/rbd/action/Snap.cc @@ -95,11 +95,8 @@ int do_list_snaps(librbd::Image& image, Formatter *f, bool all_snaps, librados:: case RBD_SNAP_NAMESPACE_TYPE_TRASH: snap_namespace_name = "trash"; break; - case RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY: - snap_namespace_name = "mirror_primary"; - break; - case RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY: - snap_namespace_name = "mirror_non_primary"; + case RBD_SNAP_NAMESPACE_TYPE_MIRROR: + snap_namespace_name = "mirror"; break; } @@ -107,22 +104,31 @@ int do_list_snaps(librbd::Image& image, Formatter *f, bool all_snaps, librados:: std::string trash_original_name; int get_group_res = -ENOENT; librbd::snap_group_namespace_t group_snap; - int get_mirror_primary_res = -ENOENT; - librbd::snap_mirror_primary_namespace_t mirror_primary_snap; - int get_mirror_non_primary_res = -ENOENT; - librbd::snap_mirror_non_primary_namespace_t mirror_non_primary_snap; + int get_mirror_res = -ENOENT; + librbd::snap_mirror_namespace_t mirror_snap; + std::string mirror_snap_state = "unknown"; if (snap_namespace == RBD_SNAP_NAMESPACE_TYPE_GROUP) { get_group_res = image.snap_get_group_namespace(s->id, &group_snap, sizeof(group_snap)); } else if (snap_namespace == RBD_SNAP_NAMESPACE_TYPE_TRASH) { get_trash_res = image.snap_get_trash_namespace( s->id, &trash_original_name); - } else if (snap_namespace == RBD_SNAP_NAMESPACE_TYPE_MIRROR_PRIMARY) { - get_mirror_primary_res = image.snap_get_mirror_primary_namespace( - s->id, &mirror_primary_snap, sizeof(mirror_primary_snap)); - } else if (snap_namespace == RBD_SNAP_NAMESPACE_TYPE_MIRROR_NON_PRIMARY) { - get_mirror_non_primary_res = image.snap_get_mirror_non_primary_namespace( - s->id, &mirror_non_primary_snap, sizeof(mirror_non_primary_snap)); + } else if (snap_namespace == RBD_SNAP_NAMESPACE_TYPE_MIRROR) { + get_mirror_res = image.snap_get_mirror_namespace( + s->id, &mirror_snap, sizeof(mirror_snap)); + + switch (mirror_snap.state) { + case RBD_SNAP_MIRROR_STATE_PRIMARY: + mirror_snap_state = "primary"; + break; + case RBD_SNAP_MIRROR_STATE_NON_PRIMARY: + mirror_snap_state = "non-primary"; + break; + case RBD_SNAP_MIRROR_STATE_PRIMARY_DEMOTED: + case RBD_SNAP_MIRROR_STATE_NON_PRIMARY_DEMOTED: + mirror_snap_state = "demoted"; + break; + } } std::string protected_str = ""; @@ -152,21 +158,23 @@ int do_list_snaps(librbd::Image& image, Formatter *f, bool all_snaps, librados:: f->dump_string("group snap", group_snap.group_snap_name); } else if (get_trash_res == 0) { f->dump_string("original_name", trash_original_name); - } else if (get_mirror_primary_res == 0) { - f->dump_bool("demoted", mirror_primary_snap.demoted); + } else if (get_mirror_res == 0) { + f->dump_string("state", mirror_snap_state); f->open_array_section("mirror_peer_uuids"); - for (auto &uuid : mirror_primary_snap.mirror_peer_uuids) { + for (auto &uuid : mirror_snap.mirror_peer_uuids) { f->dump_string("peer_uuid", uuid); } f->close_section(); - } else if (get_mirror_non_primary_res == 0) { - f->dump_string("primary_mirror_uuid", - mirror_non_primary_snap.primary_mirror_uuid); - f->dump_unsigned("primary_snap_id", - mirror_non_primary_snap.primary_snap_id); - f->dump_bool("copied", mirror_non_primary_snap.copied); - f->dump_unsigned("last_copied_object_number", - mirror_non_primary_snap.last_copied_object_number); + f->dump_bool("complete", mirror_snap.complete); + if (mirror_snap.state == RBD_SNAP_MIRROR_STATE_NON_PRIMARY || + mirror_snap.state == RBD_SNAP_MIRROR_STATE_NON_PRIMARY_DEMOTED) { + f->dump_string("primary_mirror_uuid", + mirror_snap.primary_mirror_uuid); + f->dump_unsigned("primary_snap_id", + mirror_snap.primary_snap_id); + f->dump_unsigned("last_copied_object_number", + mirror_snap.last_copied_object_number); + } } f->close_section(); } @@ -186,24 +194,26 @@ int do_list_snaps(librbd::Image& image, Formatter *f, bool all_snaps, librados:: << group_snap.group_snap_name << ")"; } else if (get_trash_res == 0) { oss << " (" << trash_original_name << ")"; - } else if (get_mirror_primary_res == 0) { - oss << " (" << (mirror_primary_snap.demoted ? "demoted " : "") - << "peer_uuids:[" << mirror_primary_snap.mirror_peer_uuids - << "])"; - } else if (get_mirror_non_primary_res == 0) { - oss << " (" << mirror_non_primary_snap.primary_mirror_uuid << ":" - << mirror_non_primary_snap.primary_snap_id << " "; - if (!mirror_non_primary_snap.copied) { - if (info.num_objs > 0) { - auto progress = std::min( - 100, 100 * mirror_non_primary_snap.last_copied_object_number / - info.num_objs); - oss << progress << "%"; - } else { - oss << "not "; + } else if (get_mirror_res == 0) { + oss << " (" << mirror_snap_state << " " + << "peer_uuids:[" << mirror_snap.mirror_peer_uuids << "]"; + if (mirror_snap.state == RBD_SNAP_MIRROR_STATE_NON_PRIMARY || + mirror_snap.state == RBD_SNAP_MIRROR_STATE_NON_PRIMARY_DEMOTED) { + oss << mirror_snap.primary_mirror_uuid << ":" + << mirror_snap.primary_snap_id << " "; + if (!mirror_snap.complete) { + if (info.num_objs > 0) { + auto progress = std::min( + 100, 100 * mirror_snap.last_copied_object_number / + info.num_objs); + oss << progress << "% "; + } else { + oss << "not "; + } } + oss << "copied"; } - oss << " copied)"; + oss << ")"; } t << oss.str(); -- 2.39.5