char parent_name[RBD_MAX_IMAGE_NAME_SIZE]; /* deprecated */
} rbd_image_info_t;
+typedef struct {
+ char *cluster_uuid;
+ char *cluster_name;
+ char *client_name;
+} rbd_mirror_peer_t;
+
CEPH_RBD_API void rbd_version(int *major, int *minor, int *extra);
/* image options */
CEPH_RBD_API int rbd_rename(rados_ioctx_t src_io_ctx, const char *srcname,
const char *destname);
+/* pool mirroring */
+CEPH_RBD_API int rbd_mirror_is_enabled(rados_ioctx_t io_ctx, bool *enabled);
+CEPH_RBD_API int rbd_mirror_set_enabled(rados_ioctx_t io_ctx, bool enabled);
+CEPH_RBD_API int rbd_mirror_peer_add(rados_ioctx_t io_ctx,
+ const char *cluster_uuid,
+ const char *cluster_name,
+ const char *client_name);
+CEPH_RBD_API int rbd_mirror_peer_remove(rados_ioctx_t io_ctx,
+ const char *cluster_name);
+CEPH_RBD_API int rbd_mirror_peer_list(rados_ioctx_t io_ctx,
+ rbd_mirror_peer_t *peers, int *max_peers);
+CEPH_RBD_API void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
+ int max_peers);
+CEPH_RBD_API int rbd_mirror_peer_set_client(rados_ioctx_t io_ctx,
+ const char *cluster_uuid,
+ const char *client_name);
+CEPH_RBD_API int rbd_mirror_peer_set_cluster(rados_ioctx_t io_ctx,
+ const char *cluster_uuid,
+ const char *cluster_name);
+
CEPH_RBD_API int rbd_open(rados_ioctx_t io, const char *name,
rbd_image_t *image, const char *snap_name);
std::string address;
} locker_t;
+ typedef struct {
+ std::string cluster_uuid;
+ std::string cluster_name;
+ std::string client_name;
+ } mirror_peer_t;
+
typedef rbd_image_info_t image_info_t;
class CEPH_RBD_API ProgressContext
int remove_with_progress(IoCtx& io_ctx, const char *name, ProgressContext& pctx);
int rename(IoCtx& src_io_ctx, const char *srcname, const char *destname);
+ // RBD pool mirroring support functions
+ int mirror_is_enabled(IoCtx& io_ctx, bool *enabled);
+ int mirror_set_enabled(IoCtx& io_ctx, bool enabled);
+ int mirror_peer_add(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &cluster_name,
+ const std::string &client_name);
+ int mirror_peer_remove(IoCtx& io_ctx, const std::string &cluster_uuid);
+ int mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers);
+ int mirror_peer_set_client(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &client_name);
+ int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &cluster_name);
+
private:
/* We don't allow assignment or copying */
RBD(const RBD& rhs);
return cls_client::metadata_list(&ictx->md_ctx, ictx->header_oid, start, max, pairs);
}
+ int mirror_is_enabled(IoCtx& io_ctx, bool *enabled) {
+ CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+ ldout(cct, 20) << __func__ << dendl;
+
+ int r = cls_client::mirror_is_enabled(&io_ctx, enabled);
+ if (r < 0) {
+ lderr(cct) << "Failed to retrieve mirror flag: " << cpp_strerror(r)
+ << dendl;
+ return r;
+ }
+ return 0;
+ }
+
+ int mirror_set_enabled(IoCtx& io_ctx, bool enabled) {
+ CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+ ldout(cct, 20) << __func__ << ": enabled=" << enabled << dendl;
+
+ int r = cls_client::mirror_set_enabled(&io_ctx, enabled);
+ if (r < 0 && r != -ENOENT) {
+ lderr(cct) << "Failed to set mirror flag: " << cpp_strerror(r) << dendl;
+ return r;
+ }
+ return 0;
+ }
+
+ int mirror_peer_add(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &cluster_name,
+ const std::string &client_name) {
+ CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+ ldout(cct, 20) << __func__ << ": uuid=" << cluster_uuid << ", "
+ << "name=" << cluster_name << ", "
+ << "client=" << client_name << dendl;
+
+ std::string local_cluster_uuid;
+ librados::Rados rados(io_ctx);
+ int r = rados.cluster_fsid(&local_cluster_uuid);
+ if (r < 0) {
+ lderr(cct) << "Failed to retreive cluster uuid" << dendl;
+ return r;
+ }
+
+ if (local_cluster_uuid == cluster_uuid) {
+ lderr(cct) << "Cannot add self as remote peer" << dendl;
+ return -EINVAL;
+ }
+
+ r = cls_client::mirror_peer_add(&io_ctx, cluster_uuid, cluster_name,
+ client_name);
+ if (r < 0) {
+ lderr(cct) << "Failed to add mirror peer '" << cluster_uuid << "': "
+ << cpp_strerror(r) << dendl;
+ return r;
+ }
+ return 0;
+ }
+
+ int mirror_peer_remove(IoCtx& io_ctx, const std::string &cluster_uuid) {
+ CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+ ldout(cct, 20) << __func__ << ": uuid=" << cluster_uuid << dendl;
+
+ int r = cls_client::mirror_peer_remove(&io_ctx, cluster_uuid);
+ if (r < 0 && r != -ENOENT) {
+ lderr(cct) << "Failed to remove peer '" << cluster_uuid << "': "
+ << cpp_strerror(r) << dendl;
+ return r;
+ }
+ return 0;
+ }
+
+ int mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers) {
+ CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+ ldout(cct, 20) << __func__ << dendl;
+
+ std::vector<cls::rbd::MirrorPeer> mirror_peers;
+ int r = cls_client::mirror_peer_list(&io_ctx, &mirror_peers);
+ if (r < 0 && r != -ENOENT) {
+ lderr(cct) << "Failed to list peers: " << cpp_strerror(r) << dendl;
+ return r;
+ }
+
+ peers->clear();
+ peers->reserve(mirror_peers.size());
+ for (auto &mirror_peer : mirror_peers) {
+ mirror_peer_t peer;
+ peer.cluster_uuid = mirror_peer.cluster_uuid;
+ peer.cluster_name = mirror_peer.cluster_name;
+ peer.client_name = mirror_peer.client_name;
+ peers->push_back(peer);
+ }
+ return 0;
+ }
+
+ int mirror_peer_set_client(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &client_name) {
+ CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+ ldout(cct, 20) << __func__ << ": uuid=" << cluster_uuid << ", "
+ << "client=" << client_name << dendl;
+
+ int r = cls_client::mirror_peer_set_client(&io_ctx, cluster_uuid,
+ client_name);
+ if (r < 0) {
+ lderr(cct) << "Failed to update client '" << cluster_uuid << "': "
+ << cpp_strerror(r) << dendl;
+ return r;
+ }
+ return 0;
+ }
+
+ int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &cluster_name) {
+ CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+ ldout(cct, 20) << __func__ << ": uuid=" << cluster_uuid << ", "
+ << "cluster=" << cluster_name << dendl;
+
+ int r = cls_client::mirror_peer_set_cluster(&io_ctx, cluster_uuid,
+ cluster_name);
+ if (r < 0) {
+ lderr(cct) << "Failed to update cluster '" << cluster_uuid << "': "
+ << cpp_strerror(r) << dendl;
+ return r;
+ }
+ return 0;
+ }
+
void rbd_req_cb(completion_t cb, void *arg)
{
AioObjectRequest *req = reinterpret_cast<AioObjectRequest *>(arg);
int metadata_set(ImageCtx *ictx, const std::string &key, const std::string &value);
int metadata_remove(ImageCtx *ictx, const std::string &key);
+ int mirror_is_enabled(IoCtx& io_ctx, bool *enabled);
+ int mirror_set_enabled(IoCtx& io_ctx, bool enabled);
+ int mirror_peer_add(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &cluster_name,
+ const std::string &client_name);
+ int mirror_peer_remove(IoCtx& io_ctx, const std::string &cluster_uuid);
+ int mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers);
+ int mirror_peer_set_client(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &client_name);
+ int mirror_peer_set_cluster(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &cluster_name);
+
AioCompletion *aio_create_completion();
AioCompletion *aio_create_completion(void *cb_arg, callback_t cb_complete);
AioCompletion *aio_create_completion_internal(void *cb_arg,
return r;
}
+ int RBD::mirror_is_enabled(IoCtx& io_ctx, bool *enabled) {
+ return librbd::mirror_is_enabled(io_ctx, enabled);
+ }
+
+ int RBD::mirror_set_enabled(IoCtx& io_ctx, bool enabled) {
+ return librbd::mirror_set_enabled(io_ctx, enabled);
+ }
+
+ int RBD::mirror_peer_add(IoCtx& io_ctx, const std::string &cluster_uuid,
+ const std::string &cluster_name,
+ const std::string &client_name) {
+ return librbd::mirror_peer_add(io_ctx, cluster_uuid, cluster_name,
+ client_name);
+ }
+
+ int RBD::mirror_peer_remove(IoCtx& io_ctx, const std::string &cluster_uuid) {
+ return librbd::mirror_peer_remove(io_ctx, cluster_uuid);
+ }
+
+ int RBD::mirror_peer_list(IoCtx& io_ctx, std::vector<mirror_peer_t> *peers) {
+ return librbd::mirror_peer_list(io_ctx, peers);
+ }
+
+ int RBD::mirror_peer_set_client(IoCtx& io_ctx,
+ const std::string &cluster_uuid,
+ const std::string &client_name) {
+ return librbd::mirror_peer_set_client(io_ctx, cluster_uuid, client_name);
+ }
+
+ int RBD::mirror_peer_set_cluster(IoCtx& io_ctx,
+ const std::string &cluster_uuid,
+ const std::string &cluster_name) {
+ return librbd::mirror_peer_set_cluster(io_ctx, cluster_uuid, cluster_name);
+ }
+
RBD::AioCompletion::AioCompletion(void *cb_arg, callback_t complete_cb)
{
librbd::AioCompletion *c = librbd::aio_create_completion(cb_arg,
return librbd::image_options_is_empty(opts);
}
+/* pool mirroring */
+extern "C" int rbd_mirror_is_enabled(rados_ioctx_t p, bool *enabled) {
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+ int r = librbd::mirror_is_enabled(io_ctx, enabled);
+ if (r < 0) {
+ return r;
+ }
+ return 0;
+}
+
+extern "C" int rbd_mirror_set_enabled(rados_ioctx_t p, bool enabled) {
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+ return librbd::mirror_set_enabled(io_ctx, enabled);
+}
+
+extern "C" int rbd_mirror_peer_add(rados_ioctx_t p,
+ const char *cluster_uuid,
+ const char *cluster_name,
+ const char *client_name) {
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+ return librbd::mirror_peer_add(io_ctx, cluster_uuid, cluster_name,
+ client_name);
+}
+
+extern "C" int rbd_mirror_peer_remove(rados_ioctx_t p,
+ const char *cluster_name) {
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+ int r = librbd::mirror_peer_remove(io_ctx, cluster_name);
+ return r;
+}
+
+extern "C" int rbd_mirror_peer_list(rados_ioctx_t p,
+ rbd_mirror_peer_t *peers, int *max_peers) {
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+
+ std::vector<librbd::mirror_peer_t> peer_vector;
+ int r = librbd::mirror_peer_list(io_ctx, &peer_vector);
+ if (r < 0) {
+ return r;
+ }
+
+ if (*max_peers < static_cast<int>(peer_vector.size())) {
+ *max_peers = static_cast<int>(peer_vector.size());
+ return -ERANGE;
+ }
+
+ for (int i = 0; i < static_cast<int>(peer_vector.size()); ++i) {
+ peers[i].cluster_uuid = strdup(peer_vector[i].cluster_uuid.c_str());
+ peers[i].cluster_name = strdup(peer_vector[i].cluster_name.c_str());
+ peers[i].client_name = strdup(peer_vector[i].client_name.c_str());
+ }
+ *max_peers = static_cast<int>(peer_vector.size());
+ return 0;
+}
+
+extern "C" void rbd_mirror_peer_list_cleanup(rbd_mirror_peer_t *peers,
+ int max_peers) {
+ for (int i = 0; i < max_peers; ++i) {
+ free(peers[i].cluster_uuid);
+ free(peers[i].cluster_name);
+ free(peers[i].client_name);
+ }
+}
+
+extern "C" int rbd_mirror_peer_set_client(rados_ioctx_t p,
+ const char *cluster_uuid,
+ const char *client_name) {
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+ return librbd::mirror_peer_set_client(io_ctx, cluster_uuid, client_name);
+}
+
+extern "C" int rbd_mirror_peer_set_cluster(rados_ioctx_t p,
+ const char *cluster_uuid,
+ const char *cluster_name) {
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+ return librbd::mirror_peer_set_cluster(io_ctx, cluster_uuid, cluster_name);
+}
+
/* images */
extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
{