Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / tools / rbd_mirror / image_sync / SyncPointCreateRequest.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 "SyncPointCreateRequest.h"
5 #include "include/uuid.h"
6 #include "common/errno.h"
7 #include "journal/Journaler.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/ImageState.h"
10 #include "librbd/Operations.h"
11 #include "librbd/Utils.h"
12
13 #define dout_context g_ceph_context
14 #define dout_subsys ceph_subsys_rbd_mirror
15 #undef dout_prefix
16 #define dout_prefix *_dout << "rbd::mirror::image_sync::SyncPointCreateRequest: " \
17                            << this << " " << __func__
18
19 namespace rbd {
20 namespace mirror {
21 namespace image_sync {
22
23 namespace {
24
25 static const std::string SNAP_NAME_PREFIX(".rbd-mirror");
26
27 } // anonymous namespace
28
29 using librbd::util::create_context_callback;
30
31 template <typename I>
32 SyncPointCreateRequest<I>::SyncPointCreateRequest(I *remote_image_ctx,
33                                                   const std::string &mirror_uuid,
34                                                   Journaler *journaler,
35                                                   MirrorPeerClientMeta *client_meta,
36                                                   Context *on_finish)
37   : m_remote_image_ctx(remote_image_ctx), m_mirror_uuid(mirror_uuid),
38     m_journaler(journaler), m_client_meta(client_meta), m_on_finish(on_finish),
39     m_client_meta_copy(*client_meta) {
40   assert(m_client_meta->sync_points.size() < 2);
41
42   // initialize the updated client meta with the new sync point
43   m_client_meta_copy.sync_points.emplace_back();
44   if (m_client_meta_copy.sync_points.size() > 1) {
45     m_client_meta_copy.sync_points.back().from_snap_name =
46       m_client_meta_copy.sync_points.front().snap_name;
47   }
48 }
49
50 template <typename I>
51 void SyncPointCreateRequest<I>::send() {
52   send_update_client();
53 }
54
55 template <typename I>
56 void SyncPointCreateRequest<I>::send_update_client() {
57   uuid_d uuid_gen;
58   uuid_gen.generate_random();
59
60   MirrorPeerSyncPoint &sync_point = m_client_meta_copy.sync_points.back();
61   sync_point.snap_name = SNAP_NAME_PREFIX + "." + m_mirror_uuid + "." +
62                          uuid_gen.to_string();
63
64   dout(20) << ": sync_point=" << sync_point << dendl;
65
66   bufferlist client_data_bl;
67   librbd::journal::ClientData client_data(m_client_meta_copy);
68   ::encode(client_data, client_data_bl);
69
70   Context *ctx = create_context_callback<
71     SyncPointCreateRequest<I>, &SyncPointCreateRequest<I>::handle_update_client>(
72       this);
73   m_journaler->update_client(client_data_bl, ctx);
74 }
75
76 template <typename I>
77 void SyncPointCreateRequest<I>::handle_update_client(int r) {
78   dout(20) << ": r=" << r << dendl;
79
80   if (r < 0) {
81     derr << ": failed to update client data: " << cpp_strerror(r)
82          << dendl;
83     finish(r);
84     return;
85   }
86
87   // update provided meta structure to reflect reality
88   *m_client_meta = m_client_meta_copy;
89
90   send_refresh_image();
91 }
92
93 template <typename I>
94 void SyncPointCreateRequest<I>::send_refresh_image() {
95   dout(20) << dendl;
96
97   Context *ctx = create_context_callback<
98     SyncPointCreateRequest<I>, &SyncPointCreateRequest<I>::handle_refresh_image>(
99       this);
100   m_remote_image_ctx->state->refresh(ctx);
101 }
102
103 template <typename I>
104 void SyncPointCreateRequest<I>::handle_refresh_image(int r) {
105   dout(20) << ": r=" << r << dendl;
106
107   if (r < 0) {
108     derr << ": remote image refresh failed: " << cpp_strerror(r) << dendl;
109     finish(r);
110     return;
111   }
112
113   send_create_snap();
114 }
115
116 template <typename I>
117 void SyncPointCreateRequest<I>::send_create_snap() {
118   dout(20) << dendl;
119
120   MirrorPeerSyncPoint &sync_point = m_client_meta_copy.sync_points.back();
121
122   Context *ctx = create_context_callback<
123     SyncPointCreateRequest<I>, &SyncPointCreateRequest<I>::handle_create_snap>(
124       this);
125   m_remote_image_ctx->operations->snap_create(
126     cls::rbd::UserSnapshotNamespace(), sync_point.snap_name.c_str(), ctx);
127 }
128
129 template <typename I>
130 void SyncPointCreateRequest<I>::handle_create_snap(int r) {
131   dout(20) << ": r=" << r << dendl;
132
133   if (r == -EEXIST) {
134     send_update_client();
135     return;
136   } else if (r < 0) {
137     derr << ": failed to create snapshot: " << cpp_strerror(r) << dendl;
138     finish(r);
139     return;
140   }
141
142   send_final_refresh_image();
143 }
144
145 template <typename I>
146 void SyncPointCreateRequest<I>::send_final_refresh_image() {
147   dout(20) << dendl;
148
149   Context *ctx = create_context_callback<
150     SyncPointCreateRequest<I>,
151     &SyncPointCreateRequest<I>::handle_final_refresh_image>(this);
152   m_remote_image_ctx->state->refresh(ctx);
153 }
154
155 template <typename I>
156 void SyncPointCreateRequest<I>::handle_final_refresh_image(int r) {
157   dout(20) << ": r=" << r << dendl;
158
159   if (r < 0) {
160     derr << ": failed to refresh image for snapshot: " << cpp_strerror(r)
161          << dendl;
162     finish(r);
163     return;
164   }
165
166   finish(0);
167 }
168
169 template <typename I>
170 void SyncPointCreateRequest<I>::finish(int r) {
171   dout(20) << ": r=" << r << dendl;
172
173   m_on_finish->complete(r);
174   delete this;
175 }
176
177 } // namespace image_sync
178 } // namespace mirror
179 } // namespace rbd
180
181 template class rbd::mirror::image_sync::SyncPointCreateRequest<librbd::ImageCtx>;