]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/mirror/PromoteRequest.cc
b7ae9366e20e4f073fdea0f6ce3505c4705eced1
[ceph.git] / ceph / src / librbd / mirror / PromoteRequest.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "librbd/mirror/PromoteRequest.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "cls/rbd/cls_rbd_client.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/ImageState.h"
10 #include "librbd/Journal.h"
11 #include "librbd/Utils.h"
12 #include "librbd/mirror/GetInfoRequest.h"
13 #include "librbd/mirror/snapshot/PromoteRequest.h"
14
15 #define dout_subsys ceph_subsys_rbd
16 #undef dout_prefix
17 #define dout_prefix *_dout << "librbd::mirror::PromoteRequest: " << this \
18 << " " << __func__ << ": "
19
20 namespace librbd {
21 namespace mirror {
22
23 using librbd::util::create_context_callback;
24
25 template <typename I>
26 void PromoteRequest<I>::send() {
27 get_info();
28 }
29
30 template <typename I>
31 void PromoteRequest<I>::get_info() {
32 CephContext *cct = m_image_ctx.cct;
33 ldout(cct, 20) << dendl;
34
35 auto ctx = create_context_callback<
36 PromoteRequest<I>, &PromoteRequest<I>::handle_get_info>(this);
37 auto req = GetInfoRequest<I>::create(m_image_ctx, &m_mirror_image,
38 &m_promotion_state,
39 &m_primary_mirror_uuid, ctx);
40 req->send();
41 }
42
43 template <typename I>
44 void PromoteRequest<I>::handle_get_info(int r) {
45 CephContext *cct = m_image_ctx.cct;
46 ldout(cct, 20) << "r=" << r << dendl;
47
48 if (r < 0) {
49 lderr(cct) << "failed to retrieve mirroring state: " << cpp_strerror(r)
50 << dendl;
51 finish(r);
52 return;
53 } else if (m_mirror_image.state != cls::rbd::MIRROR_IMAGE_STATE_ENABLED) {
54 lderr(cct) << "mirroring is not currently enabled" << dendl;
55 finish(-EINVAL);
56 return;
57 } else if (m_promotion_state == PROMOTION_STATE_PRIMARY) {
58 lderr(cct) << "image is already primary" << dendl;
59 finish(-EINVAL);
60 return;
61 } else if (m_promotion_state == PROMOTION_STATE_NON_PRIMARY && !m_force) {
62 lderr(cct) << "image is still primary within a remote cluster" << dendl;
63 finish(-EBUSY);
64 return;
65 }
66
67 promote();
68 }
69
70 template <typename I>
71 void PromoteRequest<I>::promote() {
72 CephContext *cct = m_image_ctx.cct;
73 ldout(cct, 20) << dendl;
74
75 auto ctx = create_context_callback<
76 PromoteRequest<I>, &PromoteRequest<I>::handle_promote>(this);
77 if (m_mirror_image.mode == cls::rbd::MIRROR_IMAGE_MODE_JOURNAL) {
78 Journal<I>::promote(&m_image_ctx, ctx);
79 } else if (m_mirror_image.mode == cls::rbd::MIRROR_IMAGE_MODE_SNAPSHOT) {
80 auto req = mirror::snapshot::PromoteRequest<I>::create(
81 &m_image_ctx, m_mirror_image.global_image_id, ctx);
82 req->send();
83 } else {
84 lderr(cct) << "unknown image mirror mode: " << m_mirror_image.mode << dendl;
85 finish(-EOPNOTSUPP);
86 }
87 }
88
89 template <typename I>
90 void PromoteRequest<I>::handle_promote(int r) {
91 CephContext *cct = m_image_ctx.cct;
92 ldout(cct, 20) << "r=" << r << dendl;
93
94 if (r < 0) {
95 lderr(cct) << "failed to promote image: " << cpp_strerror(r)
96 << dendl;
97 }
98
99 finish(r);
100 }
101
102 template <typename I>
103 void PromoteRequest<I>::finish(int r) {
104 CephContext *cct = m_image_ctx.cct;
105 ldout(cct, 20) << "r=" << r << dendl;
106
107 m_on_finish->complete(r);
108 delete this;
109 }
110
111 } // namespace mirror
112 } // namespace librbd
113
114 template class librbd::mirror::PromoteRequest<librbd::ImageCtx>;