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