]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/test_ImageDeleter.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / rbd_mirror / test_ImageDeleter.cc
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"
20 #include "tools/rbd_mirror/ImageReplayer.h"
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"
29 #include "test/rbd_mirror/test_fixture.h"
30
31 #include "test/librados/test.h"
32 #include "gtest/gtest.h"
33
34 #define GLOBAL_IMAGE_ID "global_image_id"
35 #define GLOBAL_CLONE_IMAGE_ID "global_image_id_clone"
36
37 #define dout_subsys ceph_subsys_rbd_mirror
38
39 using rbd::mirror::RadosRef;
40 using rbd::mirror::TestFixture;
41 using namespace librbd;
42 using cls::rbd::MirrorImageState;
43
44
45 void register_test_rbd_mirror_image_deleter() {
46 }
47
48 class TestImageDeleter : public TestFixture {
49 public:
50
51 static int64_t m_local_pool_id;
52
53 const std::string m_local_mirror_uuid = "local mirror uuid";
54 const std::string m_remote_mirror_uuid = "remote mirror uuid";
55
56 static void SetUpTestCase() {
57 TestFixture::SetUpTestCase();
58
59 m_local_pool_id = _rados->pool_lookup(_local_pool_name.c_str());
60 }
61
62 void SetUp() override {
63 TestFixture::SetUp();
64
65 librbd::api::Mirror<>::mode_set(m_local_io_ctx, RBD_MIRROR_MODE_IMAGE);
66
67 m_deleter = new rbd::mirror::ImageDeleter(m_threads->work_queue,
68 m_threads->timer,
69 &m_threads->timer_lock);
70
71 EXPECT_EQ(0, create_image(rbd, m_local_io_ctx, m_image_name, 1 << 20));
72 ImageCtx *ictx = new ImageCtx(m_image_name, "", "", m_local_io_ctx,
73 false);
74 EXPECT_EQ(0, ictx->state->open(false));
75 m_local_image_id = ictx->id;
76
77 cls::rbd::MirrorImage mirror_image(GLOBAL_IMAGE_ID,
78 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
79 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, ictx->id,
80 mirror_image));
81
82 demote_image(ictx);
83 EXPECT_EQ(0, ictx->state->close());
84 }
85
86 void TearDown() override {
87 remove_image();
88 TestFixture::TearDown();
89 delete m_deleter;
90 }
91
92 void remove_image(bool force=false) {
93 if (!force) {
94 cls::rbd::MirrorImage mirror_image;
95 int r = cls_client::mirror_image_get(&m_local_io_ctx, m_local_image_id,
96 &mirror_image);
97 EXPECT_EQ(1, r == 0 || r == -ENOENT);
98 if (r != -ENOENT) {
99 mirror_image.state = MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
100 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx,
101 m_local_image_id,
102 mirror_image));
103 }
104 promote_image();
105 }
106 NoOpProgressContext ctx;
107 int r = remove(m_local_io_ctx, m_image_name, "", ctx, force);
108 EXPECT_EQ(1, r == 0 || r == -ENOENT);
109 }
110
111 void promote_image(ImageCtx *ictx=nullptr) {
112 bool close = false;
113 int r = 0;
114 if (!ictx) {
115 ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
116 false);
117 r = ictx->state->open(false);
118 close = (r == 0);
119 }
120
121 EXPECT_EQ(1, r == 0 || r == -ENOENT);
122
123 if (r == 0) {
124 int r2 = librbd::api::Mirror<>::image_promote(ictx, true);
125 EXPECT_EQ(1, r2 == 0 || r2 == -EINVAL);
126 }
127
128 if (close) {
129 EXPECT_EQ(0, ictx->state->close());
130 }
131 }
132
133 void demote_image(ImageCtx *ictx=nullptr) {
134 bool close = false;
135 if (!ictx) {
136 ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
137 false);
138 EXPECT_EQ(0, ictx->state->open(false));
139 close = true;
140 }
141
142 EXPECT_EQ(0, librbd::api::Mirror<>::image_demote(ictx));
143
144 if (close) {
145 EXPECT_EQ(0, ictx->state->close());
146 }
147 }
148
149 void create_snapshot(std::string snap_name="snap1", bool protect=false) {
150 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
151 false);
152 EXPECT_EQ(0, ictx->state->open(false));
153 promote_image(ictx);
154
155 EXPECT_EQ(0, ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
156 snap_name.c_str()));
157
158 if (protect) {
159 EXPECT_EQ(0, ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
160 snap_name.c_str()));
161 }
162
163 demote_image(ictx);
164 EXPECT_EQ(0, ictx->state->close());
165 }
166
167 std::string create_clone() {
168 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
169 false);
170 EXPECT_EQ(0, ictx->state->open(false));
171 promote_image(ictx);
172
173 EXPECT_EQ(0, ictx->operations->snap_create(cls::rbd::UserSnapshotNamespace(),
174 "snap1"));
175 EXPECT_EQ(0, ictx->operations->snap_protect(cls::rbd::UserSnapshotNamespace(),
176 "snap1"));
177 int order = 20;
178 EXPECT_EQ(0, librbd::clone(m_local_io_ctx, ictx->name.c_str(), "snap1",
179 m_local_io_ctx, "clone1", ictx->features,
180 &order, 0, 0));
181 std::string clone_id;
182 ImageCtx *ictx_clone = new ImageCtx("clone1", "", "", m_local_io_ctx,
183 false);
184 EXPECT_EQ(0, ictx_clone->state->open(false));
185 clone_id = ictx_clone->id;
186 cls::rbd::MirrorImage mirror_image(GLOBAL_CLONE_IMAGE_ID,
187 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
188 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, clone_id,
189 mirror_image));
190 demote_image(ictx_clone);
191 EXPECT_EQ(0, ictx_clone->state->close());
192
193 demote_image(ictx);
194 EXPECT_EQ(0, ictx->state->close());
195
196 return clone_id;
197 }
198
199 void check_image_deleted() {
200 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
201 false);
202 EXPECT_EQ(-ENOENT, ictx->state->open(false));
203
204 cls::rbd::MirrorImage mirror_image;
205 EXPECT_EQ(-ENOENT, cls_client::mirror_image_get(&m_local_io_ctx,
206 m_local_image_id,
207 &mirror_image));
208 }
209
210
211 librbd::RBD rbd;
212 std::string m_local_image_id;
213 rbd::mirror::ImageDeleter *m_deleter;
214 };
215
216 int64_t TestImageDeleter::m_local_pool_id;
217
218
219 TEST_F(TestImageDeleter, Delete_NonPrimary_Image) {
220 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
221
222 C_SaferCond ctx;
223 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
224 &ctx);
225 EXPECT_EQ(0, ctx.wait());
226
227 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
228 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
229
230 check_image_deleted();
231 }
232
233 TEST_F(TestImageDeleter, Fail_Delete_Primary_Image) {
234 promote_image();
235
236 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
237
238 C_SaferCond ctx;
239 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
240 &ctx);
241 EXPECT_EQ(-rbd::mirror::ImageDeleter::EISPRM, ctx.wait());
242
243 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
244 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
245 }
246
247 TEST_F(TestImageDeleter, Delete_Image_With_Child) {
248 create_snapshot();
249
250 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
251
252 C_SaferCond ctx;
253 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
254 &ctx);
255 EXPECT_EQ(0, ctx.wait());
256
257 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
258 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
259 }
260
261 TEST_F(TestImageDeleter, Delete_Image_With_Children) {
262 create_snapshot("snap1");
263 create_snapshot("snap2");
264
265 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
266
267 C_SaferCond ctx;
268 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
269 &ctx);
270 EXPECT_EQ(0, ctx.wait());
271
272 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
273 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
274 }
275
276 TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChild) {
277 create_snapshot("snap1", true);
278
279 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
280
281 C_SaferCond ctx;
282 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
283 &ctx);
284 EXPECT_EQ(0, ctx.wait());
285
286 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
287 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
288 }
289
290 TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChildren) {
291 create_snapshot("snap1", true);
292 create_snapshot("snap2", true);
293
294 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
295
296 C_SaferCond ctx;
297 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
298 &ctx);
299 EXPECT_EQ(0, ctx.wait());
300
301 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
302 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
303 }
304
305 TEST_F(TestImageDeleter, Delete_Image_With_Clone) {
306 std::string clone_id = create_clone();
307
308 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
309
310 C_SaferCond ctx;
311 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
312 &ctx);
313 EXPECT_EQ(-EBUSY, ctx.wait());
314
315 ASSERT_EQ(1u, m_deleter->get_delete_queue_items().size());
316 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
317
318 m_deleter->schedule_image_delete(_rados, m_local_pool_id,
319 GLOBAL_CLONE_IMAGE_ID);
320
321 C_SaferCond ctx2;
322 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_CLONE_IMAGE_ID,
323 &ctx2);
324 EXPECT_EQ(0, ctx2.wait());
325
326 C_SaferCond ctx3;
327 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
328 &ctx3);
329 EXPECT_EQ(0, ctx3.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
335 TEST_F(TestImageDeleter, Delete_NonExistent_Image) {
336 remove_image();
337
338 cls::rbd::MirrorImage mirror_image(GLOBAL_IMAGE_ID,
339 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
340 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
341 mirror_image));
342
343 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
344
345 C_SaferCond ctx;
346 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
347 &ctx);
348 EXPECT_EQ(0, ctx.wait());
349
350 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
351 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
352
353 check_image_deleted();
354 }
355
356 TEST_F(TestImageDeleter, Delete_NonExistent_Image_With_MirroringState) {
357 remove_image(true);
358
359 cls::rbd::MirrorImage mirror_image(GLOBAL_IMAGE_ID,
360 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
361 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
362 mirror_image));
363 mirror_image.state = MirrorImageState::MIRROR_IMAGE_STATE_DISABLING;
364 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
365 mirror_image));
366
367 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
368
369 C_SaferCond ctx;
370 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
371 &ctx);
372 EXPECT_EQ(0, ctx.wait());
373
374 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
375 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
376
377 check_image_deleted();
378 }
379
380 TEST_F(TestImageDeleter, Delete_NonExistent_Image_Without_MirroringState) {
381 remove_image();
382
383 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
384
385 C_SaferCond ctx;
386 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
387 &ctx);
388 EXPECT_EQ(-ENOENT, ctx.wait());
389
390 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
391 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
392
393 check_image_deleted();
394 }
395
396 TEST_F(TestImageDeleter, Fail_Delete_NonPrimary_Image) {
397 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
398 false);
399 EXPECT_EQ(0, ictx->state->open(false));
400
401 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
402
403 C_SaferCond ctx;
404 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
405 &ctx);
406 EXPECT_EQ(-EBUSY, ctx.wait());
407
408 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
409 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
410
411 EXPECT_EQ(0, ictx->state->close());
412 }
413
414 TEST_F(TestImageDeleter, Retry_Failed_Deletes) {
415 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
416 false);
417 EXPECT_EQ(0, ictx->state->open(false));
418
419 m_deleter->set_failed_timer_interval(2);
420
421 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
422
423 C_SaferCond ctx;
424 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
425 &ctx);
426 EXPECT_EQ(-EBUSY, ctx.wait());
427
428 EXPECT_EQ(0, ictx->state->close());
429
430 C_SaferCond ctx2;
431 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
432 &ctx2);
433 EXPECT_EQ(0, ctx2.wait());
434
435 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
436 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
437
438 check_image_deleted();
439 }
440
441 TEST_F(TestImageDeleter, Delete_Is_Idempotent) {
442 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
443 false);
444 EXPECT_EQ(0, ictx->state->open(false));
445
446 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
447
448 C_SaferCond ctx;
449 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
450 &ctx);
451 EXPECT_EQ(-EBUSY, ctx.wait());
452
453 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
454 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
455
456 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID);
457
458 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
459 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
460
461 EXPECT_EQ(0, ictx->state->close());
462 }
463
464