<< original_snapshot_namespace_type;
}
+void MirrorPrimarySnapshotNamespace::encode(bufferlist& bl) const {
+ using ceph::encode;
+ encode(demoted, bl);
+ encode(mirror_peers, bl);
+}
+
+void MirrorPrimarySnapshotNamespace::decode(bufferlist::const_iterator& it) {
+ using ceph::decode;
+ decode(demoted, it);
+ decode(mirror_peers, it);
+}
+
+void MirrorPrimarySnapshotNamespace::dump(Formatter *f) const {
+ f->dump_bool("demoted", demoted);
+ f->open_array_section("mirror_peers");
+ for (auto &peer : mirror_peers) {
+ f->dump_string("mirror_peer", peer);
+ }
+ f->close_section();
+}
+
+void MirrorNonPrimarySnapshotNamespace::encode(bufferlist& bl) const {
+ using ceph::encode;
+ encode(primary_mirror_uuid, bl);
+ encode(primary_snap_id, bl);
+ encode(copied, bl);
+ encode(copy_progress, bl);
+}
+
+void MirrorNonPrimarySnapshotNamespace::decode(bufferlist::const_iterator& it) {
+ using ceph::decode;
+ decode(primary_mirror_uuid, it);
+ decode(primary_snap_id, it);
+ decode(copied, it);
+ decode(copy_progress, it);
+}
+
+void MirrorNonPrimarySnapshotNamespace::dump(Formatter *f) const {
+ f->dump_string("primary_mirror_uuid", primary_mirror_uuid);
+ f->dump_unsigned("primary_snap_id", primary_snap_id);
+ f->dump_bool("copied", copied);
+ f->dump_unsigned("copy_progress", copy_progress);
+}
+
class EncodeSnapshotNamespaceVisitor : public boost::static_visitor<void> {
public:
explicit EncodeSnapshotNamespaceVisitor(bufferlist &bl) : m_bl(bl) {
TrashSnapshotNamespace{
SNAPSHOT_NAMESPACE_TYPE_USER, "snap1"},
"12345", 123, {123456, 0}, 429));
+ o.push_back(new SnapshotInfo(1ULL,
+ MirrorPrimarySnapshotNamespace{true, {"1", "2"}},
+ "snap1", 123, {123456, 0}, 12));
+ o.push_back(new SnapshotInfo(1ULL,
+ MirrorNonPrimarySnapshotNamespace{"uuid", 111},
+ "snap1", 123, {123456, 0}, 12));
}
void SnapshotNamespace::encode(bufferlist& bl) const {
case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_TRASH:
*this = TrashSnapshotNamespace();
break;
+ case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY:
+ *this = MirrorPrimarySnapshotNamespace();
+ break;
+ case cls::rbd::SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY:
+ *this = MirrorNonPrimarySnapshotNamespace();
+ break;
default:
*this = UnknownSnapshotNamespace();
break;
o.push_back(new SnapshotNamespace(GroupSnapshotNamespace(5, "1018643c9869",
"33352be8933c")));
o.push_back(new SnapshotNamespace(TrashSnapshotNamespace()));
+ o.push_back(new SnapshotNamespace(MirrorPrimarySnapshotNamespace(true,
+ {"uuid"})));
+ o.push_back(new SnapshotNamespace(MirrorNonPrimarySnapshotNamespace("", 0)));
}
std::ostream& operator<<(std::ostream& os, const SnapshotNamespaceType& type) {
case SNAPSHOT_NAMESPACE_TYPE_TRASH:
os << "trash";
break;
+ case SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY:
+ os << "mirror_primary";
+ break;
+ case SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY:
+ os << "mirror_non_primary";
+ break;
default:
os << "unknown";
break;
return os;
}
+std::ostream& operator<<(std::ostream& os,
+ const MirrorPrimarySnapshotNamespace& ns) {
+ os << "[" << SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY << " "
+ << "demoted=" << ns.demoted << ", "
+ << "mirror_peers=" << ns.mirror_peers
+ << "]";
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const MirrorNonPrimarySnapshotNamespace& ns) {
+ os << "[" << SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY << " "
+ << "primary_mirror_uuid=" << ns.primary_mirror_uuid << ", "
+ << "primary_snap_id=" << ns.primary_snap_id << ", "
+ << "copied=" << ns.copied << ", "
+ << "copy_progress=" << ns.copy_progress
+ << "]";
+ return os;
+}
+
std::ostream& operator<<(std::ostream& os, const UnknownSnapshotNamespace& ns) {
os << "[unknown]";
return os;
WRITE_CLASS_ENCODER(GroupSpec);
enum SnapshotNamespaceType {
- SNAPSHOT_NAMESPACE_TYPE_USER = 0,
- SNAPSHOT_NAMESPACE_TYPE_GROUP = 1,
- SNAPSHOT_NAMESPACE_TYPE_TRASH = 2
+ SNAPSHOT_NAMESPACE_TYPE_USER = 0,
+ SNAPSHOT_NAMESPACE_TYPE_GROUP = 1,
+ SNAPSHOT_NAMESPACE_TYPE_TRASH = 2,
+ SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY = 3,
+ SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY = 4,
};
struct UserSnapshotNamespace {
}
};
+struct MirrorPrimarySnapshotNamespace {
+ static const SnapshotNamespaceType SNAPSHOT_NAMESPACE_TYPE =
+ SNAPSHOT_NAMESPACE_TYPE_MIRROR_PRIMARY;
+
+ bool demoted = false;
+ std::set<std::string> mirror_peers;
+
+ MirrorPrimarySnapshotNamespace() {
+ }
+ MirrorPrimarySnapshotNamespace(bool demoted,
+ const std::set<std::string> &mirror_peers)
+ : demoted(demoted), mirror_peers(mirror_peers) {
+ }
+
+ void encode(bufferlist& bl) const;
+ void decode(bufferlist::const_iterator& it);
+
+ void dump(Formatter *f) const;
+
+ inline bool operator==(const MirrorPrimarySnapshotNamespace& mpsn) const {
+ return demoted == mpsn.demoted &&
+ mirror_peer_uuids == mpsn.mirror_peer_uuids;
+ }
+
+ inline bool operator<(const MirrorPrimarySnapshotNamespace& mpsn) const {
+ if (demoted != mpsn.demoted) {
+ return demoted < mpsn.demoted;
+ }
+ return mirror_peer_uuids < mpsn.mirror_peer_uuids;
+ }
+};
+
+struct MirrorNonPrimarySnapshotNamespace {
+ static const SnapshotNamespaceType SNAPSHOT_NAMESPACE_TYPE =
+ SNAPSHOT_NAMESPACE_TYPE_MIRROR_NON_PRIMARY;
+
+ std::string primary_mirror_uuid;
+ snapid_t primary_snap_id = CEPH_NOSNAP;
+ bool copied = false;
+ uint64_t copy_progress = 0;
+
+ MirrorNonPrimarySnapshotNamespace() {
+ }
+ MirrorNonPrimarySnapshotNamespace(const std::string &primary_mirror_uuid,
+ snapid_t primary_snap_id)
+ : primary_mirror_uuid(primary_mirror_uuid),
+ primary_snap_id(primary_snap_id) {
+ }
+
+ void encode(bufferlist& bl) const;
+ void decode(bufferlist::const_iterator& it);
+
+ void dump(Formatter *f) const;
+
+ inline bool operator==(const MirrorNonPrimarySnapshotNamespace& mnsn) const {
+ return primary_mirror_uuid == mnsn.primary_mirror_uuid &&
+ primary_snap_id == mnsn.primary_snap_id && copied == mnsn.copied &&
+ last_copied_object_number == mnsn.last_copied_object_number;
+ }
+
+ inline bool operator<(const MirrorNonPrimarySnapshotNamespace& mnsn) const {
+ if (primary_mirror_uuid != mnsn.primary_mirror_uuid) {
+ return primary_mirror_uuid < mnsn.primary_mirror_uuid;
+ }
+ if (primary_snap_id != mnsn.primary_snap_id) {
+ return primary_snap_id < mnsn.primary_snap_id;
+ }
+ if (copied != mnsn.copied) {
+ return copied < mnsn.copied;
+ }
+ return last_copied_object_number < mnsn.last_copied_object_number;
+ }
+};
+
struct UnknownSnapshotNamespace {
static const SnapshotNamespaceType SNAPSHOT_NAMESPACE_TYPE =
static_cast<SnapshotNamespaceType>(-1);
std::ostream& operator<<(std::ostream& os, const UserSnapshotNamespace& ns);
std::ostream& operator<<(std::ostream& os, const GroupSnapshotNamespace& ns);
std::ostream& operator<<(std::ostream& os, const TrashSnapshotNamespace& ns);
+std::ostream& operator<<(std::ostream& os,
+ const MirrorPrimarySnapshotNamespace& ns);
+std::ostream& operator<<(std::ostream& os,
+ const MirrorNonPrimarySnapshotNamespace& ns);
std::ostream& operator<<(std::ostream& os, const UnknownSnapshotNamespace& ns);
typedef boost::variant<UserSnapshotNamespace,
GroupSnapshotNamespace,
TrashSnapshotNamespace,
+ MirrorPrimarySnapshotNamespace,
+ MirrorNonPrimarySnapshotNamespace,
UnknownSnapshotNamespace> SnapshotNamespaceVariant;
struct SnapshotNamespace : public SnapshotNamespaceVariant {
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_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_t;
typedef struct {
char *group_snap_name;
} rbd_snap_group_namespace_t;
+typedef struct {
+ bool demoted;
+ size_t mirror_peers_count;
+ char *mirror_peers;
+} rbd_snap_mirror_primary_namespace_t;
+
+typedef struct {
+ char *primary_mirror_uuid;
+ uint64_t primary_snap_id;
+ bool copied;
+ uint64_t copy_progress;
+} rbd_snap_mirror_non_primary_namespace_t;
+
typedef enum {
RBD_LOCK_MODE_EXCLUSIVE = 0,
RBD_LOCK_MODE_SHARED = 1,
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(
+ 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);
CEPH_RBD_API int rbd_flatten(rbd_image_t image);
std::string group_snap_name;
} snap_group_namespace_t;
+ typedef struct {
+ bool demoted;
+ std::set<std::string> mirror_peers;
+ } snap_mirror_primary_namespace_t;
+
+ typedef struct {
+ std::string primary_mirror_uuid;
+ uint64_t primary_snap_id;
+ bool copied;
+ uint64_t copy_progress;
+ } snap_mirror_non_primary_namespace_t;
+
typedef struct {
std::string client;
std::string cookie;
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,
+ size_t snap_mirror_namespace_size);
/* I/O */
ssize_t read(uint64_t ofs, size_t len, ceph::bufferlist& bl);
}
};
+class GetMirrorPrimaryVisitor : public boost::static_visitor<int> {
+public:
+ snap_mirror_primary_namespace_t *mirror_snap;
+
+ explicit GetMirrorPrimaryVisitor(snap_mirror_primary_namespace_t *mirror_snap)
+ : mirror_snap(mirror_snap) {
+ }
+
+ template <typename T>
+ inline int operator()(const T&) const {
+ return -EINVAL;
+ }
+
+ inline int operator()(
+ const cls::rbd::MirrorPrimarySnapshotNamespace& snap_namespace) {
+ mirror_snap->demoted = snap_namespace.demoted;
+ mirror_snap->mirror_peers = snap_namespace.mirror_peers;
+ return 0;
+ }
+};
+
+class GetMirrorNonPrimaryVisitor : public boost::static_visitor<int> {
+public:
+ snap_mirror_non_primary_namespace_t *mirror_snap;
+
+ explicit GetMirrorNonPrimaryVisitor(
+ snap_mirror_non_primary_namespace_t *mirror_snap)
+ : mirror_snap(mirror_snap) {
+ }
+
+ template <typename T>
+ inline int operator()(const T&) const {
+ return -EINVAL;
+ }
+
+ inline int operator()(
+ const cls::rbd::MirrorNonPrimarySnapshotNamespace& snap_namespace) {
+ 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->copy_progress = snap_namespace.copy_progress;
+ return 0;
+ }
+};
+
} // anonymous namespace
template <typename I>
return 0;
}
+template <typename I>
+int Snapshot<I>::get_mirror_primary_namespace(
+ I *ictx, uint64_t snap_id, snap_mirror_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 = GetMirrorPrimaryVisitor(mirror_snap);
+ r = boost::apply_visitor(gmv, snap_info->snap_namespace);
+ if (r < 0) {
+ return r;
+ }
+
+ return 0;
+}
+
+template <typename I>
+int Snapshot<I>::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);
+ r = boost::apply_visitor(gmv, snap_info->snap_namespace);
+ if (r < 0) {
+ return r;
+ }
+
+ return 0;
+}
+
template <typename I>
int Snapshot<I>::get_namespace_type(I *ictx, uint64_t snap_id,
snap_namespace_type_t *namespace_type) {
static int get_trash_namespace(ImageCtxT *ictx, uint64_t snap_id,
std::string *original_name);
+ static int get_mirror_primary_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);
+
static int get_namespace_type(ImageCtxT *ictx, uint64_t snap_id,
snap_namespace_type_t *namespace_type);
original_name);
}
+ int Image::snap_get_mirror_primary_namespace(
+ uint64_t snap_id, snap_mirror_primary_namespace_t *mirror_snap,
+ size_t mirror_snap_size) {
+ ImageCtx *ictx = (ImageCtx *)ctx;
+
+ if (mirror_snap_size != sizeof(snap_mirror_primary_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(
+ ictx, snap_id, mirror_snap);
+ return r;
+ }
+
int Image::snap_set_limit(uint64_t limit)
{
ImageCtx *ictx = (ImageCtx *)ctx;
strcpy(original_name, cpp_original_name.c_str());
return 0;
}
+
+extern "C" 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) {
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+
+ if (mirror_snap_size != sizeof(rbd_snap_mirror_primary_namespace_t)) {
+ return -ERANGE;
+ }
+
+ librbd::snap_mirror_primary_namespace_t mirror_namespace;
+ int r = librbd::api::Snapshot<>::get_mirror_primary_namespace(
+ ictx, snap_id, &mirror_namespace);
+ if (r < 0) {
+ return r;
+ }
+
+ mirror_snap->demoted = mirror_namespace.demoted;
+ mirror_snap->mirror_peers_count = mirror_namespace.mirror_peers.size();
+ size_t len = 0;
+ for (auto &peer : mirror_namespace.mirror_peers) {
+ len += peer.size() + 1;
+ }
+ mirror_snap->mirror_peers = (char *)malloc(len);
+ char *p = mirror_snap->mirror_peers;
+ for (auto &peer : mirror_namespace.mirror_peers) {
+ 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_peers);
+ 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->copy_progress = mirror_namespace.copy_progress;
+
+ return 0;
+}
+
+extern "C" int rbd_snap_mirror_non_primary_namespace_cleanup(
+ rbd_snap_mirror_non_primary_namespace_t *mirror_snap,
+ size_t mirror_snap_size) {
+ if (mirror_snap_size != sizeof(rbd_snap_mirror_non_primary_namespace_t)) {
+ return -ERANGE;
+ }
+
+ free(mirror_snap->primary_mirror_uuid);
+ return 0;
+}
+
extern "C" int rbd_watchers_list(rbd_image_t image,
rbd_image_watcher_t *watchers,
size_t *max_watchers) {
char *group_name
char *group_snap_name
+ ctypedef struct rbd_snap_mirror_primary_namespace_t:
+ bint demoted
+ size_t mirror_peers_count
+ char *mirror_peers
+
+ ctypedef struct rbd_snap_mirror_non_primary_namespace_t:
+ char *primary_mirror_uuid
+ uint64_t primary_snap_id
+ bint copied
+ uint64_t copy_progress
+
ctypedef struct rbd_group_info_t:
char *name
int64_t 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"
ctypedef struct rbd_snap_spec_t:
uint64_t id
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(
+ 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)
int rbd_flatten_with_progress(rbd_image_t image, librbd_progress_fn_t cb,
void *cbdata)
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_GROUP_IMAGE_STATE_ATTACHED = _RBD_GROUP_IMAGE_STATE_ATTACHED
RBD_GROUP_IMAGE_STATE_INCOMPLETE = _RBD_GROUP_IMAGE_STATE_INCOMPLETE
finally:
free(_name)
+ def snap_get_mirror_primary_namespace(self, snap_id):
+ """
+ get the mirror primary 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
+
+ * ``mirror_peers`` (list) - mirror peer uuids
+ """
+ cdef:
+ rbd_snap_mirror_primary_namespace_t sn
+ uint64_t _snap_id = snap_id
+ with nogil:
+ ret = rbd_snap_get_mirror_primary_namespace(
+ self.image, _snap_id, &sn,
+ sizeof(rbd_snap_mirror_primary_namespace_t))
+ if ret != 0:
+ raise make_ex(ret, 'error getting snapshot mirror primary '
+ 'namespace for image: %s, snap_id: %d' %
+ (self.name, snap_id))
+ peers = []
+ p = sn.mirror_peers
+ for i in range(sn.mirror_peers_count):
+ peer = decode_cstr(p)
+ peers.append(peer)
+ p += len(peer) + 1
+ info = {
+ 'demoted' : sn.demoted,
+ 'mirror_peers' : peers,
+ }
+ 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
+
+ * ``copy_progress`` (int) - copy progress
+ """
+ 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 = {
+ 'primary_mirror_uuid' : decode_cstr(sn.primary_mirror_uuid),
+ 'primary_snap_id' : sn.primary_snap_id,
+ 'copied' : sn.copied,
+ 'copy_progress' : sn.copy_progress,
+ }
+ rbd_snap_mirror_non_primary_namespace_cleanup(
+ &sn, sizeof(rbd_snap_mirror_non_primary_namespace_t))
+ return info
+
cdef class ImageIterator(object):
"""
* ``group`` (dict) - optional for group namespace snapshots
* ``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
"""
cdef rbd_snap_info_t *snaps
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:
+ try:
+ mirror = self.image.snap_get_mirror_non_primary_namespace(
+ self.snaps[i].id)
+ except:
+ mirror = None
+ s['mirror_non_primary'] = mirror
yield s
def __dealloc__(self):
return r;
}
+ librbd::image_info_t info;
if (!all_snaps) {
snaps.erase(remove_if(snaps.begin(),
snaps.end(),
boost::bind(utils::is_not_user_snap_namespace, &image, _1)),
snaps.end());
+ } else if (!f) {
+ r = image.stat(info, sizeof(info));
+ if (r < 0) {
+ std::cerr << "rbd: unable to get image info" << std::endl;
+ return r;
+ }
}
if (f) {
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";
+ break;
}
int get_trash_res = -ENOENT;
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;
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));
}
std::string protected_str = "";
f->dump_string("protected", protected_str);
f->dump_string("timestamp", tt_str);
if (all_snaps) {
- f->open_object_section("namespace");
+ f->open_object_section("namespace");
f->dump_string("type", snap_namespace_name);
- if (get_group_res == 0) {
- std::string pool_name = pool_map[group_snap.group_pool];
- f->dump_string("pool", pool_name);
- f->dump_string("group", group_snap.group_name);
- f->dump_string("group snap", group_snap.group_snap_name);
- } else if (get_trash_res == 0) {
+ if (get_group_res == 0) {
+ std::string pool_name = pool_map[group_snap.group_pool];
+ f->dump_string("pool", pool_name);
+ f->dump_string("group", group_snap.group_name);
+ 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);
+ f->open_array_section("mirror_peer_uuids");
+ for (auto &uuid : mirror_primary_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->close_section();
+ f->close_section();
}
f->close_section();
} else {
t << s->id << s->name << stringify(byte_u_t(s->size)) << protected_str << tt_str;
if (all_snaps) {
- ostringstream oss;
+ ostringstream oss;
oss << snap_namespace_name;
if (get_group_res == 0) {
- std::string pool_name = pool_map[group_snap.group_pool];
- oss << " (" << pool_name << "/"
- << group_snap.group_name << "@"
- << group_snap.group_snap_name << ")";
+ std::string pool_name = pool_map[group_snap.group_pool];
+ oss << " (" << pool_name << "/"
+ << group_snap.group_name << "@"
+ << 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<uint64_t>(
+ 100, 100 * mirror_non_primary_snap.last_copied_object_number /
+ info.num_objs);
+ oss << progress << "%";
+ } else {
+ oss << "not ";
+ }
+ }
+ oss << " copied)";
}
- t << oss.str();
+ t << oss.str();
}
t << TextTable::endrow;
}