]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/image_replayer/test_mock_CreateImageRequest.cc
9abbbcbfdf0ab133a6c9adfef6b014f4a551f4fc
[ceph.git] / ceph / src / test / rbd_mirror / image_replayer / test_mock_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 "test/rbd_mirror/test_mock_fixture.h"
5 #include "include/rbd/librbd.hpp"
6 #include "librbd/ImageState.h"
7 #include "librbd/Operations.h"
8 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
9 #include "test/librados_test_stub/MockTestMemRadosClient.h"
10 #include "test/librbd/mock/MockImageCtx.h"
11 #include "tools/rbd_mirror/image_replayer/CreateImageRequest.h"
12 #include "tools/rbd_mirror/image_replayer/CloseImageRequest.h"
13 #include "tools/rbd_mirror/image_replayer/OpenImageRequest.h"
14 #include "tools/rbd_mirror/image_replayer/OpenLocalImageRequest.h"
15 #include "librbd/image/CreateRequest.h"
16 #include "librbd/image/CloneRequest.h"
17 #include "tools/rbd_mirror/Threads.h"
18
19 namespace librbd {
20
21 namespace {
22
23 struct MockTestImageCtx : public librbd::MockImageCtx {
24 MockTestImageCtx(librbd::ImageCtx &image_ctx)
25 : librbd::MockImageCtx(image_ctx) {
26 }
27 };
28
29 } // anonymous namespace
30
31 namespace image {
32
33 template<>
34 struct CreateRequest<librbd::MockTestImageCtx> {
35 static CreateRequest *s_instance;
36 Context *on_finish = nullptr;
37
38 static CreateRequest *create(IoCtx &ioctx, const std::string &imgname,
39 const std::string &imageid, uint64_t size,
40 const librbd::ImageOptions &image_options,
41 const std::string &non_primary_global_image_id,
42 const std::string &primary_mirror_uuid,
43 bool skip_mirror_enable,
44 MockContextWQ *op_work_queue,
45 Context *on_finish) {
46 assert(s_instance != nullptr);
47 EXPECT_FALSE(non_primary_global_image_id.empty());
48 EXPECT_FALSE(primary_mirror_uuid.empty());
49 EXPECT_FALSE(skip_mirror_enable);
50 s_instance->on_finish = on_finish;
51 s_instance->construct(ioctx);
52 return s_instance;
53 }
54
55 CreateRequest() {
56 s_instance = this;
57 }
58
59 ~CreateRequest() {
60 s_instance = nullptr;
61 }
62
63 MOCK_METHOD0(send, void());
64 MOCK_METHOD1(construct, void(librados::IoCtx &ioctx));
65 };
66
67 CreateRequest<librbd::MockTestImageCtx>*
68 CreateRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
69
70 template<>
71 struct CloneRequest<librbd::MockTestImageCtx> {
72 static CloneRequest *s_instance;
73 Context *on_finish = nullptr;
74
75 static CloneRequest *create(librbd::MockTestImageCtx *p_imctx,
76 IoCtx &c_ioctx, const std::string &c_name,
77 const std::string &c_id, ImageOptions c_options,
78 const std::string &non_primary_global_image_id,
79 const std::string &primary_mirror_uuid,
80 MockContextWQ *op_work_queue, Context *on_finish) {
81 assert(s_instance != nullptr);
82 s_instance->on_finish = on_finish;
83 s_instance->construct(p_imctx);
84 return s_instance;
85 }
86
87 CloneRequest() {
88 s_instance = this;
89 }
90
91 ~CloneRequest() {
92 s_instance = nullptr;
93 }
94
95 MOCK_METHOD0(send, void());
96 MOCK_METHOD1(construct, void(librbd::MockTestImageCtx *p_imctx));
97 };
98
99 CloneRequest<librbd::MockTestImageCtx>*
100 CloneRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
101
102 } // namespace image
103 } // namespace librbd
104
105 namespace rbd {
106 namespace mirror {
107 namespace image_replayer {
108
109 template<>
110 struct CloseImageRequest<librbd::MockTestImageCtx> {
111 static CloseImageRequest* s_instance;
112 Context *on_finish = nullptr;
113
114 static CloseImageRequest* create(librbd::MockTestImageCtx **image_ctx,
115 Context *on_finish) {
116 assert(s_instance != nullptr);
117 s_instance->construct(*image_ctx);
118 s_instance->on_finish = on_finish;
119 return s_instance;
120 }
121
122 CloseImageRequest() {
123 assert(s_instance == nullptr);
124 s_instance = this;
125 }
126 ~CloseImageRequest() {
127 s_instance = nullptr;
128 }
129
130 MOCK_METHOD1(construct, void(librbd::MockTestImageCtx *image_ctx));
131 MOCK_METHOD0(send, void());
132 };
133
134 template<>
135 struct OpenImageRequest<librbd::MockTestImageCtx> {
136 static OpenImageRequest* s_instance;
137 librbd::MockTestImageCtx **image_ctx = nullptr;
138 Context *on_finish = nullptr;
139
140 static OpenImageRequest* create(librados::IoCtx &io_ctx,
141 librbd::MockTestImageCtx **image_ctx,
142 const std::string &image_id,
143 bool read_only, Context *on_finish) {
144 assert(s_instance != nullptr);
145 s_instance->image_ctx = image_ctx;
146 s_instance->on_finish = on_finish;
147 s_instance->construct(io_ctx, image_id);
148 return s_instance;
149 }
150
151 OpenImageRequest() {
152 assert(s_instance == nullptr);
153 s_instance = this;
154 }
155 ~OpenImageRequest() {
156 s_instance = nullptr;
157 }
158
159 MOCK_METHOD2(construct, void(librados::IoCtx &io_ctx,
160 const std::string &image_id));
161 MOCK_METHOD0(send, void());
162 };
163
164 CloseImageRequest<librbd::MockTestImageCtx>*
165 CloseImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
166 OpenImageRequest<librbd::MockTestImageCtx>*
167 OpenImageRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
168
169 } // namespace image_replayer
170 } // namespace mirror
171 } // namespace rbd
172
173 // template definitions
174 #include "tools/rbd_mirror/image_replayer/CreateImageRequest.cc"
175 template class rbd::mirror::image_replayer::CreateImageRequest<librbd::MockTestImageCtx>;
176
177 namespace rbd {
178 namespace mirror {
179 namespace image_replayer {
180
181 using ::testing::_;
182 using ::testing::DoAll;
183 using ::testing::InSequence;
184 using ::testing::Invoke;
185 using ::testing::Return;
186 using ::testing::StrEq;
187 using ::testing::WithArg;
188
189 MATCHER_P(IsSameIoCtx, io_ctx, "") {
190 return &get_mock_io_ctx(arg) == &get_mock_io_ctx(*io_ctx);
191 }
192
193 class TestMockImageReplayerCreateImageRequest : public TestMockFixture {
194 public:
195 typedef librbd::image::CreateRequest<librbd::MockTestImageCtx> MockCreateRequest;
196 typedef librbd::image::CloneRequest<librbd::MockTestImageCtx> MockCloneRequest;
197 typedef CreateImageRequest<librbd::MockTestImageCtx> MockCreateImageRequest;
198 typedef OpenImageRequest<librbd::MockTestImageCtx> MockOpenImageRequest;
199 typedef CloseImageRequest<librbd::MockTestImageCtx> MockCloseImageRequest;
200
201 void SetUp() override {
202 TestMockFixture::SetUp();
203
204 librbd::RBD rbd;
205 ASSERT_EQ(0, create_image(rbd, m_remote_io_ctx, m_image_name, m_image_size));
206 ASSERT_EQ(0, open_image(m_remote_io_ctx, m_image_name, &m_remote_image_ctx));
207 }
208
209 int clone_image(librbd::ImageCtx *parent_image_ctx,
210 const std::string &snap_name, const std::string &clone_name) {
211 {
212 librbd::ImageCtx *ictx = new librbd::ImageCtx(parent_image_ctx->name,
213 "", "", m_remote_io_ctx,
214 false);
215 ictx->state->open(false);
216 EXPECT_EQ(0, ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
217 snap_name.c_str()));
218 EXPECT_EQ(0, ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
219 snap_name.c_str()));
220 ictx->state->close();
221 }
222
223 EXPECT_EQ(0, parent_image_ctx->state->refresh());
224
225 int order = 0;
226 return librbd::clone(m_remote_io_ctx, parent_image_ctx->name.c_str(),
227 snap_name.c_str(), m_remote_io_ctx,
228 clone_name.c_str(), parent_image_ctx->features,
229 &order, 0, 0);
230 }
231
232 void expect_create_image(MockCreateRequest &mock_create_request,
233 librados::IoCtx &ioctx, int r) {
234 EXPECT_CALL(mock_create_request, construct(IsSameIoCtx(&ioctx)));
235 EXPECT_CALL(mock_create_request, send())
236 .WillOnce(Invoke([this, &mock_create_request, r]() {
237 m_threads->work_queue->queue(mock_create_request.on_finish, r);
238 }));
239 }
240
241 void expect_ioctx_create(librados::IoCtx &io_ctx) {
242 EXPECT_CALL(*get_mock_io_ctx(io_ctx).get_mock_rados_client(), create_ioctx(_, _))
243 .WillOnce(Return(&get_mock_io_ctx(io_ctx)));
244 }
245
246 void expect_get_parent_global_image_id(librados::IoCtx &io_ctx,
247 const std::string &global_id, int r) {
248 cls::rbd::MirrorImage mirror_image;
249 mirror_image.global_image_id = global_id;
250
251 bufferlist bl;
252 ::encode(mirror_image, bl);
253
254 EXPECT_CALL(get_mock_io_ctx(io_ctx),
255 exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_get"), _, _, _))
256 .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) {
257 *out_bl = bl;
258 })),
259 Return(r)));
260 }
261
262 void expect_mirror_image_get_image_id(librados::IoCtx &io_ctx,
263 const std::string &image_id, int r) {
264 bufferlist bl;
265 ::encode(image_id, bl);
266
267 EXPECT_CALL(get_mock_io_ctx(io_ctx),
268 exec(RBD_MIRRORING, _, StrEq("rbd"), StrEq("mirror_image_get_image_id"), _, _, _))
269 .WillOnce(DoAll(WithArg<5>(Invoke([bl](bufferlist *out_bl) {
270 *out_bl = bl;
271 })),
272 Return(r)));
273 }
274
275 void expect_open_image(MockOpenImageRequest &mock_open_image_request,
276 librados::IoCtx &io_ctx, const std::string &image_id,
277 librbd::MockTestImageCtx &mock_image_ctx, int r) {
278 EXPECT_CALL(mock_open_image_request, construct(IsSameIoCtx(&io_ctx), image_id));
279 EXPECT_CALL(mock_open_image_request, send())
280 .WillOnce(Invoke([this, &mock_open_image_request, &mock_image_ctx, r]() {
281 *mock_open_image_request.image_ctx = &mock_image_ctx;
282 m_threads->work_queue->queue(mock_open_image_request.on_finish, r);
283 }));
284 }
285
286 void expect_snap_set(librbd::MockTestImageCtx &mock_image_ctx,
287 const std::string &snap_name, int r) {
288 EXPECT_CALL(*mock_image_ctx.state, snap_set(_, StrEq(snap_name), _))
289 .WillOnce(WithArg<2>(Invoke([this, r](Context *on_finish) {
290 m_threads->work_queue->queue(on_finish, r);
291 })));
292 }
293
294 void expect_clone_image(MockCloneRequest &mock_clone_request,
295 librbd::MockTestImageCtx &mock_parent_imctx,
296 int r) {
297 EXPECT_CALL(mock_clone_request, construct(&mock_parent_imctx));
298 EXPECT_CALL(mock_clone_request, send())
299 .WillOnce(Invoke([this, &mock_clone_request, r]() {
300 m_threads->work_queue->queue(mock_clone_request.on_finish, r);
301 }));
302 }
303
304 void expect_close_image(MockCloseImageRequest &mock_close_image_request,
305 librbd::MockTestImageCtx &mock_image_ctx, int r) {
306 EXPECT_CALL(mock_close_image_request, construct(&mock_image_ctx));
307 EXPECT_CALL(mock_close_image_request, send())
308 .WillOnce(Invoke([this, &mock_close_image_request, r]() {
309 m_threads->work_queue->queue(mock_close_image_request.on_finish, r);
310 }));
311 }
312
313 MockCreateImageRequest *create_request(const std::string &global_image_id,
314 const std::string &remote_mirror_uuid,
315 const std::string &local_image_name,
316 librbd::MockTestImageCtx &mock_remote_image_ctx,
317 std::string *local_image_id,
318 Context *on_finish) {
319 return new MockCreateImageRequest(m_local_io_ctx, m_threads->work_queue,
320 global_image_id, remote_mirror_uuid,
321 local_image_name, &mock_remote_image_ctx,
322 local_image_id, on_finish);
323 }
324
325 librbd::ImageCtx *m_remote_image_ctx;
326 };
327
328 TEST_F(TestMockImageReplayerCreateImageRequest, Create) {
329 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
330 MockCreateRequest mock_create_request;
331
332 InSequence seq;
333 expect_create_image(mock_create_request, m_local_io_ctx, 0);
334
335 C_SaferCond ctx;
336 std::string local_image_id;
337 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
338 "image name",
339 mock_remote_image_ctx,
340 &local_image_id, &ctx);
341 request->send();
342 ASSERT_EQ(0, ctx.wait());
343 ASSERT_FALSE(local_image_id.empty());
344 }
345
346 TEST_F(TestMockImageReplayerCreateImageRequest, CreateError) {
347 librbd::MockTestImageCtx mock_remote_image_ctx(*m_remote_image_ctx);
348 MockCreateRequest mock_create_request;
349
350 InSequence seq;
351 expect_create_image(mock_create_request, m_local_io_ctx, -EINVAL);
352
353 C_SaferCond ctx;
354 std::string local_image_id;
355 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
356 "image name",
357 mock_remote_image_ctx,
358 &local_image_id, &ctx);
359 request->send();
360 ASSERT_EQ(-EINVAL, ctx.wait());
361 }
362
363 TEST_F(TestMockImageReplayerCreateImageRequest, Clone) {
364 librbd::RBD rbd;
365 librbd::ImageCtx *local_image_ctx;
366 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
367 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
368
369 std::string clone_image_name = get_temp_image_name();
370 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
371
372 librbd::ImageCtx *remote_clone_image_ctx;
373 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
374 &remote_clone_image_ctx));
375
376 librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
377 librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
378 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
379 MockCloneRequest mock_clone_request;
380 MockOpenImageRequest mock_open_image_request;
381 MockCloseImageRequest mock_close_image_request;
382
383 InSequence seq;
384 expect_ioctx_create(m_remote_io_ctx);
385 expect_ioctx_create(m_local_io_ctx);
386 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
387 expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
388
389 expect_open_image(mock_open_image_request, m_remote_io_ctx,
390 m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
391 expect_open_image(mock_open_image_request, m_local_io_ctx,
392 "local parent id", mock_local_parent_image_ctx, 0);
393 expect_snap_set(mock_local_parent_image_ctx, "snap", 0);
394 expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0);
395 expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0);
396 expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
397
398 C_SaferCond ctx;
399 std::string local_image_id;
400 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
401 "image name",
402 mock_remote_clone_image_ctx,
403 &local_image_id, &ctx);
404 request->send();
405 ASSERT_EQ(0, ctx.wait());
406 ASSERT_FALSE(local_image_id.empty());
407 }
408
409 TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetGlobalImageIdError) {
410 std::string clone_image_name = get_temp_image_name();
411 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
412
413 librbd::ImageCtx *remote_clone_image_ctx;
414 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
415 &remote_clone_image_ctx));
416
417 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
418 MockCloneRequest mock_clone_request;
419
420 InSequence seq;
421 expect_ioctx_create(m_remote_io_ctx);
422 expect_ioctx_create(m_local_io_ctx);
423 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", -ENOENT);
424
425 C_SaferCond ctx;
426 std::string local_image_id;
427 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
428 "image name",
429 mock_remote_clone_image_ctx,
430 &local_image_id, &ctx);
431 request->send();
432 ASSERT_EQ(-ENOENT, ctx.wait());
433 }
434
435 TEST_F(TestMockImageReplayerCreateImageRequest, CloneGetLocalParentImageIdError) {
436 std::string clone_image_name = get_temp_image_name();
437 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
438
439 librbd::ImageCtx *remote_clone_image_ctx;
440 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
441 &remote_clone_image_ctx));
442
443 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
444 MockCloneRequest mock_clone_request;
445
446 InSequence seq;
447 expect_ioctx_create(m_remote_io_ctx);
448 expect_ioctx_create(m_local_io_ctx);
449 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
450 expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", -ENOENT);
451
452 C_SaferCond ctx;
453 std::string local_image_id;
454 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
455 "image name",
456 mock_remote_clone_image_ctx,
457 &local_image_id, &ctx);
458 request->send();
459 ASSERT_EQ(-ENOENT, ctx.wait());
460 }
461
462 TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenRemoteParentError) {
463 std::string clone_image_name = get_temp_image_name();
464 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
465
466 librbd::ImageCtx *remote_clone_image_ctx;
467 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
468 &remote_clone_image_ctx));
469
470 librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
471 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
472 MockCloneRequest mock_clone_request;
473 MockOpenImageRequest mock_open_image_request;
474
475 InSequence seq;
476 expect_ioctx_create(m_remote_io_ctx);
477 expect_ioctx_create(m_local_io_ctx);
478 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
479 expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
480
481 expect_open_image(mock_open_image_request, m_remote_io_ctx,
482 m_remote_image_ctx->id, mock_remote_parent_image_ctx, -ENOENT);
483
484 C_SaferCond ctx;
485 std::string local_image_id;
486 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
487 "image name",
488 mock_remote_clone_image_ctx,
489 &local_image_id, &ctx);
490 request->send();
491 ASSERT_EQ(-ENOENT, ctx.wait());
492 }
493
494 TEST_F(TestMockImageReplayerCreateImageRequest, CloneOpenLocalParentError) {
495 librbd::RBD rbd;
496 librbd::ImageCtx *local_image_ctx;
497 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
498 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
499
500 std::string clone_image_name = get_temp_image_name();
501 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
502
503 librbd::ImageCtx *remote_clone_image_ctx;
504 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
505 &remote_clone_image_ctx));
506
507 librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
508 librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
509 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
510 MockCloneRequest mock_clone_request;
511 MockOpenImageRequest mock_open_image_request;
512 MockCloseImageRequest mock_close_image_request;
513
514 InSequence seq;
515 expect_ioctx_create(m_remote_io_ctx);
516 expect_ioctx_create(m_local_io_ctx);
517 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
518 expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
519
520 expect_open_image(mock_open_image_request, m_remote_io_ctx,
521 m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
522 expect_open_image(mock_open_image_request, m_local_io_ctx,
523 "local parent id", mock_local_parent_image_ctx, -ENOENT);
524 expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
525
526 C_SaferCond ctx;
527 std::string local_image_id;
528 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
529 "image name",
530 mock_remote_clone_image_ctx,
531 &local_image_id, &ctx);
532 request->send();
533 ASSERT_EQ(-ENOENT, ctx.wait());
534 }
535
536 TEST_F(TestMockImageReplayerCreateImageRequest, CloneSnapSetError) {
537 librbd::RBD rbd;
538 librbd::ImageCtx *local_image_ctx;
539 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
540 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
541
542 std::string clone_image_name = get_temp_image_name();
543 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
544
545 librbd::ImageCtx *remote_clone_image_ctx;
546 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
547 &remote_clone_image_ctx));
548
549 librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
550 librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
551 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
552 MockCloneRequest mock_clone_request;
553 MockOpenImageRequest mock_open_image_request;
554 MockCloseImageRequest mock_close_image_request;
555
556 InSequence seq;
557 expect_ioctx_create(m_remote_io_ctx);
558 expect_ioctx_create(m_local_io_ctx);
559 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
560 expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
561
562 expect_open_image(mock_open_image_request, m_remote_io_ctx,
563 m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
564 expect_open_image(mock_open_image_request, m_local_io_ctx,
565 "local parent id", mock_local_parent_image_ctx, 0);
566 expect_snap_set(mock_local_parent_image_ctx, "snap", -ENOENT);
567 expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0);
568 expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
569
570 C_SaferCond ctx;
571 std::string local_image_id;
572 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
573 "image name",
574 mock_remote_clone_image_ctx,
575 &local_image_id, &ctx);
576 request->send();
577 ASSERT_EQ(-ENOENT, ctx.wait());
578 }
579
580 TEST_F(TestMockImageReplayerCreateImageRequest, CloneError) {
581 librbd::RBD rbd;
582 librbd::ImageCtx *local_image_ctx;
583 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
584 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
585
586 std::string clone_image_name = get_temp_image_name();
587 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
588
589 librbd::ImageCtx *remote_clone_image_ctx;
590 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
591 &remote_clone_image_ctx));
592
593 librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
594 librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
595 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
596 MockCloneRequest mock_clone_request;
597 MockOpenImageRequest mock_open_image_request;
598 MockCloseImageRequest mock_close_image_request;
599
600 InSequence seq;
601 expect_ioctx_create(m_remote_io_ctx);
602 expect_ioctx_create(m_local_io_ctx);
603 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
604 expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
605
606 expect_open_image(mock_open_image_request, m_remote_io_ctx,
607 m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
608 expect_open_image(mock_open_image_request, m_local_io_ctx,
609 "local parent id", mock_local_parent_image_ctx, 0);
610 expect_snap_set(mock_local_parent_image_ctx, "snap", 0);
611 expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, -EINVAL);
612 expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0);
613 expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
614
615 C_SaferCond ctx;
616 std::string local_image_id;
617 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
618 "image name",
619 mock_remote_clone_image_ctx,
620 &local_image_id, &ctx);
621 request->send();
622 ASSERT_EQ(-EINVAL, ctx.wait());
623 }
624
625 TEST_F(TestMockImageReplayerCreateImageRequest, CloneLocalParentCloseError) {
626 librbd::RBD rbd;
627 librbd::ImageCtx *local_image_ctx;
628 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
629 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
630
631 std::string clone_image_name = get_temp_image_name();
632 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
633
634 librbd::ImageCtx *remote_clone_image_ctx;
635 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
636 &remote_clone_image_ctx));
637
638 librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
639 librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
640 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
641 MockCloneRequest mock_clone_request;
642 MockOpenImageRequest mock_open_image_request;
643 MockCloseImageRequest mock_close_image_request;
644
645 InSequence seq;
646 expect_ioctx_create(m_remote_io_ctx);
647 expect_ioctx_create(m_local_io_ctx);
648 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
649 expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
650
651 expect_open_image(mock_open_image_request, m_remote_io_ctx,
652 m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
653 expect_open_image(mock_open_image_request, m_local_io_ctx,
654 "local parent id", mock_local_parent_image_ctx, 0);
655 expect_snap_set(mock_local_parent_image_ctx, "snap", 0);
656 expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0);
657 expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, -EINVAL);
658 expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, 0);
659
660 C_SaferCond ctx;
661 std::string local_image_id;
662 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
663 "image name",
664 mock_remote_clone_image_ctx,
665 &local_image_id, &ctx);
666 request->send();
667 ASSERT_EQ(0, ctx.wait());
668 ASSERT_FALSE(local_image_id.empty());
669 }
670
671 TEST_F(TestMockImageReplayerCreateImageRequest, CloneRemoteParentCloseError) {
672 librbd::RBD rbd;
673 librbd::ImageCtx *local_image_ctx;
674 ASSERT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, m_image_size));
675 ASSERT_EQ(0, open_image(m_local_io_ctx, m_image_name, &local_image_ctx));
676
677 std::string clone_image_name = get_temp_image_name();
678 ASSERT_EQ(0, clone_image(m_remote_image_ctx, "snap", clone_image_name));
679
680 librbd::ImageCtx *remote_clone_image_ctx;
681 ASSERT_EQ(0, open_image(m_remote_io_ctx, clone_image_name,
682 &remote_clone_image_ctx));
683
684 librbd::MockTestImageCtx mock_remote_parent_image_ctx(*m_remote_image_ctx);
685 librbd::MockTestImageCtx mock_local_parent_image_ctx(*local_image_ctx);
686 librbd::MockTestImageCtx mock_remote_clone_image_ctx(*remote_clone_image_ctx);
687 MockCloneRequest mock_clone_request;
688 MockOpenImageRequest mock_open_image_request;
689 MockCloseImageRequest mock_close_image_request;
690
691 InSequence seq;
692 expect_ioctx_create(m_remote_io_ctx);
693 expect_ioctx_create(m_local_io_ctx);
694 expect_get_parent_global_image_id(m_remote_io_ctx, "global uuid", 0);
695 expect_mirror_image_get_image_id(m_local_io_ctx, "local parent id", 0);
696
697 expect_open_image(mock_open_image_request, m_remote_io_ctx,
698 m_remote_image_ctx->id, mock_remote_parent_image_ctx, 0);
699 expect_open_image(mock_open_image_request, m_local_io_ctx,
700 "local parent id", mock_local_parent_image_ctx, 0);
701 expect_snap_set(mock_local_parent_image_ctx, "snap", 0);
702 expect_clone_image(mock_clone_request, mock_local_parent_image_ctx, 0);
703 expect_close_image(mock_close_image_request, mock_local_parent_image_ctx, 0);
704 expect_close_image(mock_close_image_request, mock_remote_parent_image_ctx, -EINVAL);
705
706 C_SaferCond ctx;
707 std::string local_image_id;
708 MockCreateImageRequest *request = create_request("global uuid", "remote uuid",
709 "image name",
710 mock_remote_clone_image_ctx,
711 &local_image_id, &ctx);
712 request->send();
713 ASSERT_EQ(0, ctx.wait());
714 ASSERT_FALSE(local_image_id.empty());
715 }
716
717 } // namespace image_replayer
718 } // namespace mirror
719 } // namespace rbd