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