1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
11 #include <boost/scope_exit.hpp>
15 void register_test_groups() {
18 class TestGroup
: public TestFixture
{
22 TEST_F(TestGroup
, group_create
)
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
;
31 ASSERT_EQ(0, rbd_group_create(ioctx
, "mygroup"));
34 ASSERT_EQ(-ERANGE
, rbd_group_list(ioctx
, NULL
, &size
));
35 ASSERT_EQ(strlen("mygroup") + 1, size
);
38 ASSERT_EQ(static_cast<int>(strlen("mygroup") + 1),
39 rbd_group_list(ioctx
, groups
, &size
));
40 ASSERT_STREQ("mygroup", groups
);
42 ASSERT_EQ(0, rbd_group_remove(ioctx
, "mygroup"));
44 ASSERT_EQ(0, rbd_group_list(ioctx
, groups
, &size
));
47 TEST_F(TestGroup
, group_createPP
)
49 librados::IoCtx ioctx
;
50 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
53 ASSERT_EQ(0, rbd
.group_create(ioctx
, "mygroup"));
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]);
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]);
66 ASSERT_EQ(0, rbd
.group_remove(ioctx
, "newgroup"));
69 ASSERT_EQ(0, rbd
.group_list(ioctx
, &groups
));
70 ASSERT_EQ(0U, groups
.size());
73 TEST_F(TestGroup
, add_image
)
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
;
83 const char *group_name
= "mycg";
84 ASSERT_EQ(0, rbd_group_create(ioctx
, group_name
));
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
;
93 ASSERT_EQ(0, rbd_get_features(image
, &features
));
94 ASSERT_TRUE((features
& RBD_FEATURE_OPERATIONS
) == 0ULL);
97 ASSERT_EQ(0, rbd_get_op_features(image
, &op_features
));
98 ASSERT_TRUE((op_features
& RBD_OPERATION_FEATURE_GROUP
) == 0ULL);
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
));
106 ASSERT_EQ(0, rbd_group_image_add(ioctx
, group_name
, ioctx
,
107 m_image_name
.c_str()));
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
));
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
);
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
),
126 ASSERT_EQ(1U, num_images
);
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
),
133 ASSERT_EQ(m_image_name
, images
[0].name
);
134 ASSERT_EQ(rados_ioctx_get_id(ioctx
), images
[0].pool
);
136 ASSERT_EQ(0, rbd_group_image_list_cleanup(images
,
137 sizeof(rbd_group_image_info_t
),
139 ASSERT_EQ(0, rbd_group_image_remove(ioctx
, group_name
, ioctx
,
140 m_image_name
.c_str()));
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);
147 ASSERT_EQ(0, rbd_group_image_list(ioctx
, group_name
, images
,
148 sizeof(rbd_group_image_info_t
),
150 ASSERT_EQ(0U, num_images
);
152 ASSERT_EQ(0, rbd_group_remove(ioctx
, group_name
));
155 TEST_F(TestGroup
, add_imagePP
)
159 librados::IoCtx ioctx
;
160 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
162 const char *group_name
= "mycg";
164 ASSERT_EQ(0, rbd
.group_create(ioctx
, group_name
));
167 ASSERT_EQ(0, rbd
.open(ioctx
, image
, m_image_name
.c_str(), NULL
));
170 ASSERT_EQ(0, image
.features(&features
));
171 ASSERT_TRUE((features
& RBD_FEATURE_OPERATIONS
) == 0ULL);
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);
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
);
182 ASSERT_EQ(0, rbd
.group_image_add(ioctx
, group_name
, ioctx
,
183 m_image_name
.c_str()));
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
);
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
);
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
);
204 ASSERT_EQ(0, rbd
.group_image_remove(ioctx
, group_name
, ioctx
,
205 m_image_name
.c_str()));
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);
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());
217 ASSERT_EQ(0, rbd
.group_remove(ioctx
, group_name
));
220 TEST_F(TestGroup
, add_snapshot
)
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
;
230 const char *group_name
= "snap_group";
231 const char *snap_name
= "snap_snapshot";
233 const char orig_data
[] = "orig data";
234 const char test_data
[] = "test data";
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
;
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));
247 ASSERT_EQ(0, rbd_group_create(ioctx
, group_name
));
249 ASSERT_EQ(0, rbd_group_image_add(ioctx
, group_name
, ioctx
,
250 m_image_name
.c_str()));
253 static void quiesce_cb(void *arg
) {
254 Watcher
*watcher
= static_cast<Watcher
*>(arg
);
255 watcher
->handle_quiesce();
257 static void unquiesce_cb(void *arg
) {
258 Watcher
*watcher
= static_cast<Watcher
*>(arg
);
259 watcher
->handle_unquiesce();
264 size_t quiesce_count
= 0;
265 size_t unquiesce_count
= 0;
268 ceph::mutex lock
= ceph::make_mutex("lock");
269 ceph::condition_variable cv
;
271 Watcher(rbd_image_t
&image
) : image(image
) {
274 void handle_quiesce() {
275 ASSERT_EQ(quiesce_count
, unquiesce_count
);
277 rbd_quiesce_complete(image
, handle
, r
);
279 void handle_unquiesce() {
280 std::unique_lock
locker(lock
);
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
; });
291 ASSERT_EQ(0, rbd_quiesce_watch(image
, Watcher::quiesce_cb
,
292 Watcher::unquiesce_cb
, &watcher
,
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
);
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
),
303 ASSERT_EQ(1U, num_snaps
);
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
),
310 ASSERT_STREQ(snap_name
, snaps
[0].name
);
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));
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));
320 ASSERT_EQ(0, rbd_group_snap_list_cleanup(snaps
, sizeof(rbd_group_snap_info_t
),
322 ASSERT_EQ(0, rbd_group_snap_remove(ioctx
, group_name
, snap_name
));
324 ASSERT_EQ(0, rbd_group_snap_list(ioctx
, group_name
, snaps
,
325 sizeof(rbd_group_snap_info_t
),
327 ASSERT_EQ(0U, num_snaps
);
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
));
333 ASSERT_EQ(-EINVAL
, rbd_group_snap_create2(ioctx
, group_name
, snap_name
, 0));
336 ASSERT_EQ(0, rbd_group_snap_list(ioctx
, group_name
, snaps
,
337 sizeof(rbd_group_snap_info_t
),
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
);
346 ASSERT_EQ(1, rbd_group_snap_list(ioctx
, group_name
, snaps
,
347 sizeof(rbd_group_snap_info_t
),
349 ASSERT_EQ(0, rbd_group_snap_list_cleanup(snaps
, sizeof(rbd_group_snap_info_t
),
351 ASSERT_EQ(0, rbd_group_snap_remove(ioctx
, group_name
, snap_name
));
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
),
358 ASSERT_EQ(0, rbd_group_snap_list_cleanup(snaps
, sizeof(rbd_group_snap_info_t
),
360 ASSERT_EQ(0, rbd_group_snap_remove(ioctx
, group_name
, snap_name
));
362 ASSERT_EQ(0, rbd_quiesce_unwatch(image
, watcher
.handle
));
363 ASSERT_EQ(0, rbd_group_remove(ioctx
, group_name
));
366 TEST_F(TestGroup
, add_snapshotPP
)
370 librados::IoCtx ioctx
;
371 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
373 const char *group_name
= "snap_group";
374 const char *snap_name
= "snap_snapshot";
377 ASSERT_EQ(0, rbd
.group_create(ioctx
, group_name
));
379 ASSERT_EQ(0, rbd
.group_image_add(ioctx
, group_name
, ioctx
,
380 m_image_name
.c_str()));
383 ASSERT_EQ(0, rbd
.open(ioctx
, image
, m_image_name
.c_str(), NULL
));
384 bufferlist expect_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
));
391 ASSERT_EQ(0, rbd
.group_snap_create(ioctx
, group_name
, snap_name
));
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());
398 ASSERT_EQ(snap_name
, snaps
[0].name
);
401 write_bl
.append(std::string(1024, '2'));
402 ASSERT_EQ(1024, image
.write(513, write_bl
.length(), write_bl
));
405 ASSERT_EQ(1024, image
.read(513, 1024, read_bl
));
406 ASSERT_TRUE(write_bl
.contents_equal(read_bl
));
408 ASSERT_EQ(0, rbd
.group_snap_rollback(ioctx
, group_name
, snap_name
));
410 ASSERT_EQ(512, image
.read(0, 512, read_bl
));
411 ASSERT_TRUE(expect_bl
.contents_equal(read_bl
));
413 ASSERT_EQ(0, image
.close());
415 ASSERT_EQ(0, rbd
.group_snap_remove(ioctx
, group_name
, snap_name
));
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());
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
));
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
));
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());
436 ASSERT_EQ(0, rbd
.group_snap_create2(ioctx
, group_name
, snap_name
,
437 RBD_SNAP_CREATE_SKIP_QUIESCE
));
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());
443 ASSERT_EQ(0, rbd
.group_snap_remove(ioctx
, group_name
, snap_name
));
444 ASSERT_EQ(0, rbd
.group_remove(ioctx
, group_name
));