]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/rbd_mirror/test_ImageDeleter.cc
update sources to v12.1.3
[ceph.git] / ceph / src / test / rbd_mirror / test_ImageDeleter.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2016 SUSE LINUX GmbH
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14#include "include/rados/librados.hpp"
15#include "include/rbd/librbd.hpp"
16#include "include/stringify.h"
17#include "cls/rbd/cls_rbd_types.h"
18#include "cls/rbd/cls_rbd_client.h"
19#include "tools/rbd_mirror/ImageDeleter.h"
c07f9fc5 20#include "tools/rbd_mirror/ServiceDaemon.h"
7c673cae
FG
21#include "tools/rbd_mirror/Threads.h"
22#include "librbd/ImageCtx.h"
23#include "librbd/ImageState.h"
24#include "librbd/Operations.h"
25#include "librbd/Journal.h"
26#include "librbd/internal.h"
27#include "librbd/Utils.h"
28#include "librbd/api/Mirror.h"
c07f9fc5 29#include "librbd/journal/DisabledPolicy.h"
7c673cae
FG
30#include "test/rbd_mirror/test_fixture.h"
31
32#include "test/librados/test.h"
33#include "gtest/gtest.h"
34
35#define GLOBAL_IMAGE_ID "global_image_id"
36#define GLOBAL_CLONE_IMAGE_ID "global_image_id_clone"
37
38#define dout_subsys ceph_subsys_rbd_mirror
39
40using rbd::mirror::RadosRef;
41using rbd::mirror::TestFixture;
42using namespace librbd;
43using cls::rbd::MirrorImageState;
44
45
46void register_test_rbd_mirror_image_deleter() {
47}
48
49class TestImageDeleter : public TestFixture {
50public:
51
52 static int64_t m_local_pool_id;
53
54 const std::string m_local_mirror_uuid = "local mirror uuid";
55 const std::string m_remote_mirror_uuid = "remote mirror uuid";
56
57 static void SetUpTestCase() {
58 TestFixture::SetUpTestCase();
59
60 m_local_pool_id = _rados->pool_lookup(_local_pool_name.c_str());
61 }
62
63 void SetUp() override {
64 TestFixture::SetUp();
c07f9fc5
FG
65 m_service_daemon.reset(new rbd::mirror::ServiceDaemon<>(g_ceph_context,
66 _rados, m_threads));
7c673cae
FG
67
68 librbd::api::Mirror<>::mode_set(m_local_io_ctx, RBD_MIRROR_MODE_IMAGE);
69
c07f9fc5
FG
70 m_deleter = new rbd::mirror::ImageDeleter<>(m_threads->work_queue,
71 m_threads->timer,
72 &m_threads->timer_lock,
73 m_service_daemon.get());
74
75 m_local_image_id = librbd::util::generate_image_id(m_local_io_ctx);
76 librbd::ImageOptions image_opts;
77 image_opts.set(RBD_IMAGE_OPTION_FEATURES, RBD_FEATURES_ALL);
78 EXPECT_EQ(0, librbd::create(m_local_io_ctx, m_image_name, m_local_image_id,
79 1 << 20, image_opts, GLOBAL_IMAGE_ID,
80 m_remote_mirror_uuid, true));
81
82 cls::rbd::MirrorImage mirror_image(
83 GLOBAL_IMAGE_ID, MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
84 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
7c673cae 85 mirror_image));
7c673cae
FG
86 }
87
88 void TearDown() override {
89 remove_image();
7c673cae 90 delete m_deleter;
c07f9fc5
FG
91 m_service_daemon.reset();
92
93 TestFixture::TearDown();
7c673cae
FG
94 }
95
96 void remove_image(bool force=false) {
97 if (!force) {
98 cls::rbd::MirrorImage mirror_image;
99 int r = cls_client::mirror_image_get(&m_local_io_ctx, m_local_image_id,
100 &mirror_image);
101 EXPECT_EQ(1, r == 0 || r == -ENOENT);
102 if (r != -ENOENT) {
103 mirror_image.state = MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
104 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx,
105 m_local_image_id,
106 mirror_image));
107 }
108 promote_image();
109 }
110 NoOpProgressContext ctx;
111 int r = remove(m_local_io_ctx, m_image_name, "", ctx, force);
112 EXPECT_EQ(1, r == 0 || r == -ENOENT);
113 }
114
115 void promote_image(ImageCtx *ictx=nullptr) {
116 bool close = false;
117 int r = 0;
118 if (!ictx) {
119 ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
120 false);
121 r = ictx->state->open(false);
122 close = (r == 0);
123 }
124
125 EXPECT_EQ(1, r == 0 || r == -ENOENT);
126
127 if (r == 0) {
128 int r2 = librbd::api::Mirror<>::image_promote(ictx, true);
129 EXPECT_EQ(1, r2 == 0 || r2 == -EINVAL);
130 }
131
132 if (close) {
133 EXPECT_EQ(0, ictx->state->close());
134 }
135 }
136
137 void demote_image(ImageCtx *ictx=nullptr) {
138 bool close = false;
139 if (!ictx) {
140 ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
141 false);
142 EXPECT_EQ(0, ictx->state->open(false));
143 close = true;
144 }
145
146 EXPECT_EQ(0, librbd::api::Mirror<>::image_demote(ictx));
147
148 if (close) {
149 EXPECT_EQ(0, ictx->state->close());
150 }
151 }
152
153 void create_snapshot(std::string snap_name="snap1", bool protect=false) {
154 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
155 false);
156 EXPECT_EQ(0, ictx->state->open(false));
c07f9fc5
FG
157 {
158 RWLock::WLocker snap_locker(ictx->snap_lock);
159 ictx->set_journal_policy(new librbd::journal::DisabledPolicy());
160 }
7c673cae 161
c07f9fc5
FG
162 EXPECT_EQ(0, ictx->operations->snap_create(
163 cls::rbd::UserSnapshotNamespace(), snap_name.c_str()));
7c673cae
FG
164
165 if (protect) {
c07f9fc5
FG
166 EXPECT_EQ(0, ictx->operations->snap_protect(
167 cls::rbd::UserSnapshotNamespace(), snap_name.c_str()));
7c673cae
FG
168 }
169
7c673cae
FG
170 EXPECT_EQ(0, ictx->state->close());
171 }
172
173 std::string create_clone() {
174 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
175 false);
176 EXPECT_EQ(0, ictx->state->open(false));
c07f9fc5
FG
177 {
178 RWLock::WLocker snap_locker(ictx->snap_lock);
179 ictx->set_journal_policy(new librbd::journal::DisabledPolicy());
180 }
181
182 EXPECT_EQ(0, ictx->operations->snap_create(
183 cls::rbd::UserSnapshotNamespace(), "snap1"));
184 EXPECT_EQ(0, ictx->operations->snap_protect(
185 cls::rbd::UserSnapshotNamespace(), "snap1"));
186 EXPECT_EQ(0, librbd::snap_set(ictx, cls::rbd::UserSnapshotNamespace(),
187 "snap1"));
188
189 std::string clone_id = librbd::util::generate_image_id(m_local_io_ctx);
190 librbd::ImageOptions clone_opts;
191 clone_opts.set(RBD_IMAGE_OPTION_FEATURES, ictx->features);
192 EXPECT_EQ(0, librbd::clone(ictx, m_local_io_ctx, "clone1", clone_id,
193 clone_opts, GLOBAL_CLONE_IMAGE_ID,
194 m_remote_mirror_uuid));
195
196 cls::rbd::MirrorImage mirror_image(
197 GLOBAL_CLONE_IMAGE_ID, MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
7c673cae
FG
198 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, clone_id,
199 mirror_image));
7c673cae 200 EXPECT_EQ(0, ictx->state->close());
7c673cae
FG
201 return clone_id;
202 }
203
204 void check_image_deleted() {
205 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
206 false);
207 EXPECT_EQ(-ENOENT, ictx->state->open(false));
208
209 cls::rbd::MirrorImage mirror_image;
210 EXPECT_EQ(-ENOENT, cls_client::mirror_image_get(&m_local_io_ctx,
211 m_local_image_id,
212 &mirror_image));
213 }
214
215
216 librbd::RBD rbd;
217 std::string m_local_image_id;
c07f9fc5
FG
218 std::unique_ptr<rbd::mirror::ServiceDaemon<>> m_service_daemon;
219 rbd::mirror::ImageDeleter<> *m_deleter;
7c673cae
FG
220};
221
222int64_t TestImageDeleter::m_local_pool_id;
223
224
225TEST_F(TestImageDeleter, Delete_NonPrimary_Image) {
c07f9fc5
FG
226 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
227 false);
228
229 C_SaferCond ctx;
230 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
231 &ctx);
232 EXPECT_EQ(0, ctx.wait());
233
234 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
235 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
236
237 check_image_deleted();
238}
239
240TEST_F(TestImageDeleter, Delete_Split_Brain_Image) {
241 promote_image();
242 demote_image();
243
244 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
245 true);
7c673cae
FG
246
247 C_SaferCond ctx;
248 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
249 &ctx);
250 EXPECT_EQ(0, ctx.wait());
251
252 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
253 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
254
255 check_image_deleted();
256}
257
258TEST_F(TestImageDeleter, Fail_Delete_Primary_Image) {
259 promote_image();
260
c07f9fc5
FG
261 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
262 false);
263
264 C_SaferCond ctx;
265 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
266 &ctx);
267 EXPECT_EQ(-rbd::mirror::ImageDeleter<>::EISPRM, ctx.wait());
268
269 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
270 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
271}
272
273TEST_F(TestImageDeleter, Fail_Delete_Orphan_Image) {
274 promote_image();
275 demote_image();
276
277 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
278 false);
7c673cae
FG
279
280 C_SaferCond ctx;
281 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
282 &ctx);
c07f9fc5 283 EXPECT_EQ(-rbd::mirror::ImageDeleter<>::EISPRM, ctx.wait());
7c673cae
FG
284
285 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
286 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
287}
288
289TEST_F(TestImageDeleter, Delete_Image_With_Child) {
290 create_snapshot();
291
c07f9fc5
FG
292 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
293 false);
7c673cae
FG
294
295 C_SaferCond ctx;
296 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
297 &ctx);
298 EXPECT_EQ(0, ctx.wait());
299
300 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
301 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
302}
303
304TEST_F(TestImageDeleter, Delete_Image_With_Children) {
305 create_snapshot("snap1");
306 create_snapshot("snap2");
307
c07f9fc5
FG
308 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
309 false);
7c673cae
FG
310
311 C_SaferCond ctx;
312 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
313 &ctx);
314 EXPECT_EQ(0, ctx.wait());
315
316 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
317 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
318}
319
320TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChild) {
321 create_snapshot("snap1", true);
322
c07f9fc5
FG
323 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
324 false);
7c673cae
FG
325
326 C_SaferCond ctx;
327 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
328 &ctx);
329 EXPECT_EQ(0, ctx.wait());
330
331 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
332 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
333}
334
335TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChildren) {
336 create_snapshot("snap1", true);
337 create_snapshot("snap2", true);
338
c07f9fc5
FG
339 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
340 false);
7c673cae
FG
341
342 C_SaferCond ctx;
343 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
344 &ctx);
345 EXPECT_EQ(0, ctx.wait());
346
347 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
348 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
349}
350
351TEST_F(TestImageDeleter, Delete_Image_With_Clone) {
352 std::string clone_id = create_clone();
353
c07f9fc5
FG
354 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
355 false);
7c673cae
FG
356
357 C_SaferCond ctx;
358 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
359 &ctx);
360 EXPECT_EQ(-EBUSY, ctx.wait());
361
362 ASSERT_EQ(1u, m_deleter->get_delete_queue_items().size());
363 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
364
365 m_deleter->schedule_image_delete(_rados, m_local_pool_id,
c07f9fc5 366 GLOBAL_CLONE_IMAGE_ID, false);
7c673cae
FG
367
368 C_SaferCond ctx2;
369 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_CLONE_IMAGE_ID,
370 &ctx2);
371 EXPECT_EQ(0, ctx2.wait());
372
373 C_SaferCond ctx3;
374 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
375 &ctx3);
376 EXPECT_EQ(0, ctx3.wait());
377
378 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
379 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
380}
381
382TEST_F(TestImageDeleter, Delete_NonExistent_Image) {
383 remove_image();
384
385 cls::rbd::MirrorImage mirror_image(GLOBAL_IMAGE_ID,
386 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
387 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
388 mirror_image));
389
c07f9fc5
FG
390 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
391 false);
7c673cae
FG
392
393 C_SaferCond ctx;
394 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
395 &ctx);
396 EXPECT_EQ(0, ctx.wait());
397
398 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
399 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
400
401 check_image_deleted();
402}
403
404TEST_F(TestImageDeleter, Delete_NonExistent_Image_With_MirroringState) {
405 remove_image(true);
406
407 cls::rbd::MirrorImage mirror_image(GLOBAL_IMAGE_ID,
408 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
409 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
410 mirror_image));
411 mirror_image.state = MirrorImageState::MIRROR_IMAGE_STATE_DISABLING;
412 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
413 mirror_image));
414
c07f9fc5
FG
415 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
416 false);
7c673cae
FG
417
418 C_SaferCond ctx;
419 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
420 &ctx);
421 EXPECT_EQ(0, ctx.wait());
422
423 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
424 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
425
426 check_image_deleted();
427}
428
429TEST_F(TestImageDeleter, Delete_NonExistent_Image_Without_MirroringState) {
430 remove_image();
431
c07f9fc5
FG
432 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
433 false);
7c673cae
FG
434
435 C_SaferCond ctx;
436 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
437 &ctx);
438 EXPECT_EQ(-ENOENT, ctx.wait());
439
440 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
441 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
442
443 check_image_deleted();
444}
445
446TEST_F(TestImageDeleter, Fail_Delete_NonPrimary_Image) {
447 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
448 false);
449 EXPECT_EQ(0, ictx->state->open(false));
450
c07f9fc5
FG
451 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
452 false);
7c673cae
FG
453
454 C_SaferCond ctx;
455 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
456 &ctx);
457 EXPECT_EQ(-EBUSY, ctx.wait());
458
459 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
460 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
461
462 EXPECT_EQ(0, ictx->state->close());
463}
464
465TEST_F(TestImageDeleter, Retry_Failed_Deletes) {
466 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
467 false);
468 EXPECT_EQ(0, ictx->state->open(false));
469
470 m_deleter->set_failed_timer_interval(2);
471
c07f9fc5
FG
472 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
473 false);
7c673cae
FG
474
475 C_SaferCond ctx;
476 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
477 &ctx);
478 EXPECT_EQ(-EBUSY, ctx.wait());
479
480 EXPECT_EQ(0, ictx->state->close());
481
482 C_SaferCond ctx2;
483 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
484 &ctx2);
485 EXPECT_EQ(0, ctx2.wait());
486
487 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
488 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
489
490 check_image_deleted();
491}
492
493TEST_F(TestImageDeleter, Delete_Is_Idempotent) {
494 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
495 false);
496 EXPECT_EQ(0, ictx->state->open(false));
497
c07f9fc5
FG
498 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
499 false);
7c673cae
FG
500
501 C_SaferCond ctx;
502 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
503 &ctx);
504 EXPECT_EQ(-EBUSY, ctx.wait());
505
506 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
507 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
508
c07f9fc5
FG
509 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
510 false);
7c673cae
FG
511
512 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
513 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
514
515 EXPECT_EQ(0, ictx->state->close());
516}
517
518