CEPH_RBD_API int rbd_mirror_image_status_summary(rados_ioctx_t io_ctx,
rbd_mirror_image_status_state_t *states, int *counts, size_t *maxlen);
+CEPH_RBD_API int rbd_mirror_image_instance_id_list(rados_ioctx_t io_ctx,
+ const char *start_id,
+ size_t max, char **image_ids,
+ char **instance_ids,
+ size_t *len);
+CEPH_RBD_API void rbd_mirror_image_instance_id_list_cleanup(char **image_ids,
+ char **instance_ids,
+ size_t len);
+
/* pool metadata */
CEPH_RBD_API int rbd_pool_metadata_get(rados_ioctx_t io_ctx, const char *key,
char *value, size_t *val_len);
CEPH_RBD_API int rbd_mirror_image_get_status(rbd_image_t image,
rbd_mirror_image_status_t *mirror_image_status,
size_t status_size);
+CEPH_RBD_API int rbd_mirror_image_get_instance_id(rbd_image_t image,
+ char *instance_id,
+ size_t *id_max_length);
CEPH_RBD_API int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
rbd_completion_t c);
CEPH_RBD_API int rbd_aio_mirror_image_demote(rbd_image_t image,
size_t max, std::map<std::string, mirror_image_status_t> *images);
int mirror_image_status_summary(IoCtx& io_ctx,
std::map<mirror_image_status_state_t, int> *states);
+ int mirror_image_instance_id_list(IoCtx& io_ctx, const std::string &start_id,
+ size_t max, std::map<std::string, std::string> *sevice_ids);
// RBD groups support functions
int group_create(IoCtx& io_ctx, const char *group_name);
size_t info_size);
int mirror_image_get_status(mirror_image_status_t *mirror_image_status,
size_t status_size);
+ int mirror_image_get_instance_id(std::string *instance_id);
int aio_mirror_image_promote(bool force, RBD::AioCompletion *c);
int aio_mirror_image_demote(RBD::AioCompletion *c);
int aio_mirror_image_get_info(mirror_image_info_t *mirror_image_info,
return 0;
}
+template <typename I>
+int Mirror<I>::image_get_instance_id(I *ictx, std::string *instance_id) {
+ CephContext *cct = ictx->cct;
+ ldout(cct, 20) << "ictx=" << ictx << dendl;
+
+ cls::rbd::MirrorImage mirror_image;
+ int r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id, &mirror_image);
+ if (r < 0 && r != -ENOENT) {
+ lderr(cct) << "failed to retrieve mirroring state: " << cpp_strerror(r)
+ << dendl;
+ return r;
+ } else if (mirror_image.state != cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
+ lderr(cct) << "mirroring is not currently enabled" << dendl;
+ return -EINVAL;
+ }
+
+ entity_inst_t instance;
+ r = cls_client::mirror_image_instance_get(&ictx->md_ctx,
+ mirror_image.global_image_id,
+ &instance);
+ if (r < 0) {
+ if (r != -ENOENT && r != -ESTALE) {
+ lderr(cct) << "failed to get mirror image instance: " << cpp_strerror(r)
+ << dendl;
+ }
+ return r;
+ }
+
+ *instance_id = stringify(instance.name.num());
+ return 0;
+}
+
template <typename I>
int Mirror<I>::mode_get(librados::IoCtx& io_ctx,
rbd_mirror_mode_t *mirror_mode) {
return 0;
}
+template <typename I>
+int Mirror<I>::image_instance_id_list(
+ librados::IoCtx& io_ctx, const std::string &start_image_id, size_t max,
+ std::map<std::string, std::string> *instance_ids) {
+ CephContext *cct = reinterpret_cast<CephContext *>(io_ctx.cct());
+ std::map<std::string, entity_inst_t> instances;
+
+ int r = librbd::cls_client::mirror_image_instance_list(
+ &io_ctx, start_image_id, max, &instances);
+ if (r < 0 && r != -ENOENT) {
+ lderr(cct) << "failed to list mirror image instances: " << cpp_strerror(r)
+ << dendl;
+ return r;
+ }
+
+ for (auto it : instances) {
+ (*instance_ids)[it.first] = stringify(it.second.name.num());
+ }
+
+ return 0;
+}
+
} // namespace api
} // namespace librbd
IdToMirrorImageStatus *images);
static int image_status_summary(librados::IoCtx& io_ctx,
MirrorImageStatusStates *states);
+ static int image_instance_id_list(librados::IoCtx& io_ctx,
+ const std::string &start_image_id,
+ size_t max,
+ std::map<std::string, std::string> *ids);
static int image_enable(ImageCtxT *ictx, bool relax_same_pool_parent_check);
static int image_disable(ImageCtxT *ictx, bool force);
static int image_get_status(ImageCtxT *ictx, mirror_image_status_t *status);
static void image_get_status(ImageCtxT *ictx, mirror_image_status_t *status,
Context *on_finish);
-
+ static int image_get_instance_id(ImageCtxT *ictx, std::string *instance_id);
};
} // namespace api
return librbd::api::Mirror<>::image_status_summary(io_ctx, states);
}
+ int RBD::mirror_image_instance_id_list(IoCtx& io_ctx,
+ const std::string &start_id, size_t max,
+ std::map<std::string, std::string> *instance_ids) {
+ return librbd::api::Mirror<>::image_instance_id_list(io_ctx, start_id, max,
+ instance_ids);
+ }
+
int RBD::group_create(IoCtx& io_ctx, const char *group_name)
{
TracepointProvider::initialize<tracepoint_traits>(get_cct(io_ctx));
return librbd::api::Mirror<>::image_get_status(ictx, mirror_image_status);
}
+ int Image::mirror_image_get_instance_id(std::string *instance_id) {
+ ImageCtx *ictx = (ImageCtx *)ctx;
+
+ return librbd::api::Mirror<>::image_get_instance_id(ictx, instance_id);
+ }
+
int Image::aio_mirror_image_promote(bool force, RBD::AioCompletion *c) {
ImageCtx *ictx = (ImageCtx *)ctx;
librbd::api::Mirror<>::image_promote(
return 0;
}
+extern "C" int rbd_mirror_image_instance_id_list(
+ rados_ioctx_t p, const char *start_id, size_t max, char **image_ids,
+ char **instance_ids, size_t *len) {
+ librados::IoCtx io_ctx;
+ librados::IoCtx::from_rados_ioctx_t(p, io_ctx);
+ std::map<std::string, std::string> cpp_instance_ids;
+
+ int r = librbd::api::Mirror<>::image_instance_id_list(io_ctx, start_id, max,
+ &cpp_instance_ids);
+ if (r < 0) {
+ return r;
+ }
+
+ size_t i = 0;
+ for (auto &it : cpp_instance_ids) {
+ ceph_assert(i < max);
+ image_ids[i] = strdup(it.first.c_str());
+ instance_ids[i] = strdup(it.second.c_str());
+ i++;
+ }
+ *len = i;
+ return 0;
+}
+
+extern "C" void rbd_mirror_image_instance_id_list_cleanup(
+ char **image_ids, char **instance_ids, size_t len) {
+ for (size_t i = 0; i < len; i++) {
+ free(image_ids[i]);
+ free(instance_ids[i]);
+ }
+}
+
/* images */
extern "C" int rbd_list(rados_ioctx_t p, char *names, size_t *size)
{
return 0;
}
+extern "C" int rbd_mirror_image_get_instance_id(rbd_image_t image,
+ char *instance_id,
+ size_t *instance_id_max_length)
+{
+ librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
+
+ std::string cpp_instance_id;
+ int r = librbd::api::Mirror<>::image_get_instance_id(ictx, &cpp_instance_id);
+ if (r < 0) {
+ return r;
+ }
+
+ if (cpp_instance_id.size() >= *instance_id_max_length) {
+ *instance_id_max_length = cpp_instance_id.size() + 1;
+ return -ERANGE;
+ }
+
+ strcpy(instance_id, cpp_instance_id.c_str());
+ *instance_id_max_length = cpp_instance_id.size() + 1;
+ return 0;
+}
+
extern "C" int rbd_aio_mirror_image_promote(rbd_image_t image, bool force,
rbd_completion_t c) {
librbd::ImageCtx *ictx = (librbd::ImageCtx *)image;
int rbd_mirror_image_status_summary(rados_ioctx_t io,
rbd_mirror_image_status_state_t *states,
int *counts, size_t *maxlen)
+ int rbd_mirror_image_instance_id_list(rados_ioctx_t io_ctx,
+ const char *start_id,
+ size_t max, char **image_ids,
+ char **instance_ids,
+ size_t *len)
+ void rbd_mirror_image_instance_id_list_cleanup(char **image_ids,
+ char **instance_ids,
+ size_t len)
int rbd_pool_metadata_get(rados_ioctx_t io_ctx, const char *key,
char *value, size_t *val_len)
int rbd_mirror_image_get_status(rbd_image_t image,
rbd_mirror_image_status_t *mirror_image_status,
size_t status_size)
+ int rbd_mirror_image_get_instance_id(rbd_image_t image, char *instance_id,
+ size_t *id_max_length)
int rbd_aio_write2(rbd_image_t image, uint64_t off, size_t len,
const char *buf, rbd_completion_t c, int op_flags)
:param ioctx: determines which RADOS pool is read
:type ioctx: :class:`rados.Ioctx`
- :returns: :class:`MirrorImageStatus`
+ :returns: :class:`MirrorImageStatusIterator`
"""
return MirrorImageStatusIterator(ioctx)
free(states)
free(counts)
+ def mirror_image_instance_id_list(self, ioctx):
+ """
+ Iterate over the mirror image instance ids of a pool.
+
+ :param ioctx: determines which RADOS pool is read
+ :type ioctx: :class:`rados.Ioctx`
+ :returns: :class:`MirrorImageInstanceIdIterator`
+ """
+ return MirrorImageInstanceIdIterator(ioctx)
+
def pool_metadata_get(self, ioctx, key):
"""
Get pool metadata for the given key.
* ``name`` (str) - mirror image name
+ * ``id`` (str) - mirror image id
+
* `info` (dict) - mirror image info
* `state` (int) - mirror state
for i in range(self.size):
yield {
'name' : decode_cstr(self.images[i].name),
+ 'id' : decode_cstr(self.image_ids[i]),
'info' : {
'global_id' : decode_cstr(self.images[i].info.global_id),
'state' : self.images[i].info.state,
free(self.last_read)
self.last_read = strdup("")
+cdef class MirrorImageInstanceIdIterator(object):
+ """
+ Iterator over mirror image instance id for a pool.
+
+ Yields ``(image_id, instance_id)`` tuple.
+ """
+
+ cdef:
+ rados_ioctx_t ioctx
+ size_t max_read
+ char *last_read
+ char **image_ids
+ char **instance_ids
+ size_t size
+
+ def __init__(self, ioctx):
+ self.ioctx = convert_ioctx(ioctx)
+ self.max_read = 1024
+ self.last_read = strdup("")
+ self.image_ids = <char **>realloc_chk(NULL,
+ sizeof(char *) * self.max_read)
+ self.instance_ids = <char **>realloc_chk(NULL,
+ sizeof(char *) * self.max_read)
+ self.size = 0
+ self.get_next_chunk()
+
+ def __iter__(self):
+ while self.size > 0:
+ for i in range(self.size):
+ yield (decode_cstr(self.image_ids[i]),
+ decode_cstr(self.instance_ids[i]))
+ if self.size < self.max_read:
+ break
+ self.get_next_chunk()
+
+ def __dealloc__(self):
+ rbd_mirror_image_instance_id_list_cleanup(self.image_ids,
+ self.instance_ids, self.size)
+ if self.last_read:
+ free(self.last_read)
+ if self.image_ids:
+ free(self.image_ids)
+ if self.instance_ids:
+ free(self.instance_ids)
+
+ def get_next_chunk(self):
+ if self.size > 0:
+ rbd_mirror_image_instance_id_list_cleanup(self.image_ids,
+ self.instance_ids,
+ self.size)
+ self.size = 0
+ with nogil:
+ ret = rbd_mirror_image_instance_id_list(self.ioctx, self.last_read,
+ self.max_read,
+ self.image_ids,
+ self.instance_ids,
+ &self.size)
+ if ret < 0:
+ raise make_ex(ret, 'error listing mirror images instance ids')
+ if self.size > 0:
+ free(self.last_read)
+ last_read = decode_cstr(self.image_ids[self.size - 1])
+ self.last_read = strdup(last_read)
+ else:
+ free(self.last_read)
+ self.last_read = strdup("")
+
cdef class PoolMetadataIterator(object):
"""
Iterator over pool metadata list.
* ``name`` (str) - mirror image name
+ * ``id`` (str) - mirror image id
+
* `info` (dict) - mirror image info
* ``state`` (int) - status mirror state
raise make_ex(ret, 'error getting mirror status for image %s' % self.name)
status = {
'name' : decode_cstr(c_status.name),
+ 'id' : self.id(),
'info' : {
'global_id' : decode_cstr(c_status.info.global_id),
'state' : int(c_status.info.state),
free(c_status.description)
return status
+ def mirror_image_get_instance_id(self):
+ """
+ Get mirror instance id for the image.
+
+ :returns: str - instance id
+ """
+ cdef:
+ int ret = -errno.ERANGE
+ size_t size = 32
+ char *instance_id = NULL
+ try:
+ while ret == -errno.ERANGE and size <= 4096:
+ instance_id = <char *>realloc_chk(instance_id, size)
+ with nogil:
+ ret = rbd_mirror_image_get_instance_id(self.image,
+ instance_id, &size)
+ if ret != 0:
+ raise make_ex(ret,
+ 'error getting mirror instance id for image %s' %
+ self.name)
+ return decode_cstr(instance_id)
+ finally:
+ free(instance_id)
+
def aio_read(self, offset, length, oncomplete, fadvise_flags=0):
"""
Asynchronously read data from the image
ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+ std::string instance_id;
+ ASSERT_EQ(mirror_state == RBD_MIRROR_IMAGE_ENABLED ? -ENOENT : -EINVAL,
+ image.mirror_image_get_instance_id(&instance_id));
+
ASSERT_EQ(0, image.close());
ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str()));
ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED));
ASSERT_EQ(0, image.mirror_image_get_status(&status, sizeof(status)));
ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, status.state);
+ std::string instance_id;
+ ASSERT_EQ(mirror_state == RBD_MIRROR_IMAGE_ENABLED ? -ENOENT : -EINVAL,
+ image.mirror_image_get_instance_id(&instance_id));
+
ASSERT_EQ(0, image.close());
ASSERT_EQ(0, m_rbd.remove(m_ioctx, image_name.c_str()));
ASSERT_EQ(0, m_rbd.mirror_mode_set(m_ioctx, RBD_MIRROR_MODE_DISABLED));
ASSERT_EQ(images.size(), states_count);
*images_count = images.size();
+
+ std::map<std::string, std::string> instance_ids;
+ ASSERT_EQ(0, m_rbd.mirror_image_instance_id_list(m_ioctx, "", 4096,
+ &instance_ids));
+ ASSERT_TRUE(instance_ids.empty());
}
void check_mirroring_on_create(uint64_t features,
states = self.rbd.mirror_image_status_summary(ioctx)
eq([(MIRROR_IMAGE_STATUS_STATE_UNKNOWN, 1)], states)
+ assert_raises(ImageNotFound, self.image.mirror_image_get_instance_id)
+ instance_ids = list(self.rbd.mirror_image_instance_id_list(ioctx))
+ eq(0, len(instance_ids))
+
N = 65
for i in range(N):
self.rbd.create(ioctx, image_name + str(i), IMG_SIZE, IMG_ORDER,