1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 SUSE LINUX GmbH
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.
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/ServiceDaemon.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 "librbd/journal/DisabledPolicy.h"
30 #include "test/rbd_mirror/test_fixture.h"
32 #include "test/librados/test.h"
33 #include "gtest/gtest.h"
35 #define GLOBAL_IMAGE_ID "global_image_id"
36 #define GLOBAL_CLONE_IMAGE_ID "global_image_id_clone"
38 #define dout_subsys ceph_subsys_rbd_mirror
40 using rbd::mirror::RadosRef;
41 using rbd::mirror::TestFixture;
42 using namespace librbd;
43 using cls::rbd::MirrorImageState;
46 void register_test_rbd_mirror_image_deleter() {
49 class TestImageDeleter : public TestFixture {
52 static int64_t m_local_pool_id;
54 const std::string m_local_mirror_uuid = "local mirror uuid";
55 const std::string m_remote_mirror_uuid = "remote mirror uuid";
57 static void SetUpTestCase() {
58 TestFixture::SetUpTestCase();
60 m_local_pool_id = _rados->pool_lookup(_local_pool_name.c_str());
63 void SetUp() override {
65 m_service_daemon.reset(new rbd::mirror::ServiceDaemon<>(g_ceph_context,
68 librbd::api::Mirror<>::mode_set(m_local_io_ctx, RBD_MIRROR_MODE_IMAGE);
70 m_deleter = new rbd::mirror::ImageDeleter<>(m_threads->work_queue,
72 &m_threads->timer_lock,
73 m_service_daemon.get());
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));
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,
88 void TearDown() override {
91 m_service_daemon.reset();
93 TestFixture::TearDown();
96 void remove_image(bool force=false) {
98 cls::rbd::MirrorImage mirror_image;
99 int r = cls_client::mirror_image_get(&m_local_io_ctx, m_local_image_id,
101 EXPECT_EQ(1, r == 0 || r == -ENOENT);
103 mirror_image.state = MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
104 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx,
110 NoOpProgressContext ctx;
111 int r = remove(m_local_io_ctx, m_image_name, "", ctx, force);
112 EXPECT_EQ(1, r == 0 || r == -ENOENT);
115 void promote_image(ImageCtx *ictx=nullptr) {
119 ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
121 r = ictx->state->open(false);
125 EXPECT_EQ(1, r == 0 || r == -ENOENT);
128 int r2 = librbd::api::Mirror<>::image_promote(ictx, true);
129 EXPECT_EQ(1, r2 == 0 || r2 == -EINVAL);
133 EXPECT_EQ(0, ictx->state->close());
137 void demote_image(ImageCtx *ictx=nullptr) {
140 ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
142 EXPECT_EQ(0, ictx->state->open(false));
146 EXPECT_EQ(0, librbd::api::Mirror<>::image_demote(ictx));
149 EXPECT_EQ(0, ictx->state->close());
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,
156 EXPECT_EQ(0, ictx->state->open(false));
158 RWLock::WLocker snap_locker(ictx->snap_lock);
159 ictx->set_journal_policy(new librbd::journal::DisabledPolicy());
162 EXPECT_EQ(0, ictx->operations->snap_create(
163 cls::rbd::UserSnapshotNamespace(), snap_name.c_str()));
166 EXPECT_EQ(0, ictx->operations->snap_protect(
167 cls::rbd::UserSnapshotNamespace(), snap_name.c_str()));
170 EXPECT_EQ(0, ictx->state->close());
173 std::string create_clone() {
174 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
176 EXPECT_EQ(0, ictx->state->open(false));
178 RWLock::WLocker snap_locker(ictx->snap_lock);
179 ictx->set_journal_policy(new librbd::journal::DisabledPolicy());
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(),
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));
196 cls::rbd::MirrorImage mirror_image(
197 GLOBAL_CLONE_IMAGE_ID, MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
198 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, clone_id,
200 EXPECT_EQ(0, ictx->state->close());
204 void check_image_deleted() {
205 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
207 EXPECT_EQ(-ENOENT, ictx->state->open(false));
209 cls::rbd::MirrorImage mirror_image;
210 EXPECT_EQ(-ENOENT, cls_client::mirror_image_get(&m_local_io_ctx,
217 std::string m_local_image_id;
218 std::unique_ptr<rbd::mirror::ServiceDaemon<>> m_service_daemon;
219 rbd::mirror::ImageDeleter<> *m_deleter;
222 int64_t TestImageDeleter::m_local_pool_id;
225 TEST_F(TestImageDeleter, Delete_NonPrimary_Image) {
226 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
230 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
232 EXPECT_EQ(0, ctx.wait());
234 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
235 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
237 check_image_deleted();
240 TEST_F(TestImageDeleter, Delete_Split_Brain_Image) {
244 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
248 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
250 EXPECT_EQ(0, ctx.wait());
252 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
253 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
255 check_image_deleted();
258 TEST_F(TestImageDeleter, Fail_Delete_Primary_Image) {
261 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
265 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
267 EXPECT_EQ(-rbd::mirror::ImageDeleter<>::EISPRM, ctx.wait());
269 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
270 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
273 TEST_F(TestImageDeleter, Fail_Delete_Orphan_Image) {
277 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
281 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
283 EXPECT_EQ(-rbd::mirror::ImageDeleter<>::EISPRM, ctx.wait());
285 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
286 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
289 TEST_F(TestImageDeleter, Delete_Image_With_Child) {
292 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
296 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
298 EXPECT_EQ(0, ctx.wait());
300 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
301 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
304 TEST_F(TestImageDeleter, Delete_Image_With_Children) {
305 create_snapshot("snap1");
306 create_snapshot("snap2");
308 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
312 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
314 EXPECT_EQ(0, ctx.wait());
316 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
317 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
320 TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChild) {
321 create_snapshot("snap1", true);
323 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
327 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
329 EXPECT_EQ(0, ctx.wait());
331 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
332 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
335 TEST_F(TestImageDeleter, Delete_Image_With_ProtectedChildren) {
336 create_snapshot("snap1", true);
337 create_snapshot("snap2", true);
339 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
343 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
345 EXPECT_EQ(0, ctx.wait());
347 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
348 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
351 TEST_F(TestImageDeleter, Delete_Image_With_Clone) {
352 std::string clone_id = create_clone();
354 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
358 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
360 EXPECT_EQ(-EBUSY, ctx.wait());
362 ASSERT_EQ(1u, m_deleter->get_delete_queue_items().size());
363 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
365 m_deleter->schedule_image_delete(_rados, m_local_pool_id,
366 GLOBAL_CLONE_IMAGE_ID, false);
369 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_CLONE_IMAGE_ID,
371 EXPECT_EQ(0, ctx2.wait());
374 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
376 EXPECT_EQ(0, ctx3.wait());
378 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
379 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
382 TEST_F(TestImageDeleter, Delete_NonExistent_Image) {
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,
390 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
394 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
396 EXPECT_EQ(0, ctx.wait());
398 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
399 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
401 check_image_deleted();
404 TEST_F(TestImageDeleter, Delete_NonExistent_Image_With_MirroringState) {
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,
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,
415 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
419 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
421 EXPECT_EQ(0, ctx.wait());
423 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
424 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
426 check_image_deleted();
429 TEST_F(TestImageDeleter, Delete_NonExistent_Image_Without_MirroringState) {
432 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
436 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
438 EXPECT_EQ(-ENOENT, ctx.wait());
440 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
441 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
443 check_image_deleted();
446 TEST_F(TestImageDeleter, Fail_Delete_NonPrimary_Image) {
447 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
449 EXPECT_EQ(0, ictx->state->open(false));
451 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
455 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
457 EXPECT_EQ(-EBUSY, ctx.wait());
459 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
460 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
462 EXPECT_EQ(0, ictx->state->close());
465 TEST_F(TestImageDeleter, Retry_Failed_Deletes) {
466 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
468 EXPECT_EQ(0, ictx->state->open(false));
470 m_deleter->set_failed_timer_interval(2);
472 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
476 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
478 EXPECT_EQ(-EBUSY, ctx.wait());
480 EXPECT_EQ(0, ictx->state->close());
483 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
485 EXPECT_EQ(0, ctx2.wait());
487 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
488 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
490 check_image_deleted();
493 TEST_F(TestImageDeleter, Delete_Is_Idempotent) {
494 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
496 EXPECT_EQ(0, ictx->state->open(false));
498 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
502 m_deleter->wait_for_scheduled_deletion(m_local_pool_id, GLOBAL_IMAGE_ID,
504 EXPECT_EQ(-EBUSY, ctx.wait());
506 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
507 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
509 m_deleter->schedule_image_delete(_rados, m_local_pool_id, GLOBAL_IMAGE_ID,
512 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
513 ASSERT_EQ(1u, m_deleter->get_failed_queue_items().size());
515 EXPECT_EQ(0, ictx->state->close());