]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/rbd_mirror/test_ImageDeleter.cc
bump version to 18.2.4-pve3
[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/ServiceDaemon.h"
21 #include "tools/rbd_mirror/Threads.h"
22 #include "tools/rbd_mirror/Throttler.h"
23 #include "tools/rbd_mirror/Types.h"
24 #include "librbd/ImageCtx.h"
25 #include "librbd/ImageState.h"
26 #include "librbd/Operations.h"
27 #include "librbd/Journal.h"
28 #include "librbd/internal.h"
29 #include "librbd/Utils.h"
30 #include "librbd/api/Image.h"
31 #include "librbd/api/Mirror.h"
32 #include "librbd/journal/DisabledPolicy.h"
33 #include "test/rbd_mirror/test_fixture.h"
34
35 #include "test/librados/test.h"
36 #include "gtest/gtest.h"
37
38 #define GLOBAL_IMAGE_ID "global_image_id"
39 #define GLOBAL_CLONE_IMAGE_ID "global_image_id_clone"
40
41 #define dout_subsys ceph_subsys_rbd_mirror
42
43 using rbd::mirror::RadosRef;
44 using rbd::mirror::TestFixture;
45 using namespace librbd;
46 using cls::rbd::MirrorImageMode;
47 using cls::rbd::MirrorImageState;
48
49
50 void register_test_rbd_mirror_image_deleter() {
51 }
52
53 class TestImageDeleter : public TestFixture {
54 public:
55 const std::string m_local_mirror_uuid = "local mirror uuid";
56 const std::string m_remote_mirror_uuid = "remote mirror uuid";
57
58 void SetUp() override {
59 TestFixture::SetUp();
60
61 m_image_deletion_throttler.reset(
62 new rbd::mirror::Throttler<>(g_ceph_context,
63 "rbd_mirror_concurrent_image_deletions"));
64
65 m_service_daemon.reset(new rbd::mirror::ServiceDaemon<>(g_ceph_context,
66 _rados, m_threads));
67
68 librbd::api::Mirror<>::mode_set(m_local_io_ctx, RBD_MIRROR_MODE_IMAGE);
69
70 m_deleter = new rbd::mirror::ImageDeleter<>(
71 m_local_io_ctx, m_threads, m_image_deletion_throttler.get(),
72 m_service_daemon.get());
73
74 m_local_image_id = librbd::util::generate_image_id(m_local_io_ctx);
75 librbd::ImageOptions image_opts;
76 image_opts.set(RBD_IMAGE_OPTION_FEATURES, RBD_FEATURES_ALL);
77 EXPECT_EQ(0, librbd::create(m_local_io_ctx, m_image_name, m_local_image_id,
78 1 << 20, image_opts, GLOBAL_IMAGE_ID,
79 m_remote_mirror_uuid, true));
80
81 cls::rbd::MirrorImage mirror_image(
82 MirrorImageMode::MIRROR_IMAGE_MODE_JOURNAL, GLOBAL_IMAGE_ID,
83 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
84 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, m_local_image_id,
85 mirror_image));
86 }
87
88 void TearDown() override {
89 remove_image();
90
91 C_SaferCond ctx;
92 m_deleter->shut_down(&ctx);
93 ctx.wait();
94
95 delete m_deleter;
96 m_service_daemon.reset();
97
98 TestFixture::TearDown();
99 }
100
101 void init_image_deleter() {
102 C_SaferCond ctx;
103 m_deleter->init(&ctx);
104 ASSERT_EQ(0, ctx.wait());
105 }
106
107 void remove_image() {
108 cls::rbd::MirrorImage mirror_image;
109 int r = cls_client::mirror_image_get(&m_local_io_ctx, m_local_image_id,
110 &mirror_image);
111 EXPECT_EQ(1, r == 0 || r == -ENOENT);
112 if (r != -ENOENT) {
113 mirror_image.state = MirrorImageState::MIRROR_IMAGE_STATE_ENABLED;
114 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx,
115 m_local_image_id,
116 mirror_image));
117 }
118 promote_image();
119
120 NoOpProgressContext ctx;
121 r = librbd::api::Image<>::remove(m_local_io_ctx, m_image_name, ctx);
122 EXPECT_EQ(1, r == 0 || r == -ENOENT);
123 }
124
125 void promote_image(ImageCtx *ictx=nullptr) {
126 bool close = false;
127 int r = 0;
128 if (!ictx) {
129 ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
130 false);
131 r = ictx->state->open(0);
132 close = (r == 0);
133 }
134
135 EXPECT_EQ(1, r == 0 || r == -ENOENT);
136
137 if (r == 0) {
138 int r2 = librbd::api::Mirror<>::image_promote(ictx, true);
139 EXPECT_EQ(1, r2 == 0 || r2 == -EINVAL);
140 }
141
142 if (close) {
143 EXPECT_EQ(0, ictx->state->close());
144 }
145 }
146
147 void demote_image(ImageCtx *ictx=nullptr) {
148 bool close = false;
149 if (!ictx) {
150 ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
151 false);
152 EXPECT_EQ(0, ictx->state->open(0));
153 close = true;
154 }
155
156 EXPECT_EQ(0, librbd::api::Mirror<>::image_demote(ictx));
157
158 if (close) {
159 EXPECT_EQ(0, ictx->state->close());
160 }
161 }
162
163 void create_snapshot(std::string snap_name="snap1", bool protect=false) {
164 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
165 false);
166 EXPECT_EQ(0, ictx->state->open(0));
167 {
168 std::unique_lock image_locker{ictx->image_lock};
169 ictx->set_journal_policy(new librbd::journal::DisabledPolicy());
170 }
171
172 librbd::NoOpProgressContext prog_ctx;
173 EXPECT_EQ(0, ictx->operations->snap_create(
174 cls::rbd::UserSnapshotNamespace(), snap_name, 0, prog_ctx));
175
176 if (protect) {
177 EXPECT_EQ(0, ictx->operations->snap_protect(
178 cls::rbd::UserSnapshotNamespace(), snap_name));
179 }
180
181 EXPECT_EQ(0, ictx->state->close());
182 }
183
184 std::string create_clone() {
185 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
186 false);
187 EXPECT_EQ(0, ictx->state->open(0));
188 {
189 std::unique_lock image_locker{ictx->image_lock};
190 ictx->set_journal_policy(new librbd::journal::DisabledPolicy());
191 }
192
193 librbd::NoOpProgressContext prog_ctx;
194 EXPECT_EQ(0, ictx->operations->snap_create(
195 cls::rbd::UserSnapshotNamespace(), "snap1", 0, prog_ctx));
196 EXPECT_EQ(0, ictx->operations->snap_protect(
197 cls::rbd::UserSnapshotNamespace(), "snap1"));
198 EXPECT_EQ(0, librbd::api::Image<>::snap_set(
199 ictx, cls::rbd::UserSnapshotNamespace(), "snap1"));
200
201 std::string clone_id = librbd::util::generate_image_id(m_local_io_ctx);
202 librbd::ImageOptions clone_opts;
203 clone_opts.set(RBD_IMAGE_OPTION_FEATURES, ictx->features);
204 EXPECT_EQ(0, librbd::clone(m_local_io_ctx, m_local_image_id.c_str(),
205 nullptr, "snap1", m_local_io_ctx,
206 clone_id.c_str(), "clone1", clone_opts,
207 GLOBAL_CLONE_IMAGE_ID, m_remote_mirror_uuid));
208
209 cls::rbd::MirrorImage mirror_image(
210 MirrorImageMode::MIRROR_IMAGE_MODE_JOURNAL, GLOBAL_CLONE_IMAGE_ID,
211 MirrorImageState::MIRROR_IMAGE_STATE_ENABLED);
212 EXPECT_EQ(0, cls_client::mirror_image_set(&m_local_io_ctx, clone_id,
213 mirror_image));
214 EXPECT_EQ(0, ictx->state->close());
215 return clone_id;
216 }
217
218 void check_image_deleted() {
219 ImageCtx *ictx = new ImageCtx("", m_local_image_id, "", m_local_io_ctx,
220 false);
221 EXPECT_EQ(-ENOENT, ictx->state->open(0));
222
223 cls::rbd::MirrorImage mirror_image;
224 EXPECT_EQ(-ENOENT, cls_client::mirror_image_get(&m_local_io_ctx,
225 m_local_image_id,
226 &mirror_image));
227 }
228
229 int trash_move(const std::string& global_image_id) {
230 C_SaferCond ctx;
231 rbd::mirror::ImageDeleter<>::trash_move(m_local_io_ctx, global_image_id,
232 true, m_threads->work_queue, &ctx);
233 return ctx.wait();
234 }
235
236 librbd::RBD rbd;
237 std::string m_local_image_id;
238 std::unique_ptr<rbd::mirror::Throttler<>> m_image_deletion_throttler;
239 std::unique_ptr<rbd::mirror::ServiceDaemon<>> m_service_daemon;
240 rbd::mirror::ImageDeleter<> *m_deleter;
241 };
242
243 TEST_F(TestImageDeleter, ExistingTrashMove) {
244 ASSERT_EQ(0, trash_move(GLOBAL_IMAGE_ID));
245
246 C_SaferCond ctx;
247 m_deleter->wait_for_deletion(m_local_image_id, false, &ctx);
248 init_image_deleter();
249
250 ASSERT_EQ(0, ctx.wait());
251 }
252
253 TEST_F(TestImageDeleter, LiveTrashMove) {
254 init_image_deleter();
255
256 C_SaferCond ctx;
257 m_deleter->wait_for_deletion(m_local_image_id, false, &ctx);
258
259 ASSERT_EQ(0, trash_move(GLOBAL_IMAGE_ID));
260 ASSERT_EQ(0, ctx.wait());
261 }
262
263 TEST_F(TestImageDeleter, Delete_Image_With_Snapshots) {
264 init_image_deleter();
265 create_snapshot("snap1");
266 create_snapshot("snap2");
267
268 C_SaferCond ctx;
269 m_deleter->wait_for_deletion(m_local_image_id, false, &ctx);
270 ASSERT_EQ(0, trash_move(GLOBAL_IMAGE_ID));
271 EXPECT_EQ(0, ctx.wait());
272
273 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
274 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
275 }
276
277 TEST_F(TestImageDeleter, Delete_Image_With_ProtectedSnapshots) {
278 init_image_deleter();
279 create_snapshot("snap1", true);
280 create_snapshot("snap2", true);
281
282 C_SaferCond ctx;
283 m_deleter->wait_for_deletion(m_local_image_id, false, &ctx);
284 ASSERT_EQ(0, trash_move(GLOBAL_IMAGE_ID));
285 EXPECT_EQ(0, ctx.wait());
286
287 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
288 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
289 }
290
291 TEST_F(TestImageDeleter, Delete_Image_With_Clone) {
292 init_image_deleter();
293 std::string clone_id = create_clone();
294
295 C_SaferCond ctx1;
296 m_deleter->set_busy_timer_interval(0.1);
297 m_deleter->wait_for_deletion(m_local_image_id, false, &ctx1);
298 ASSERT_EQ(0, trash_move(GLOBAL_IMAGE_ID));
299 EXPECT_EQ(-EBUSY, ctx1.wait());
300
301 C_SaferCond ctx2;
302 m_deleter->wait_for_deletion(clone_id, false, &ctx2);
303 ASSERT_EQ(0, trash_move(GLOBAL_CLONE_IMAGE_ID));
304 EXPECT_EQ(0, ctx2.wait());
305
306 C_SaferCond ctx3;
307 m_deleter->wait_for_deletion(m_local_image_id, true, &ctx3);
308 EXPECT_EQ(0, ctx3.wait());
309
310 ASSERT_EQ(0u, m_deleter->get_delete_queue_items().size());
311 ASSERT_EQ(0u, m_deleter->get_failed_queue_items().size());
312 }
313