return 0;
}
+int validate_mirroring_enabled(ImageCtx *ictx) {
+ CephContext *cct = ictx->cct;
+ cls::rbd::MirrorImage mirror_image_internal;
+ int r = cls_client::mirror_image_get(&ictx->md_ctx, ictx->id,
+ &mirror_image_internal);
+ if (r < 0 && r != -ENOENT) {
+ lderr(cct) << "failed to retrieve mirroring state: " << cpp_strerror(r)
+ << dendl;
+ return r;
+ } else if (mirror_image_internal.state !=
+ cls::rbd::MirrorImageState::MIRROR_IMAGE_STATE_ENABLED) {
+ lderr(cct) << "mirroring is not currently enabled" << dendl;
+ return -EINVAL;
+ }
+ return 0;
+}
+
} // anonymous namespace
int detect_format(IoCtx &io_ctx, const string &name,
CephContext *cct = ictx->cct;
ldout(cct, 20) << __func__ << ": ictx=" << ictx << ", "
<< "force=" << force << dendl;
- return -EOPNOTSUPP;
+
+ int r = validate_mirroring_enabled(ictx);
+ if (r < 0) {
+ return r;
+ }
+
+ std::string mirror_uuid;
+ r = Journal<>::get_tag_owner(ictx, &mirror_uuid);
+ if (r < 0) {
+ lderr(cct) << "failed to determine tag ownership: " << cpp_strerror(r)
+ << dendl;
+ return r;
+ } else if (mirror_uuid == Journal<>::LOCAL_MIRROR_UUID) {
+ lderr(cct) << "image is already primary" << dendl;
+ return -EINVAL;
+ } else if (mirror_uuid != Journal<>::ORPHAN_MIRROR_UUID && !force) {
+ lderr(cct) << "image is still primary within a remote cluster" << dendl;
+ return -EBUSY;
+ }
+
+ // TODO: need interlock with local rbd-mirror daemon to ensure it has stopped
+ // replay
+
+ r = Journal<>::allocate_tag(ictx, Journal<>::LOCAL_MIRROR_UUID);
+ if (r < 0) {
+ lderr(cct) << "failed to promote image: " << cpp_strerror(r)
+ << dendl;
+ return r;
+ }
+ return 0;
}
int mirror_image_demote(ImageCtx *ictx) {
CephContext *cct = ictx->cct;
ldout(cct, 20) << __func__ << ": ictx=" << ictx << dendl;
- return -EOPNOTSUPP;
+
+ int r = validate_mirroring_enabled(ictx);
+ if (r < 0) {
+ return r;
+ }
+
+ bool is_primary;
+ r = Journal<>::is_tag_owner(ictx, &is_primary);
+ if (r < 0) {
+ lderr(cct) << "failed to determine tag ownership: " << cpp_strerror(r)
+ << dendl;
+ return r;
+ }
+
+ if (!is_primary) {
+ lderr(cct) << "image is not currently the primary" << dendl;
+ return -EINVAL;
+ }
+
+ RWLock::RLocker owner_lock(ictx->owner_lock);
+ C_SaferCond lock_ctx;
+ ictx->exclusive_lock->request_lock(&lock_ctx);
+ r = lock_ctx.wait();
+ if (r < 0) {
+ lderr(cct) << "failed to lock image: " << cpp_strerror(r) << dendl;
+ } else if (!ictx->exclusive_lock->is_lock_owner()) {
+ lderr(cct) << "failed to acquire exclusive lock" << dendl;
+ }
+
+ r = Journal<>::allocate_tag(ictx, Journal<>::ORPHAN_MIRROR_UUID);
+ if (r < 0) {
+ lderr(cct) << "failed to demote image: " << cpp_strerror(r)
+ << dendl;
+ return r;
+ }
+ return 0;
}
int mirror_image_resync(ImageCtx *ictx) {