]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/test_Groups.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / test / librbd / test_Groups.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "test/librbd/test_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "include/rbd/librbd.h"
7 #include "include/rbd/librbd.hpp"
8 #include "test/librados/test.h"
9 #include "gtest/gtest.h"
10
11 #include <boost/scope_exit.hpp>
12 #include <chrono>
13 #include <vector>
14
15 void register_test_groups() {
16 }
17
18 class TestGroup : public TestFixture {
19
20 };
21
22 TEST_F(TestGroup, group_create)
23 {
24 rados_ioctx_t ioctx;
25 rados_ioctx_create(_cluster, _pool_name.c_str(), &ioctx);
26 BOOST_SCOPE_EXIT(ioctx) {
27 rados_ioctx_destroy(ioctx);
28 } BOOST_SCOPE_EXIT_END;
29
30 librbd::RBD rbd;
31 ASSERT_EQ(0, rbd_group_create(ioctx, "mygroup"));
32
33 size_t size = 0;
34 ASSERT_EQ(-ERANGE, rbd_group_list(ioctx, NULL, &size));
35 ASSERT_EQ(strlen("mygroup") + 1, size);
36
37 char groups[80];
38 ASSERT_EQ(static_cast<int>(strlen("mygroup") + 1),
39 rbd_group_list(ioctx, groups, &size));
40 ASSERT_STREQ("mygroup", groups);
41
42 ASSERT_EQ(0, rbd_group_remove(ioctx, "mygroup"));
43
44 ASSERT_EQ(0, rbd_group_list(ioctx, groups, &size));
45 }
46
47 TEST_F(TestGroup, group_createPP)
48 {
49 librados::IoCtx ioctx;
50 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
51
52 librbd::RBD rbd;
53 ASSERT_EQ(0, rbd.group_create(ioctx, "mygroup"));
54
55 std::vector<std::string> groups;
56 ASSERT_EQ(0, rbd.group_list(ioctx, &groups));
57 ASSERT_EQ(1U, groups.size());
58 ASSERT_EQ("mygroup", groups[0]);
59
60 groups.clear();
61 ASSERT_EQ(0, rbd.group_rename(ioctx, "mygroup", "newgroup"));
62 ASSERT_EQ(0, rbd.group_list(ioctx, &groups));
63 ASSERT_EQ(1U, groups.size());
64 ASSERT_EQ("newgroup", groups[0]);
65
66 ASSERT_EQ(0, rbd.group_remove(ioctx, "newgroup"));
67
68 groups.clear();
69 ASSERT_EQ(0, rbd.group_list(ioctx, &groups));
70 ASSERT_EQ(0U, groups.size());
71 }
72
73 TEST_F(TestGroup, add_image)
74 {
75 REQUIRE_FORMAT_V2();
76
77 rados_ioctx_t ioctx;
78 rados_ioctx_create(_cluster, _pool_name.c_str(), &ioctx);
79 BOOST_SCOPE_EXIT(ioctx) {
80 rados_ioctx_destroy(ioctx);
81 } BOOST_SCOPE_EXIT_END;
82
83 const char *group_name = "mycg";
84 ASSERT_EQ(0, rbd_group_create(ioctx, group_name));
85
86 rbd_image_t image;
87 ASSERT_EQ(0, rbd_open(ioctx, m_image_name.c_str(), &image, NULL));
88 BOOST_SCOPE_EXIT(image) {
89 EXPECT_EQ(0, rbd_close(image));
90 } BOOST_SCOPE_EXIT_END;
91
92 uint64_t features;
93 ASSERT_EQ(0, rbd_get_features(image, &features));
94 ASSERT_TRUE((features & RBD_FEATURE_OPERATIONS) == 0ULL);
95
96 uint64_t op_features;
97 ASSERT_EQ(0, rbd_get_op_features(image, &op_features));
98 ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) == 0ULL);
99
100 rbd_group_info_t group_info;
101 ASSERT_EQ(0, rbd_get_group(image, &group_info, sizeof(group_info)));
102 ASSERT_EQ(0, strcmp("", group_info.name));
103 ASSERT_EQ(RBD_GROUP_INVALID_POOL, group_info.pool);
104 rbd_group_info_cleanup(&group_info, sizeof(group_info));
105
106 ASSERT_EQ(0, rbd_group_image_add(ioctx, group_name, ioctx,
107 m_image_name.c_str()));
108
109 ASSERT_EQ(-ERANGE, rbd_get_group(image, &group_info, 0));
110 ASSERT_EQ(0, rbd_get_group(image, &group_info, sizeof(group_info)));
111 ASSERT_EQ(0, strcmp(group_name, group_info.name));
112 ASSERT_EQ(rados_ioctx_get_id(ioctx), group_info.pool);
113 rbd_group_info_cleanup(&group_info, sizeof(group_info));
114
115 ASSERT_EQ(0, rbd_get_features(image, &features));
116 ASSERT_TRUE((features & RBD_FEATURE_OPERATIONS) ==
117 RBD_FEATURE_OPERATIONS);
118 ASSERT_EQ(0, rbd_get_op_features(image, &op_features));
119 ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) ==
120 RBD_OPERATION_FEATURE_GROUP);
121
122 size_t num_images = 0;
123 ASSERT_EQ(-ERANGE, rbd_group_image_list(ioctx, group_name, NULL,
124 sizeof(rbd_group_image_info_t),
125 &num_images));
126 ASSERT_EQ(1U, num_images);
127
128 rbd_group_image_info_t images[1];
129 ASSERT_EQ(1, rbd_group_image_list(ioctx, group_name, images,
130 sizeof(rbd_group_image_info_t),
131 &num_images));
132
133 ASSERT_EQ(m_image_name, images[0].name);
134 ASSERT_EQ(rados_ioctx_get_id(ioctx), images[0].pool);
135
136 ASSERT_EQ(0, rbd_group_image_list_cleanup(images,
137 sizeof(rbd_group_image_info_t),
138 num_images));
139 ASSERT_EQ(0, rbd_group_image_remove(ioctx, group_name, ioctx,
140 m_image_name.c_str()));
141
142 ASSERT_EQ(0, rbd_get_features(image, &features));
143 ASSERT_TRUE((features & RBD_FEATURE_OPERATIONS) == 0ULL);
144 ASSERT_EQ(0, rbd_get_op_features(image, &op_features));
145 ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) == 0ULL);
146
147 ASSERT_EQ(0, rbd_group_image_list(ioctx, group_name, images,
148 sizeof(rbd_group_image_info_t),
149 &num_images));
150 ASSERT_EQ(0U, num_images);
151
152 ASSERT_EQ(0, rbd_group_remove(ioctx, group_name));
153 }
154
155 TEST_F(TestGroup, add_imagePP)
156 {
157 REQUIRE_FORMAT_V2();
158
159 librados::IoCtx ioctx;
160 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
161
162 const char *group_name = "mycg";
163 librbd::RBD rbd;
164 ASSERT_EQ(0, rbd.group_create(ioctx, group_name));
165
166 librbd::Image image;
167 ASSERT_EQ(0, rbd.open(ioctx, image, m_image_name.c_str(), NULL));
168
169 uint64_t features;
170 ASSERT_EQ(0, image.features(&features));
171 ASSERT_TRUE((features & RBD_FEATURE_OPERATIONS) == 0ULL);
172
173 uint64_t op_features;
174 ASSERT_EQ(0, image.get_op_features(&op_features));
175 ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) == 0ULL);
176
177 librbd::group_info_t group_info;
178 ASSERT_EQ(0, image.get_group(&group_info, sizeof(group_info)));
179 ASSERT_EQ(std::string(""), group_info.name);
180 ASSERT_EQ(RBD_GROUP_INVALID_POOL, group_info.pool);
181
182 ASSERT_EQ(0, rbd.group_image_add(ioctx, group_name, ioctx,
183 m_image_name.c_str()));
184
185 ASSERT_EQ(-ERANGE, image.get_group(&group_info, 0));
186 ASSERT_EQ(0, image.get_group(&group_info, sizeof(group_info)));
187 ASSERT_EQ(std::string(group_name), group_info.name);
188 ASSERT_EQ(ioctx.get_id(), group_info.pool);
189
190 ASSERT_EQ(0, image.features(&features));
191 ASSERT_TRUE((features & RBD_FEATURE_OPERATIONS) ==
192 RBD_FEATURE_OPERATIONS);
193 ASSERT_EQ(0, image.get_op_features(&op_features));
194 ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) ==
195 RBD_OPERATION_FEATURE_GROUP);
196
197 std::vector<librbd::group_image_info_t> images;
198 ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, &images,
199 sizeof(librbd::group_image_info_t)));
200 ASSERT_EQ(1U, images.size());
201 ASSERT_EQ(m_image_name, images[0].name);
202 ASSERT_EQ(ioctx.get_id(), images[0].pool);
203
204 ASSERT_EQ(0, rbd.group_image_remove(ioctx, group_name, ioctx,
205 m_image_name.c_str()));
206
207 ASSERT_EQ(0, image.features(&features));
208 ASSERT_TRUE((features & RBD_FEATURE_OPERATIONS) == 0ULL);
209 ASSERT_EQ(0, image.get_op_features(&op_features));
210 ASSERT_TRUE((op_features & RBD_OPERATION_FEATURE_GROUP) == 0ULL);
211
212 images.clear();
213 ASSERT_EQ(0, rbd.group_image_list(ioctx, group_name, &images,
214 sizeof(librbd::group_image_info_t)));
215 ASSERT_EQ(0U, images.size());
216
217 ASSERT_EQ(0, rbd.group_remove(ioctx, group_name));
218 }
219
220 TEST_F(TestGroup, add_snapshot)
221 {
222 REQUIRE_FORMAT_V2();
223
224 rados_ioctx_t ioctx;
225 rados_ioctx_create(_cluster, _pool_name.c_str(), &ioctx);
226 BOOST_SCOPE_EXIT(ioctx) {
227 rados_ioctx_destroy(ioctx);
228 } BOOST_SCOPE_EXIT_END;
229
230 const char *group_name = "snap_group";
231 const char *snap_name = "snap_snapshot";
232
233 const char orig_data[] = "orig data";
234 const char test_data[] = "test data";
235 char read_data[10];
236
237 rbd_image_t image;
238 ASSERT_EQ(0, rbd_open(ioctx, m_image_name.c_str(), &image, NULL));
239 BOOST_SCOPE_EXIT(image) {
240 EXPECT_EQ(0, rbd_close(image));
241 } BOOST_SCOPE_EXIT_END;
242
243 ASSERT_EQ(10, rbd_write(image, 0, 10, orig_data));
244 ASSERT_EQ(10, rbd_read(image, 0, 10, read_data));
245 ASSERT_EQ(0, memcmp(orig_data, read_data, 10));
246
247 ASSERT_EQ(0, rbd_group_create(ioctx, group_name));
248
249 ASSERT_EQ(0, rbd_group_image_add(ioctx, group_name, ioctx,
250 m_image_name.c_str()));
251
252 struct Watcher {
253 static void quiesce_cb(void *arg) {
254 Watcher *watcher = static_cast<Watcher *>(arg);
255 watcher->handle_quiesce();
256 }
257 static void unquiesce_cb(void *arg) {
258 Watcher *watcher = static_cast<Watcher *>(arg);
259 watcher->handle_unquiesce();
260 }
261
262 rbd_image_t &image;
263 uint64_t handle = 0;
264 size_t quiesce_count = 0;
265 size_t unquiesce_count = 0;
266 int r = 0;
267
268 ceph::mutex lock = ceph::make_mutex("lock");
269 ceph::condition_variable cv;
270
271 Watcher(rbd_image_t &image) : image(image) {
272 }
273
274 void handle_quiesce() {
275 ASSERT_EQ(quiesce_count, unquiesce_count);
276 quiesce_count++;
277 rbd_quiesce_complete(image, handle, r);
278 }
279 void handle_unquiesce() {
280 std::unique_lock locker(lock);
281 unquiesce_count++;
282 cv.notify_one();
283 }
284 bool wait_for_unquiesce(size_t c) {
285 std::unique_lock locker(lock);
286 return cv.wait_for(locker, std::chrono::seconds(60),
287 [this, c]() { return unquiesce_count >= c; });
288 }
289 } watcher(image);
290
291 ASSERT_EQ(0, rbd_quiesce_watch(image, Watcher::quiesce_cb,
292 Watcher::unquiesce_cb, &watcher,
293 &watcher.handle));
294
295 ASSERT_EQ(0, rbd_group_snap_create(ioctx, group_name, snap_name));
296 ASSERT_TRUE(watcher.wait_for_unquiesce(1U));
297 ASSERT_EQ(1U, watcher.quiesce_count);
298
299 size_t num_snaps = 0;
300 ASSERT_EQ(-ERANGE, rbd_group_snap_list(ioctx, group_name, NULL,
301 sizeof(rbd_group_snap_info_t),
302 &num_snaps));
303 ASSERT_EQ(1U, num_snaps);
304
305 rbd_group_snap_info_t snaps[1];
306 ASSERT_EQ(1, rbd_group_snap_list(ioctx, group_name, snaps,
307 sizeof(rbd_group_snap_info_t),
308 &num_snaps));
309
310 ASSERT_STREQ(snap_name, snaps[0].name);
311
312 ASSERT_EQ(10, rbd_write(image, 11, 10, test_data));
313 ASSERT_EQ(10, rbd_read(image, 11, 10, read_data));
314 ASSERT_EQ(0, memcmp(test_data, read_data, 10));
315
316 ASSERT_EQ(0, rbd_group_snap_rollback(ioctx, group_name, snap_name));
317 ASSERT_EQ(10, rbd_read(image, 0, 10, read_data));
318 ASSERT_EQ(0, memcmp(orig_data, read_data, 10));
319
320 ASSERT_EQ(0, rbd_group_snap_list_cleanup(snaps, sizeof(rbd_group_snap_info_t),
321 num_snaps));
322 ASSERT_EQ(0, rbd_group_snap_remove(ioctx, group_name, snap_name));
323
324 ASSERT_EQ(0, rbd_group_snap_list(ioctx, group_name, snaps,
325 sizeof(rbd_group_snap_info_t),
326 &num_snaps));
327 ASSERT_EQ(0U, num_snaps);
328
329 ASSERT_EQ(-EINVAL, rbd_group_snap_create2(ioctx, group_name, snap_name,
330 RBD_SNAP_CREATE_SKIP_QUIESCE |
331 RBD_SNAP_CREATE_IGNORE_QUIESCE_ERROR));
332 watcher.r = -EINVAL;
333 ASSERT_EQ(-EINVAL, rbd_group_snap_create2(ioctx, group_name, snap_name, 0));
334
335 num_snaps = 1;
336 ASSERT_EQ(0, rbd_group_snap_list(ioctx, group_name, snaps,
337 sizeof(rbd_group_snap_info_t),
338 &num_snaps));
339
340 watcher.quiesce_count = 0;
341 watcher.unquiesce_count = 0;
342 ASSERT_EQ(0, rbd_group_snap_create2(ioctx, group_name, snap_name,
343 RBD_SNAP_CREATE_SKIP_QUIESCE));
344 ASSERT_EQ(0U, watcher.quiesce_count);
345 num_snaps = 1;
346 ASSERT_EQ(1, rbd_group_snap_list(ioctx, group_name, snaps,
347 sizeof(rbd_group_snap_info_t),
348 &num_snaps));
349 ASSERT_EQ(0, rbd_group_snap_list_cleanup(snaps, sizeof(rbd_group_snap_info_t),
350 num_snaps));
351 ASSERT_EQ(0, rbd_group_snap_remove(ioctx, group_name, snap_name));
352
353 ASSERT_EQ(0, rbd_group_snap_create2(ioctx, group_name, snap_name,
354 RBD_SNAP_CREATE_IGNORE_QUIESCE_ERROR));
355 ASSERT_EQ(1, rbd_group_snap_list(ioctx, group_name, snaps,
356 sizeof(rbd_group_snap_info_t),
357 &num_snaps));
358 ASSERT_EQ(0, rbd_group_snap_list_cleanup(snaps, sizeof(rbd_group_snap_info_t),
359 num_snaps));
360 ASSERT_EQ(0, rbd_group_snap_remove(ioctx, group_name, snap_name));
361
362 ASSERT_EQ(0, rbd_quiesce_unwatch(image, watcher.handle));
363 ASSERT_EQ(0, rbd_group_remove(ioctx, group_name));
364 }
365
366 TEST_F(TestGroup, add_snapshotPP)
367 {
368 REQUIRE_FORMAT_V2();
369
370 librados::IoCtx ioctx;
371 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
372
373 const char *group_name = "snap_group";
374 const char *snap_name = "snap_snapshot";
375
376 librbd::RBD rbd;
377 ASSERT_EQ(0, rbd.group_create(ioctx, group_name));
378
379 ASSERT_EQ(0, rbd.group_image_add(ioctx, group_name, ioctx,
380 m_image_name.c_str()));
381
382 librbd::Image image;
383 ASSERT_EQ(0, rbd.open(ioctx, image, m_image_name.c_str(), NULL));
384 bufferlist expect_bl;
385 bufferlist read_bl;
386 expect_bl.append(std::string(512, '1'));
387 ASSERT_EQ((ssize_t)expect_bl.length(), image.write(0, expect_bl.length(), expect_bl));
388 ASSERT_EQ(512, image.read(0, 512, read_bl));
389 ASSERT_TRUE(expect_bl.contents_equal(read_bl));
390
391 ASSERT_EQ(0, rbd.group_snap_create(ioctx, group_name, snap_name));
392
393 std::vector<librbd::group_snap_info_t> snaps;
394 ASSERT_EQ(0, rbd.group_snap_list(ioctx, group_name, &snaps,
395 sizeof(librbd::group_snap_info_t)));
396 ASSERT_EQ(1U, snaps.size());
397
398 ASSERT_EQ(snap_name, snaps[0].name);
399
400 bufferlist write_bl;
401 write_bl.append(std::string(1024, '2'));
402 ASSERT_EQ(1024, image.write(513, write_bl.length(), write_bl));
403
404 read_bl.clear();
405 ASSERT_EQ(1024, image.read(513, 1024, read_bl));
406 ASSERT_TRUE(write_bl.contents_equal(read_bl));
407
408 ASSERT_EQ(0, rbd.group_snap_rollback(ioctx, group_name, snap_name));
409
410 ASSERT_EQ(512, image.read(0, 512, read_bl));
411 ASSERT_TRUE(expect_bl.contents_equal(read_bl));
412
413 ASSERT_EQ(0, image.close());
414
415 ASSERT_EQ(0, rbd.group_snap_remove(ioctx, group_name, snap_name));
416
417 snaps.clear();
418 ASSERT_EQ(0, rbd.group_snap_list(ioctx, group_name, &snaps,
419 sizeof(librbd::group_snap_info_t)));
420 ASSERT_EQ(0U, snaps.size());
421
422 ASSERT_EQ(0, rbd.group_snap_create(ioctx, group_name, snap_name));
423 ASSERT_EQ(0, rbd.group_snap_list(ioctx, group_name, &snaps,
424 sizeof(librbd::group_snap_info_t)));
425 ASSERT_EQ(1U, snaps.size());
426 ASSERT_EQ(0, rbd.group_snap_remove(ioctx, group_name, snap_name));
427
428 ASSERT_EQ(-EINVAL, rbd.group_snap_create2(ioctx, group_name, snap_name,
429 RBD_SNAP_CREATE_SKIP_QUIESCE |
430 RBD_SNAP_CREATE_IGNORE_QUIESCE_ERROR));
431 snaps.clear();
432 ASSERT_EQ(0, rbd.group_snap_list(ioctx, group_name, &snaps,
433 sizeof(librbd::group_snap_info_t)));
434 ASSERT_EQ(0U, snaps.size());
435
436 ASSERT_EQ(0, rbd.group_snap_create2(ioctx, group_name, snap_name,
437 RBD_SNAP_CREATE_SKIP_QUIESCE));
438 snaps.clear();
439 ASSERT_EQ(0, rbd.group_snap_list(ioctx, group_name, &snaps,
440 sizeof(librbd::group_snap_info_t)));
441 ASSERT_EQ(1U, snaps.size());
442
443 ASSERT_EQ(0, rbd.group_snap_remove(ioctx, group_name, snap_name));
444 ASSERT_EQ(0, rbd.group_remove(ioctx, group_name));
445 }