Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / tools / rbd_mirror / image_replayer / CreateImageRequest.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 "CreateImageRequest.h"
5 #include "CloseImageRequest.h"
6 #include "OpenImageRequest.h"
7 #include "common/errno.h"
8 #include "common/WorkQueue.h"
9 #include "cls/rbd/cls_rbd_client.h"
10 #include "librbd/ImageCtx.h"
11 #include "librbd/ImageState.h"
12 #include "librbd/internal.h"
13 #include "librbd/Utils.h"
14 #include "librbd/image/CreateRequest.h"
15 #include "librbd/image/CloneRequest.h"
16
17 #define dout_context g_ceph_context
18 #define dout_subsys ceph_subsys_rbd_mirror
19 #undef dout_prefix
20 #define dout_prefix *_dout << "rbd::mirror::image_replayer::CreateImageRequest: " \
21                            << this << " " << __func__
22
23 using librbd::util::create_context_callback;
24 using librbd::util::create_rados_callback;
25
26 namespace rbd {
27 namespace mirror {
28 namespace image_replayer {
29
30 template <typename I>
31 CreateImageRequest<I>::CreateImageRequest(librados::IoCtx &local_io_ctx,
32                                           ContextWQ *work_queue,
33                                           const std::string &global_image_id,
34                                           const std::string &remote_mirror_uuid,
35                                           const std::string &local_image_name,
36                                           const std::string &local_image_id,
37                                           I *remote_image_ctx,
38                                           Context *on_finish)
39   : m_local_io_ctx(local_io_ctx), m_work_queue(work_queue),
40     m_global_image_id(global_image_id),
41     m_remote_mirror_uuid(remote_mirror_uuid),
42     m_local_image_name(local_image_name), m_local_image_id(local_image_id),
43     m_remote_image_ctx(remote_image_ctx), m_on_finish(on_finish) {
44 }
45
46 template <typename I>
47 void CreateImageRequest<I>::send() {
48   int r = validate_parent();
49   if (r < 0) {
50     error(r);
51     return;
52   }
53
54   if (m_remote_parent_spec.pool_id == -1) {
55     create_image();
56   } else {
57     get_parent_global_image_id();
58   }
59 }
60
61 template <typename I>
62 void CreateImageRequest<I>::create_image() {
63   dout(20) << dendl;
64
65   using klass = CreateImageRequest<I>;
66   Context *ctx = create_context_callback<klass, &klass::handle_create_image>(this);
67
68   RWLock::RLocker snap_locker(m_remote_image_ctx->snap_lock);
69
70   librbd::ImageOptions image_options;
71   image_options.set(RBD_IMAGE_OPTION_FEATURES, m_remote_image_ctx->features);
72   image_options.set(RBD_IMAGE_OPTION_ORDER, m_remote_image_ctx->order);
73   image_options.set(RBD_IMAGE_OPTION_STRIPE_UNIT,
74                     m_remote_image_ctx->stripe_unit);
75   image_options.set(RBD_IMAGE_OPTION_STRIPE_COUNT,
76                     m_remote_image_ctx->stripe_count);
77   image_options.set(RBD_IMAGE_OPTION_DATA_POOL,
78                     m_remote_image_ctx->data_ctx.get_pool_name());
79
80   librbd::image::CreateRequest<I> *req = librbd::image::CreateRequest<I>::create(
81     m_local_io_ctx, m_local_image_name, m_local_image_id,
82     m_remote_image_ctx->size, image_options, m_global_image_id,
83     m_remote_mirror_uuid, false, m_remote_image_ctx->op_work_queue, ctx);
84   req->send();
85 }
86
87 template <typename I>
88 void CreateImageRequest<I>::handle_create_image(int r) {
89   dout(20) << ": r=" << r << dendl;
90   if (r < 0) {
91     derr << ": failed to create local image: " << cpp_strerror(r) << dendl;
92     finish(r);
93     return;
94   }
95
96   finish(0);
97 }
98
99 template <typename I>
100 void CreateImageRequest<I>::get_parent_global_image_id() {
101   dout(20) << dendl;
102
103   librados::ObjectReadOperation op;
104   librbd::cls_client::mirror_image_get_start(&op, m_remote_parent_spec.image_id);
105
106   librados::AioCompletion *aio_comp = create_rados_callback<
107     CreateImageRequest<I>,
108     &CreateImageRequest<I>::handle_get_parent_global_image_id>(this);
109   m_out_bl.clear();
110   int r = m_remote_parent_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op,
111                                              &m_out_bl);
112   assert(r == 0);
113   aio_comp->release();
114 }
115
116 template <typename I>
117 void CreateImageRequest<I>::handle_get_parent_global_image_id(int r) {
118   dout(20) << ": r=" << r << dendl;
119   if (r == 0) {
120     cls::rbd::MirrorImage mirror_image;
121     bufferlist::iterator iter = m_out_bl.begin();
122     r = librbd::cls_client::mirror_image_get_finish(&iter, &mirror_image);
123     if (r == 0) {
124       m_parent_global_image_id = mirror_image.global_image_id;
125       dout(20) << ": parent_global_image_id=" << m_parent_global_image_id
126                << dendl;
127     }
128   }
129
130   if (r == -ENOENT) {
131     dout(10) << ": parent image " << m_remote_parent_spec.image_id << " not mirrored"
132              << dendl;
133     finish(r);
134     return;
135   } else if (r < 0) {
136     derr << ": failed to retrieve global image id for parent image "
137          << m_remote_parent_spec.image_id << ": " << cpp_strerror(r) << dendl;
138     finish(r);
139     return;
140   }
141
142   get_local_parent_image_id();
143 }
144
145 template <typename I>
146 void CreateImageRequest<I>::get_local_parent_image_id() {
147   dout(20) << dendl;
148
149   librados::ObjectReadOperation op;
150   librbd::cls_client::mirror_image_get_image_id_start(
151     &op, m_parent_global_image_id);
152
153   librados::AioCompletion *aio_comp = create_rados_callback<
154     CreateImageRequest<I>,
155     &CreateImageRequest<I>::handle_get_local_parent_image_id>(this);
156   m_out_bl.clear();
157   int r = m_local_parent_io_ctx.aio_operate(RBD_MIRRORING, aio_comp, &op,
158                                             &m_out_bl);
159   assert(r == 0);
160   aio_comp->release();
161 }
162
163 template <typename I>
164 void CreateImageRequest<I>::handle_get_local_parent_image_id(int r) {
165   dout(20) << ": r=" << r << dendl;
166
167   if (r == 0) {
168     bufferlist::iterator iter = m_out_bl.begin();
169     r = librbd::cls_client::mirror_image_get_image_id_finish(
170       &iter, &m_local_parent_spec.image_id);
171   }
172
173   if (r == -ENOENT) {
174     dout(10) << ": parent image " << m_parent_global_image_id << " not "
175              << "registered locally" << dendl;
176     finish(r);
177     return;
178   } else if (r < 0) {
179     derr << ": failed to retrieve local image id for parent image "
180          << m_parent_global_image_id << ": " << cpp_strerror(r) << dendl;
181     finish(r);
182     return;
183   }
184
185   open_remote_parent_image();
186 }
187
188 template <typename I>
189 void CreateImageRequest<I>::open_remote_parent_image() {
190   dout(20) << dendl;
191
192   Context *ctx = create_context_callback<
193     CreateImageRequest<I>,
194     &CreateImageRequest<I>::handle_open_remote_parent_image>(this);
195   OpenImageRequest<I> *request = OpenImageRequest<I>::create(
196     m_remote_parent_io_ctx, &m_remote_parent_image_ctx,
197     m_remote_parent_spec.image_id, true, ctx);
198   request->send();
199 }
200
201 template <typename I>
202 void CreateImageRequest<I>::handle_open_remote_parent_image(int r) {
203   dout(20) << ": r=" << r << dendl;
204   if (r < 0) {
205     derr << ": failed to open remote parent image " << m_parent_pool_name << "/"
206          << m_remote_parent_spec.image_id << dendl;
207     finish(r);
208     return;
209   }
210
211   open_local_parent_image();
212 }
213
214 template <typename I>
215 void CreateImageRequest<I>::open_local_parent_image() {
216   dout(20) << dendl;
217
218   Context *ctx = create_context_callback<
219     CreateImageRequest<I>,
220     &CreateImageRequest<I>::handle_open_local_parent_image>(this);
221   OpenImageRequest<I> *request = OpenImageRequest<I>::create(
222     m_local_parent_io_ctx, &m_local_parent_image_ctx,
223     m_local_parent_spec.image_id, true, ctx);
224   request->send();
225 }
226
227 template <typename I>
228 void CreateImageRequest<I>::handle_open_local_parent_image(int r) {
229   dout(20) << ": r=" << r << dendl;
230   if (r < 0) {
231     derr << ": failed to open local parent image " << m_parent_pool_name << "/"
232          << m_local_parent_spec.image_id << dendl;
233     m_ret_val = r;
234     close_remote_parent_image();
235     return;
236   }
237
238   set_local_parent_snap();
239 }
240
241 template <typename I>
242 void CreateImageRequest<I>::set_local_parent_snap() {
243   dout(20) << dendl;
244
245   {
246     RWLock::RLocker remote_snap_locker(m_remote_parent_image_ctx->snap_lock);
247     auto it = m_remote_parent_image_ctx->snap_info.find(
248       m_remote_parent_spec.snap_id);
249     if (it != m_remote_parent_image_ctx->snap_info.end()) {
250       m_parent_snap_name = it->second.name;
251     }
252   }
253
254   if (m_parent_snap_name.empty()) {
255     m_ret_val = -ENOENT;
256     close_local_parent_image();
257     return;
258   }
259   dout(20) << ": parent_snap_name=" << m_parent_snap_name << dendl;
260
261   Context *ctx = create_context_callback<
262     CreateImageRequest<I>,
263     &CreateImageRequest<I>::handle_set_local_parent_snap>(this);
264   m_local_parent_image_ctx->state->snap_set(cls::rbd::UserSnapshotNamespace(),
265                                             m_parent_snap_name,
266                                             ctx);
267 }
268
269 template <typename I>
270 void CreateImageRequest<I>::handle_set_local_parent_snap(int r) {
271   dout(20) << ": r=" << r << dendl;
272   if (r < 0) {
273     derr << ": failed to set parent snapshot " << m_parent_snap_name
274          << ": " << cpp_strerror(r) << dendl;
275     m_ret_val = r;
276     close_local_parent_image();
277     return;
278   }
279
280   clone_image();
281 }
282
283 template <typename I>
284 void CreateImageRequest<I>::clone_image() {
285   dout(20) << dendl;
286
287   librbd::ImageOptions opts;
288   opts.set(RBD_IMAGE_OPTION_FEATURES, m_remote_image_ctx->features);
289   opts.set(RBD_IMAGE_OPTION_ORDER, m_remote_image_ctx->order);
290   opts.set(RBD_IMAGE_OPTION_STRIPE_UNIT, m_remote_image_ctx->stripe_unit);
291   opts.set(RBD_IMAGE_OPTION_STRIPE_COUNT, m_remote_image_ctx->stripe_count);
292
293   using klass = CreateImageRequest<I>;
294   Context *ctx = create_context_callback<klass, &klass::handle_clone_image>(this);
295
296   librbd::image::CloneRequest<I> *req = librbd::image::CloneRequest<I>::create(
297     m_local_parent_image_ctx, m_local_io_ctx, m_local_image_name,
298     m_local_image_id, opts, m_global_image_id, m_remote_mirror_uuid,
299     m_remote_image_ctx->op_work_queue, ctx);
300   req->send();
301 }
302
303 template <typename I>
304 void CreateImageRequest<I>::handle_clone_image(int r) {
305   dout(20) << ": r=" << r << dendl;
306   if (r < 0) {
307     derr << ": failed to clone image " << m_parent_pool_name << "/"
308          << m_local_parent_image_ctx->name << " to "
309          << m_local_image_name << dendl;
310     m_ret_val = r;
311   }
312
313   close_local_parent_image();
314 }
315
316 template <typename I>
317 void CreateImageRequest<I>::close_local_parent_image() {
318   dout(20) << dendl;
319   Context *ctx = create_context_callback<
320     CreateImageRequest<I>,
321     &CreateImageRequest<I>::handle_close_local_parent_image>(this);
322   CloseImageRequest<I> *request = CloseImageRequest<I>::create(
323     &m_local_parent_image_ctx, ctx);
324   request->send();
325 }
326
327 template <typename I>
328 void CreateImageRequest<I>::handle_close_local_parent_image(int r) {
329   dout(20) << ": r=" << r << dendl;
330   if (r < 0) {
331     derr << ": error encountered closing local parent image: "
332          << cpp_strerror(r) << dendl;
333   }
334
335   close_remote_parent_image();
336 }
337
338 template <typename I>
339 void CreateImageRequest<I>::close_remote_parent_image() {
340   dout(20) << dendl;
341   Context *ctx = create_context_callback<
342     CreateImageRequest<I>,
343     &CreateImageRequest<I>::handle_close_remote_parent_image>(this);
344   CloseImageRequest<I> *request = CloseImageRequest<I>::create(
345     &m_remote_parent_image_ctx, ctx);
346   request->send();
347 }
348
349 template <typename I>
350 void CreateImageRequest<I>::handle_close_remote_parent_image(int r) {
351   dout(20) << ": r=" << r << dendl;
352   if (r < 0) {
353     derr << ": error encountered closing remote parent image: "
354          << cpp_strerror(r) << dendl;
355   }
356
357   finish(m_ret_val);
358 }
359
360 template <typename I>
361 void CreateImageRequest<I>::error(int r) {
362   dout(20) << ": r=" << r << dendl;
363
364   m_work_queue->queue(create_context_callback<
365     CreateImageRequest<I>, &CreateImageRequest<I>::finish>(this), r);
366 }
367
368 template <typename I>
369 void CreateImageRequest<I>::finish(int r) {
370   dout(20) << ": r=" << r << dendl;
371   m_on_finish->complete(r);
372   delete this;
373 }
374
375 template <typename I>
376 int CreateImageRequest<I>::validate_parent() {
377   RWLock::RLocker owner_locker(m_remote_image_ctx->owner_lock);
378   RWLock::RLocker snap_locker(m_remote_image_ctx->snap_lock);
379
380   m_remote_parent_spec = m_remote_image_ctx->parent_md.spec;
381
382   // scan all remote snapshots for a linked parent
383   for (auto &snap_info_pair : m_remote_image_ctx->snap_info) {
384     auto &parent_spec = snap_info_pair.second.parent.spec;
385     if (parent_spec.pool_id == -1) {
386       continue;
387     } else if (m_remote_parent_spec.pool_id == -1) {
388       m_remote_parent_spec = parent_spec;
389       continue;
390     }
391
392     if (m_remote_parent_spec != parent_spec) {
393       derr << ": remote image parent spec mismatch" << dendl;
394       return -EINVAL;
395     }
396   }
397
398   if (m_remote_parent_spec.pool_id == -1) {
399     return 0;
400   }
401
402   // map remote parent pool to local parent pool
403   librados::Rados remote_rados(m_remote_image_ctx->md_ctx);
404   int r = remote_rados.ioctx_create2(m_remote_parent_spec.pool_id,
405                                      m_remote_parent_io_ctx);
406   if (r < 0) {
407     derr << ": failed to open remote parent pool " << m_remote_parent_spec.pool_id
408          << ": " << cpp_strerror(r) << dendl;
409     return r;
410   }
411
412   m_parent_pool_name = m_remote_parent_io_ctx.get_pool_name();
413
414   librados::Rados local_rados(m_local_io_ctx);
415   r = local_rados.ioctx_create(m_parent_pool_name.c_str(),
416                                m_local_parent_io_ctx);
417   if (r < 0) {
418     derr << ": failed to open local parent pool " << m_parent_pool_name << ": "
419          << cpp_strerror(r) << dendl;
420     return r;
421   }
422
423   return 0;
424 }
425
426 } // namespace image_replayer
427 } // namespace mirror
428 } // namespace rbd
429
430 template class rbd::mirror::image_replayer::CreateImageRequest<librbd::ImageCtx>;