1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "common/ceph_context.h"
5 #include "common/config.h"
6 #include "common/snap_types.h"
7 #include "common/Clock.h"
8 #include "include/encoding.h"
9 #include "include/types.h"
10 #include "include/rados/librados.h"
11 #include "include/rbd/object_map_types.h"
12 #include "include/rbd_types.h"
13 #include "include/stringify.h"
14 #include "cls/rbd/cls_rbd.h"
15 #include "cls/rbd/cls_rbd_client.h"
16 #include "cls/rbd/cls_rbd_types.h"
18 #include "gtest/gtest.h"
19 #include "test/librados/test.h"
26 using namespace librbd::cls_client;
27 using ::librbd::ParentInfo;
28 using ::librbd::ParentSpec;
30 static int snapshot_add(librados::IoCtx *ioctx, const std::string &oid,
31 uint64_t snap_id, const std::string &snap_name) {
32 librados::ObjectWriteOperation op;
33 ::librbd::cls_client::snapshot_add(&op, snap_id, snap_name, cls::rbd::UserSnapshotNamespace());
34 return ioctx->operate(oid, &op);
37 static int snapshot_remove(librados::IoCtx *ioctx, const std::string &oid,
39 librados::ObjectWriteOperation op;
40 ::librbd::cls_client::snapshot_remove(&op, snap_id);
41 return ioctx->operate(oid, &op);
44 static int snapshot_rename(librados::IoCtx *ioctx, const std::string &oid,
45 uint64_t snap_id, const std::string &snap_name) {
46 librados::ObjectWriteOperation op;
47 ::librbd::cls_client::snapshot_rename(&op, snap_id, snap_name);
48 return ioctx->operate(oid, &op);
51 static int old_snapshot_add(librados::IoCtx *ioctx, const std::string &oid,
52 uint64_t snap_id, const std::string &snap_name) {
53 librados::ObjectWriteOperation op;
54 ::librbd::cls_client::old_snapshot_add(&op, snap_id, snap_name);
55 return ioctx->operate(oid, &op);
58 static char *random_buf(size_t len)
60 char *b = new char[len];
61 for (size_t i = 0; i < len; i++)
62 b[i] = (rand() % (128 - 32)) + 32;
66 class TestClsRbd : public ::testing::Test {
69 static void SetUpTestCase() {
70 _pool_name = get_temp_pool_name();
71 ASSERT_EQ("", create_one_pool_pp(_pool_name, _rados));
74 static void TearDownTestCase() {
75 ASSERT_EQ(0, destroy_one_pool_pp(_pool_name, _rados));
78 std::string get_temp_image_name() {
80 return "image" + stringify(_image_number);
83 static std::string _pool_name;
84 static librados::Rados _rados;
85 static uint64_t _image_number;
89 std::string TestClsRbd::_pool_name;
90 librados::Rados TestClsRbd::_rados;
91 uint64_t TestClsRbd::_image_number = 0;
93 TEST_F(TestClsRbd, get_all_features)
95 librados::IoCtx ioctx;
96 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
98 string oid = get_temp_image_name();
99 ASSERT_EQ(0, ioctx.create(oid, false));
101 uint64_t all_features = 0;
102 ASSERT_EQ(0, get_all_features(&ioctx, oid, &all_features));
103 ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURES_ALL),
104 static_cast<uint64_t>(all_features & RBD_FEATURES_ALL));
109 TEST_F(TestClsRbd, copyup)
111 librados::IoCtx ioctx;
112 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
114 string oid = get_temp_image_name();
115 bufferlist inbl, outbl;
117 // copyup of 0-len nonexistent object should create new 0-len object
119 ASSERT_EQ(0, copyup(&ioctx, oid, inbl));
121 ASSERT_EQ(0, ioctx.stat(oid, &size, NULL));
124 // create some random data to write
126 char *b = random_buf(l);
129 ASSERT_EQ(l, inbl.length());
131 // copyup to nonexistent object should create new object
133 ASSERT_EQ(-ENOENT, ioctx.remove(oid));
134 ASSERT_EQ(0, copyup(&ioctx, oid, inbl));
135 // and its contents should match
136 ASSERT_EQ(l, (size_t)ioctx.read(oid, outbl, l, 0));
137 ASSERT_TRUE(outbl.contents_equal(inbl));
139 // now send different data, but with a preexisting object
144 ASSERT_EQ(l, inbl2.length());
146 // should still succeed
147 ASSERT_EQ(0, copyup(&ioctx, oid, inbl));
148 ASSERT_EQ(l, (size_t)ioctx.read(oid, outbl, l, 0));
149 // but contents should not have changed
150 ASSERT_FALSE(outbl.contents_equal(inbl2));
151 ASSERT_TRUE(outbl.contents_equal(inbl));
153 ASSERT_EQ(0, ioctx.remove(oid));
157 TEST_F(TestClsRbd, get_and_set_id)
159 librados::IoCtx ioctx;
160 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
162 string oid = get_temp_image_name();
164 string valid_id = "0123abcxyzZYXCBA";
165 string invalid_id = ".abc";
168 ASSERT_EQ(-ENOENT, get_id(&ioctx, oid, &id));
169 ASSERT_EQ(-ENOENT, set_id(&ioctx, oid, valid_id));
171 ASSERT_EQ(0, ioctx.create(oid, true));
172 ASSERT_EQ(-EINVAL, set_id(&ioctx, oid, invalid_id));
173 ASSERT_EQ(-EINVAL, set_id(&ioctx, oid, empty_id));
174 ASSERT_EQ(-ENOENT, get_id(&ioctx, oid, &id));
176 ASSERT_EQ(0, set_id(&ioctx, oid, valid_id));
177 ASSERT_EQ(-EEXIST, set_id(&ioctx, oid, valid_id));
178 ASSERT_EQ(-EEXIST, set_id(&ioctx, oid, valid_id + valid_id));
179 ASSERT_EQ(0, get_id(&ioctx, oid, &id));
180 ASSERT_EQ(id, valid_id);
185 TEST_F(TestClsRbd, add_remove_child)
187 librados::IoCtx ioctx;
188 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
190 string oid = get_temp_image_name();
191 ASSERT_EQ(0, ioctx.create(oid, true));
193 string snapname = "parent_snap";
195 string parent_image = "parent_id";
197 ParentSpec pspec(ioctx.get_id(), parent_image, snapid);
199 // nonexistent children cannot be listed or removed
200 ASSERT_EQ(-ENOENT, get_children(&ioctx, oid, pspec, children));
201 ASSERT_EQ(-ENOENT, remove_child(&ioctx, oid, pspec, "child1"));
203 // create the parent and snapshot
204 ASSERT_EQ(0, create_image(&ioctx, parent_image, 2<<20, 0,
205 RBD_FEATURE_LAYERING, parent_image, -1));
206 ASSERT_EQ(0, snapshot_add(&ioctx, parent_image, snapid, snapname));
208 // add child to it, verify it showed up
209 ASSERT_EQ(0, add_child(&ioctx, oid, pspec, "child1"));
210 ASSERT_EQ(0, get_children(&ioctx, oid, pspec, children));
211 ASSERT_TRUE(children.find("child1") != children.end());
212 // add another child to it, verify it showed up
213 ASSERT_EQ(0, add_child(&ioctx, oid, pspec, "child2"));
214 ASSERT_EQ(0, get_children(&ioctx, oid, pspec, children));
215 ASSERT_TRUE(children.find("child2") != children.end());
216 // add child2 again, expect -EEXIST
217 ASSERT_EQ(-EEXIST, add_child(&ioctx, oid, pspec, "child2"));
218 // remove first, verify it's gone
219 ASSERT_EQ(0, remove_child(&ioctx, oid, pspec, "child1"));
220 ASSERT_EQ(0, get_children(&ioctx, oid, pspec, children));
221 ASSERT_FALSE(children.find("child1") != children.end());
222 // remove second, verify list empty
223 ASSERT_EQ(0, remove_child(&ioctx, oid, pspec, "child2"));
224 ASSERT_EQ(-ENOENT, get_children(&ioctx, oid, pspec, children));
225 // try to remove again, validate -ENOENT to that as well
226 ASSERT_EQ(-ENOENT, remove_child(&ioctx, oid, pspec, "child2"));
231 TEST_F(TestClsRbd, directory_methods)
233 librados::IoCtx ioctx;
234 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
236 string oid = get_temp_image_name();
238 string imgname = get_temp_image_name();
239 string imgname2 = get_temp_image_name();
240 string imgname3 = get_temp_image_name();
241 string valid_id = "0123abcxyzZYXCBA";
242 string valid_id2 = "5";
243 string invalid_id = ".abc";
246 ASSERT_EQ(-ENOENT, dir_get_id(&ioctx, oid, imgname, &id));
247 ASSERT_EQ(-ENOENT, dir_get_name(&ioctx, oid, valid_id, &name));
248 ASSERT_EQ(-ENOENT, dir_remove_image(&ioctx, oid, imgname, valid_id));
250 ASSERT_EQ(-EINVAL, dir_add_image(&ioctx, oid, imgname, invalid_id));
251 ASSERT_EQ(-EINVAL, dir_add_image(&ioctx, oid, imgname, empty));
252 ASSERT_EQ(-EINVAL, dir_add_image(&ioctx, oid, empty, valid_id));
254 map<string, string> images;
255 ASSERT_EQ(-ENOENT, dir_list(&ioctx, oid, "", 30, &images));
257 ASSERT_EQ(0, ioctx.create(oid, true));
258 ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
259 ASSERT_EQ(0u, images.size());
260 ASSERT_EQ(0, ioctx.remove(oid));
262 ASSERT_EQ(0, dir_add_image(&ioctx, oid, imgname, valid_id));
263 ASSERT_EQ(-EEXIST, dir_add_image(&ioctx, oid, imgname, valid_id2));
264 ASSERT_EQ(-EBADF, dir_add_image(&ioctx, oid, imgname2, valid_id));
265 ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
266 ASSERT_EQ(1u, images.size());
267 ASSERT_EQ(valid_id, images[imgname]);
268 ASSERT_EQ(0, dir_list(&ioctx, oid, "", 0, &images));
269 ASSERT_EQ(0u, images.size());
270 ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id, &name));
271 ASSERT_EQ(imgname, name);
272 ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname, &id));
273 ASSERT_EQ(valid_id, id);
275 ASSERT_EQ(0, dir_add_image(&ioctx, oid, imgname2, valid_id2));
276 ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
277 ASSERT_EQ(2u, images.size());
278 ASSERT_EQ(valid_id, images[imgname]);
279 ASSERT_EQ(valid_id2, images[imgname2]);
280 ASSERT_EQ(0, dir_list(&ioctx, oid, imgname, 0, &images));
281 ASSERT_EQ(0u, images.size());
282 ASSERT_EQ(0, dir_list(&ioctx, oid, imgname, 2, &images));
283 ASSERT_EQ(1u, images.size());
284 ASSERT_EQ(valid_id2, images[imgname2]);
285 ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id2, &name));
286 ASSERT_EQ(imgname2, name);
287 ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname2, &id));
288 ASSERT_EQ(valid_id2, id);
290 librados::ObjectWriteOperation op1;
291 dir_rename_image(&op1, imgname, imgname2, valid_id2);
292 ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op1));
293 ASSERT_EQ(-ESTALE, dir_remove_image(&ioctx, oid, imgname, valid_id2));
294 librados::ObjectWriteOperation op2;
295 dir_rename_image(&op2, imgname, imgname2, valid_id);
296 ASSERT_EQ(-EEXIST, ioctx.operate(oid, &op2));
297 ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname, &id));
298 ASSERT_EQ(valid_id, id);
299 ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id2, &name));
300 ASSERT_EQ(imgname2, name);
302 librados::ObjectWriteOperation op3;
303 dir_rename_image(&op3, imgname, imgname3, valid_id);
304 ASSERT_EQ(0, ioctx.operate(oid, &op3));
305 ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname3, &id));
306 ASSERT_EQ(valid_id, id);
307 ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id, &name));
308 ASSERT_EQ(imgname3, name);
309 librados::ObjectWriteOperation op4;
310 dir_rename_image(&op4, imgname3, imgname, valid_id);
311 ASSERT_EQ(0, ioctx.operate(oid, &op4));
313 ASSERT_EQ(0, dir_remove_image(&ioctx, oid, imgname, valid_id));
314 ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
315 ASSERT_EQ(1u, images.size());
316 ASSERT_EQ(valid_id2, images[imgname2]);
317 ASSERT_EQ(0, dir_list(&ioctx, oid, imgname2, 30, &images));
318 ASSERT_EQ(0u, images.size());
319 ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id2, &name));
320 ASSERT_EQ(imgname2, name);
321 ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname2, &id));
322 ASSERT_EQ(valid_id2, id);
323 ASSERT_EQ(-ENOENT, dir_get_name(&ioctx, oid, valid_id, &name));
324 ASSERT_EQ(-ENOENT, dir_get_id(&ioctx, oid, imgname, &id));
326 ASSERT_EQ(0, dir_add_image(&ioctx, oid, imgname, valid_id));
327 ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
328 ASSERT_EQ(2u, images.size());
329 ASSERT_EQ(valid_id, images[imgname]);
330 ASSERT_EQ(valid_id2, images[imgname2]);
331 ASSERT_EQ(0, dir_remove_image(&ioctx, oid, imgname, valid_id));
332 ASSERT_EQ(-ENOENT, dir_remove_image(&ioctx, oid, imgname, valid_id));
333 ASSERT_EQ(0, dir_remove_image(&ioctx, oid, imgname2, valid_id2));
334 ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
335 ASSERT_EQ(0u, images.size());
340 TEST_F(TestClsRbd, create)
342 librados::IoCtx ioctx;
343 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
345 string oid = get_temp_image_name();
346 uint64_t size = 20ULL << 30;
347 uint64_t features = 0;
349 string object_prefix = oid;
351 ASSERT_EQ(0, create_image(&ioctx, oid, size, order,
352 features, object_prefix, -1));
353 ASSERT_EQ(-EEXIST, create_image(&ioctx, oid, size, order,
354 features, object_prefix, -1));
355 ASSERT_EQ(0, ioctx.remove(oid));
357 ASSERT_EQ(-EINVAL, create_image(&ioctx, oid, size, order,
359 ASSERT_EQ(-ENOENT, ioctx.remove(oid));
361 ASSERT_EQ(0, create_image(&ioctx, oid, 0, order,
362 features, object_prefix, -1));
363 ASSERT_EQ(0, ioctx.remove(oid));
365 ASSERT_EQ(-ENOSYS, create_image(&ioctx, oid, size, order,
366 -1, object_prefix, -1));
367 ASSERT_EQ(-ENOENT, ioctx.remove(oid));
369 ASSERT_EQ(0, create_image(&ioctx, oid, size, order, RBD_FEATURE_DATA_POOL,
370 object_prefix, 123));
371 ASSERT_EQ(0, ioctx.remove(oid));
372 ASSERT_EQ(-EINVAL, create_image(&ioctx, oid, size, order,
373 RBD_FEATURE_DATA_POOL, object_prefix, -1));
374 ASSERT_EQ(-EINVAL, create_image(&ioctx, oid, size, order, 0, object_prefix,
377 bufferlist inbl, outbl;
378 ASSERT_EQ(-EINVAL, ioctx.exec(oid, "rbd", "create", inbl, outbl));
383 TEST_F(TestClsRbd, get_features)
385 librados::IoCtx ioctx;
386 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
388 string oid = get_temp_image_name();
391 ASSERT_EQ(-ENOENT, get_features(&ioctx, oid, CEPH_NOSNAP, &features));
393 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
394 ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &features));
395 ASSERT_EQ(0u, features);
397 int r = get_features(&ioctx, oid, 1, &features);
399 ASSERT_EQ(0u, features);
401 // deprecated snapshot handling
402 ASSERT_EQ(-ENOENT, r);
408 TEST_F(TestClsRbd, get_object_prefix)
410 librados::IoCtx ioctx;
411 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
413 string oid = get_temp_image_name();
415 string object_prefix;
416 ASSERT_EQ(-ENOENT, get_object_prefix(&ioctx, oid, &object_prefix));
418 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
419 ASSERT_EQ(0, get_object_prefix(&ioctx, oid, &object_prefix));
420 ASSERT_EQ(oid, object_prefix);
425 TEST_F(TestClsRbd, get_create_timestamp)
427 librados::IoCtx ioctx;
428 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
430 string oid = get_temp_image_name();
431 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
434 ASSERT_EQ(0, get_create_timestamp(&ioctx, oid, ×tamp));
435 ASSERT_LT(0U, timestamp.tv.tv_sec);
440 TEST_F(TestClsRbd, get_data_pool)
442 librados::IoCtx ioctx;
443 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
445 string oid = get_temp_image_name();
447 int64_t data_pool_id;
448 ASSERT_EQ(0, ioctx.create(oid, true));
449 ASSERT_EQ(0, get_data_pool(&ioctx, oid, &data_pool_id));
450 ASSERT_EQ(-1, data_pool_id);
451 ASSERT_EQ(0, ioctx.remove(oid));
453 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, RBD_FEATURE_DATA_POOL, oid,
455 ASSERT_EQ(0, get_data_pool(&ioctx, oid, &data_pool_id));
456 ASSERT_EQ(12, data_pool_id);
459 TEST_F(TestClsRbd, get_size)
461 librados::IoCtx ioctx;
462 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
464 string oid = get_temp_image_name();
467 ASSERT_EQ(-ENOENT, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
469 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
470 ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
472 ASSERT_EQ(22, order);
473 ASSERT_EQ(0, ioctx.remove(oid));
475 ASSERT_EQ(0, create_image(&ioctx, oid, 2 << 22, 0, 0, oid, -1));
476 ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
477 ASSERT_EQ(2u << 22, size);
480 ASSERT_EQ(-ENOENT, get_size(&ioctx, oid, 1, &size, &order));
485 TEST_F(TestClsRbd, set_size)
487 librados::IoCtx ioctx;
488 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
490 string oid = get_temp_image_name();
491 ASSERT_EQ(-ENOENT, set_size(&ioctx, oid, 5));
495 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
496 ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
498 ASSERT_EQ(22, order);
500 ASSERT_EQ(0, set_size(&ioctx, oid, 0));
501 ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
503 ASSERT_EQ(22, order);
505 ASSERT_EQ(0, set_size(&ioctx, oid, 3 << 22));
506 ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
507 ASSERT_EQ(3u << 22, size);
508 ASSERT_EQ(22, order);
513 TEST_F(TestClsRbd, protection_status)
515 librados::IoCtx ioctx;
516 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
518 string oid = get_temp_image_name();
519 string oid2 = get_temp_image_name();
520 uint8_t status = RBD_PROTECTION_STATUS_UNPROTECTED;
521 ASSERT_EQ(-ENOENT, get_protection_status(&ioctx, oid,
522 CEPH_NOSNAP, &status));
523 ASSERT_EQ(-ENOENT, set_protection_status(&ioctx, oid,
524 CEPH_NOSNAP, status));
526 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, RBD_FEATURE_LAYERING, oid, -1));
527 ASSERT_EQ(0, create_image(&ioctx, oid2, 0, 22, 0, oid, -1));
528 ASSERT_EQ(-EINVAL, get_protection_status(&ioctx, oid2,
529 CEPH_NOSNAP, &status));
530 ASSERT_EQ(-ENOEXEC, set_protection_status(&ioctx, oid2,
531 CEPH_NOSNAP, status));
532 ASSERT_EQ(-EINVAL, get_protection_status(&ioctx, oid,
533 CEPH_NOSNAP, &status));
534 ASSERT_EQ(-EINVAL, set_protection_status(&ioctx, oid,
535 CEPH_NOSNAP, status));
536 ASSERT_EQ(-ENOENT, get_protection_status(&ioctx, oid,
538 ASSERT_EQ(-ENOENT, set_protection_status(&ioctx, oid,
541 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 10, "snap1"));
542 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
544 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED, status);
546 ASSERT_EQ(0, set_protection_status(&ioctx, oid,
547 10, RBD_PROTECTION_STATUS_PROTECTED));
548 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
550 ASSERT_EQ(+RBD_PROTECTION_STATUS_PROTECTED, status);
551 ASSERT_EQ(-EBUSY, snapshot_remove(&ioctx, oid, 10));
553 ASSERT_EQ(0, set_protection_status(&ioctx, oid,
554 10, RBD_PROTECTION_STATUS_UNPROTECTING));
555 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
557 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTING, status);
558 ASSERT_EQ(-EBUSY, snapshot_remove(&ioctx, oid, 10));
560 ASSERT_EQ(-EINVAL, set_protection_status(&ioctx, oid,
561 10, RBD_PROTECTION_STATUS_LAST));
562 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
564 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTING, status);
566 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 20, "snap2"));
567 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
569 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED, status);
570 ASSERT_EQ(0, set_protection_status(&ioctx, oid,
571 10, RBD_PROTECTION_STATUS_UNPROTECTED));
572 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
574 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED, status);
576 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 10));
577 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 20));
582 TEST_F(TestClsRbd, snapshot_limits)
584 librados::IoCtx ioctx;
585 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
587 librados::ObjectWriteOperation op;
588 string oid = get_temp_image_name();
591 ASSERT_EQ(-ENOENT, snapshot_get_limit(&ioctx, oid, &limit));
593 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, RBD_FEATURE_LAYERING, oid, -1));
595 snapshot_set_limit(&op, 2);
597 ASSERT_EQ(0, ioctx.operate(oid, &op));
599 ASSERT_EQ(0, snapshot_get_limit(&ioctx, oid, &limit));
600 ASSERT_EQ(2U, limit);
602 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 10, "snap1"));
603 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 20, "snap2"));
604 ASSERT_EQ(-EDQUOT, snapshot_add(&ioctx, oid, 30, "snap3"));
606 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 10));
607 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 20));
612 TEST_F(TestClsRbd, parents)
614 librados::IoCtx ioctx;
615 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
617 string oid = get_temp_image_name();
621 ASSERT_EQ(-ENOENT, get_parent(&ioctx, "doesnotexist", CEPH_NOSNAP, &pspec, &size));
623 // old image should fail
624 ASSERT_EQ(0, create_image(&ioctx, "old", 33<<20, 22, 0, "old_blk.", -1));
625 // get nonexistent parent: succeed, return (-1, "", CEPH_NOSNAP), overlap 0
626 ASSERT_EQ(0, get_parent(&ioctx, "old", CEPH_NOSNAP, &pspec, &size));
627 ASSERT_EQ(pspec.pool_id, -1);
628 ASSERT_STREQ("", pspec.image_id.c_str());
629 ASSERT_EQ(pspec.snap_id, CEPH_NOSNAP);
630 ASSERT_EQ(size, 0ULL);
631 pspec = ParentSpec(-1, "parent", 3);
632 ASSERT_EQ(-ENOEXEC, set_parent(&ioctx, "old", ParentSpec(-1, "parent", 3), 10<<20));
633 ASSERT_EQ(-ENOEXEC, remove_parent(&ioctx, "old"));
635 // new image will work
636 ASSERT_EQ(0, create_image(&ioctx, oid, 33<<20, 22, RBD_FEATURE_LAYERING,
639 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
640 ASSERT_EQ(-1, pspec.pool_id);
641 ASSERT_EQ(0, get_parent(&ioctx, oid, 123, &pspec, &size));
642 ASSERT_EQ(-1, pspec.pool_id);
644 ASSERT_EQ(-EINVAL, set_parent(&ioctx, oid, ParentSpec(-1, "parent", 3), 10<<20));
645 ASSERT_EQ(-EINVAL, set_parent(&ioctx, oid, ParentSpec(1, "", 3), 10<<20));
646 ASSERT_EQ(-EINVAL, set_parent(&ioctx, oid, ParentSpec(1, "parent", CEPH_NOSNAP), 10<<20));
647 ASSERT_EQ(-EINVAL, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 0));
649 pspec = ParentSpec(1, "parent", 3);
650 ASSERT_EQ(0, set_parent(&ioctx, oid, pspec, 10<<20));
651 ASSERT_EQ(-EEXIST, set_parent(&ioctx, oid, pspec, 10<<20));
652 ASSERT_EQ(-EEXIST, set_parent(&ioctx, oid, ParentSpec(2, "parent", 34), 10<<20));
654 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
655 ASSERT_EQ(pspec.pool_id, 1);
656 ASSERT_EQ(pspec.image_id, "parent");
657 ASSERT_EQ(pspec.snap_id, snapid_t(3));
659 ASSERT_EQ(0, remove_parent(&ioctx, oid));
660 ASSERT_EQ(-ENOENT, remove_parent(&ioctx, oid));
661 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
662 ASSERT_EQ(-1, pspec.pool_id);
665 ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 10<<20));
666 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 10, "snap1"));
667 ASSERT_EQ(0, get_parent(&ioctx, oid, 10, &pspec, &size));
668 ASSERT_EQ(pspec.pool_id, 1);
669 ASSERT_EQ(pspec.image_id, "parent");
670 ASSERT_EQ(pspec.snap_id, snapid_t(3));
671 ASSERT_EQ(size, 10ull<<20);
673 ASSERT_EQ(0, remove_parent(&ioctx, oid));
674 ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(4, "parent2", 6), 5<<20));
675 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 11, "snap2"));
676 ASSERT_EQ(0, get_parent(&ioctx, oid, 10, &pspec, &size));
677 ASSERT_EQ(pspec.pool_id, 1);
678 ASSERT_EQ(pspec.image_id, "parent");
679 ASSERT_EQ(pspec.snap_id, snapid_t(3));
680 ASSERT_EQ(size, 10ull<<20);
681 ASSERT_EQ(0, get_parent(&ioctx, oid, 11, &pspec, &size));
682 ASSERT_EQ(pspec.pool_id, 4);
683 ASSERT_EQ(pspec.image_id, "parent2");
684 ASSERT_EQ(pspec.snap_id, snapid_t(6));
685 ASSERT_EQ(size, 5ull<<20);
687 ASSERT_EQ(0, remove_parent(&ioctx, oid));
688 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 12, "snap3"));
689 ASSERT_EQ(0, get_parent(&ioctx, oid, 10, &pspec, &size));
690 ASSERT_EQ(pspec.pool_id, 1);
691 ASSERT_EQ(pspec.image_id, "parent");
692 ASSERT_EQ(pspec.snap_id, snapid_t(3));
693 ASSERT_EQ(size, 10ull<<20);
694 ASSERT_EQ(0, get_parent(&ioctx, oid, 11, &pspec, &size));
695 ASSERT_EQ(pspec.pool_id, 4);
696 ASSERT_EQ(pspec.image_id, "parent2");
697 ASSERT_EQ(pspec.snap_id, snapid_t(6));
698 ASSERT_EQ(size, 5ull<<20);
699 ASSERT_EQ(0, get_parent(&ioctx, oid, 12, &pspec, &size));
700 ASSERT_EQ(-1, pspec.pool_id);
702 // make sure set_parent takes min of our size and parent's size
703 ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 1<<20));
704 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
705 ASSERT_EQ(pspec.pool_id, 1);
706 ASSERT_EQ(pspec.image_id, "parent");
707 ASSERT_EQ(pspec.snap_id, snapid_t(3));
708 ASSERT_EQ(size, 1ull<<20);
709 ASSERT_EQ(0, remove_parent(&ioctx, oid));
711 ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 100<<20));
712 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
713 ASSERT_EQ(pspec.pool_id, 1);
714 ASSERT_EQ(pspec.image_id, "parent");
715 ASSERT_EQ(pspec.snap_id, snapid_t(3));
716 ASSERT_EQ(size, 33ull<<20);
717 ASSERT_EQ(0, remove_parent(&ioctx, oid));
719 // make sure resize adjust parent overlap
720 ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 10<<20));
722 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 14, "snap4"));
723 ASSERT_EQ(0, set_size(&ioctx, oid, 3 << 20));
724 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
725 ASSERT_EQ(pspec.pool_id, 1);
726 ASSERT_EQ(pspec.image_id, "parent");
727 ASSERT_EQ(pspec.snap_id, snapid_t(3));
728 ASSERT_EQ(size, 3ull<<20);
729 ASSERT_EQ(0, get_parent(&ioctx, oid, 14, &pspec, &size));
730 ASSERT_EQ(pspec.pool_id, 1);
731 ASSERT_EQ(pspec.image_id, "parent");
732 ASSERT_EQ(pspec.snap_id, snapid_t(3));
733 ASSERT_EQ(size, 10ull<<20);
735 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 15, "snap5"));
736 ASSERT_EQ(0, set_size(&ioctx, oid, 30 << 20));
737 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
738 ASSERT_EQ(pspec.pool_id, 1);
739 ASSERT_EQ(pspec.image_id, "parent");
740 ASSERT_EQ(pspec.snap_id, snapid_t(3));
741 ASSERT_EQ(size, 3ull<<20);
742 ASSERT_EQ(0, get_parent(&ioctx, oid, 14, &pspec, &size));
743 ASSERT_EQ(pspec.pool_id, 1);
744 ASSERT_EQ(pspec.image_id, "parent");
745 ASSERT_EQ(pspec.snap_id, snapid_t(3));
746 ASSERT_EQ(size, 10ull<<20);
747 ASSERT_EQ(0, get_parent(&ioctx, oid, 15, &pspec, &size));
748 ASSERT_EQ(pspec.pool_id, 1);
749 ASSERT_EQ(pspec.image_id, "parent");
750 ASSERT_EQ(pspec.snap_id, snapid_t(3));
751 ASSERT_EQ(size, 3ull<<20);
753 ASSERT_EQ(0, set_size(&ioctx, oid, 2 << 20));
754 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
755 ASSERT_EQ(pspec.pool_id, 1);
756 ASSERT_EQ(pspec.image_id, "parent");
757 ASSERT_EQ(pspec.snap_id, snapid_t(3));
758 ASSERT_EQ(size, 2ull<<20);
760 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 16, "snap6"));
761 ASSERT_EQ(0, get_parent(&ioctx, oid, 16, &pspec, &size));
762 ASSERT_EQ(pspec.pool_id, 1);
763 ASSERT_EQ(pspec.image_id, "parent");
764 ASSERT_EQ(pspec.snap_id, snapid_t(3));
765 ASSERT_EQ(size, 2ull<<20);
767 ASSERT_EQ(0, ioctx.remove(oid));
768 ASSERT_EQ(0, create_image(&ioctx, oid, 33<<20, 22,
769 RBD_FEATURE_LAYERING | RBD_FEATURE_DEEP_FLATTEN,
771 ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 100<<20));
772 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 1, "snap1"));
773 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 2, "snap2"));
774 ASSERT_EQ(0, remove_parent(&ioctx, oid));
776 ASSERT_EQ(0, get_parent(&ioctx, oid, 1, &pspec, &size));
777 ASSERT_EQ(-1, pspec.pool_id);
778 ASSERT_EQ(0, get_parent(&ioctx, oid, 2, &pspec, &size));
779 ASSERT_EQ(-1, pspec.pool_id);
780 ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
781 ASSERT_EQ(-1, pspec.pool_id);
786 TEST_F(TestClsRbd, snapshots)
788 cls::rbd::SnapshotNamespace userSnapNamespace = cls::rbd::UserSnapshotNamespace();
789 librados::IoCtx ioctx;
790 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
792 string oid = get_temp_image_name();
793 ASSERT_EQ(-ENOENT, snapshot_add(&ioctx, oid, 0, "snap1"));
795 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
797 vector<string> snap_names;
798 vector<cls::rbd::SnapshotNamespace> snap_namespaces;
799 vector<uint64_t> snap_sizes;
801 vector<ParentInfo> parents;
802 vector<uint8_t> protection_status;
803 vector<utime_t> snap_timestamps;
805 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
806 ASSERT_EQ(0u, snapc.snaps.size());
807 ASSERT_EQ(0u, snapc.seq);
808 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
809 &snap_sizes, &parents, &protection_status));
810 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
811 ASSERT_EQ(0u, snap_names.size());
812 ASSERT_EQ(0u, snap_namespaces.size());
813 ASSERT_EQ(0u, snap_sizes.size());
814 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
815 ASSERT_EQ(0u, snap_timestamps.size());
817 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
818 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
819 ASSERT_EQ(1u, snapc.snaps.size());
820 ASSERT_EQ(0u, snapc.snaps[0]);
821 ASSERT_EQ(0u, snapc.seq);
822 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
823 &snap_sizes, &parents, &protection_status));
824 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
825 ASSERT_EQ(1u, snap_names.size());
826 ASSERT_EQ("snap1", snap_names[0]);
827 ASSERT_EQ(1u, snap_namespaces.size());
828 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
829 ASSERT_EQ(10u, snap_sizes[0]);
830 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
831 ASSERT_EQ(1u, snap_timestamps.size());
833 // snap with same id and name
834 ASSERT_EQ(-EEXIST, snapshot_add(&ioctx, oid, 0, "snap1"));
835 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
836 ASSERT_EQ(1u, snapc.snaps.size());
837 ASSERT_EQ(0u, snapc.snaps[0]);
838 ASSERT_EQ(0u, snapc.seq);
839 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
840 &snap_sizes, &parents, &protection_status));
841 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
842 ASSERT_EQ(1u, snap_names.size());
843 ASSERT_EQ("snap1", snap_names[0]);
844 ASSERT_EQ(1u, snap_namespaces.size());
845 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
846 ASSERT_EQ(10u, snap_sizes[0]);
847 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
848 ASSERT_EQ(1u, snap_timestamps.size());
851 // snap with same id, different name
852 ASSERT_EQ(-EEXIST, snapshot_add(&ioctx, oid, 0, "snap2"));
853 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
854 ASSERT_EQ(1u, snapc.snaps.size());
855 ASSERT_EQ(0u, snapc.snaps[0]);
856 ASSERT_EQ(0u, snapc.seq);
857 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
858 &snap_sizes, &parents, &protection_status));
859 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
860 ASSERT_EQ(1u, snap_names.size());
861 ASSERT_EQ("snap1", snap_names[0]);
862 ASSERT_EQ(1u, snap_namespaces.size());
863 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
864 ASSERT_EQ(10u, snap_sizes[0]);
865 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
866 ASSERT_EQ(1u, snap_timestamps.size());
868 // snap with different id, same name
869 ASSERT_EQ(-EEXIST, snapshot_add(&ioctx, oid, 1, "snap1"));
870 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
871 ASSERT_EQ(1u, snapc.snaps.size());
872 ASSERT_EQ(0u, snapc.snaps[0]);
873 ASSERT_EQ(0u, snapc.seq);
874 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
875 &snap_sizes, &parents, &protection_status));
876 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
877 ASSERT_EQ(snap_names.size(), 1u);
878 ASSERT_EQ(snap_names[0], "snap1");
879 ASSERT_EQ(1u, snap_namespaces.size());
880 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
881 ASSERT_EQ(snap_sizes[0], 10u);
882 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
883 ASSERT_EQ(1u, snap_timestamps.size());
885 // snap with different id, different name
886 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 1, "snap2"));
887 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
888 ASSERT_EQ(2u, snapc.snaps.size());
889 ASSERT_EQ(1u, snapc.snaps[0]);
890 ASSERT_EQ(0u, snapc.snaps[1]);
891 ASSERT_EQ(1u, snapc.seq);
892 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
893 &snap_sizes, &parents, &protection_status));
894 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
895 ASSERT_EQ(2u, snap_names.size());
896 ASSERT_EQ(2u, snap_namespaces.size());
897 ASSERT_EQ("snap2", snap_names[0]);
898 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
899 ASSERT_EQ(10u, snap_sizes[0]);
900 ASSERT_EQ("snap1", snap_names[1]);
901 ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
902 ASSERT_EQ(10u, snap_sizes[1]);
903 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
904 ASSERT_EQ(2u, snap_timestamps.size());
906 ASSERT_EQ(0, snapshot_rename(&ioctx, oid, 0, "snap1-rename"));
907 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
908 &snap_sizes, &parents, &protection_status));
909 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
910 ASSERT_EQ(2u, snap_names.size());
911 ASSERT_EQ(2u, snap_namespaces.size());
912 ASSERT_EQ("snap2", snap_names[0]);
913 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
914 ASSERT_EQ(10u, snap_sizes[0]);
915 ASSERT_EQ("snap1-rename", snap_names[1]);
916 ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
917 ASSERT_EQ(10u, snap_sizes[1]);
918 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
919 ASSERT_EQ(2u, snap_timestamps.size());
921 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 0));
922 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
923 ASSERT_EQ(1u, snapc.snaps.size());
924 ASSERT_EQ(1u, snapc.snaps[0]);
925 ASSERT_EQ(1u, snapc.seq);
926 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
927 &snap_sizes, &parents, &protection_status));
928 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
929 ASSERT_EQ(1u, snap_names.size());
930 ASSERT_EQ(1u, snap_namespaces.size());
931 ASSERT_EQ("snap2", snap_names[0]);
932 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
933 ASSERT_EQ(10u, snap_sizes[0]);
934 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
935 ASSERT_EQ(1u, snap_timestamps.size());
939 ASSERT_EQ(0, set_size(&ioctx, oid, 0));
940 ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
942 ASSERT_EQ(22u, order);
944 uint64_t large_snap_id = 1ull << 63;
945 ASSERT_EQ(0, snapshot_add(&ioctx, oid, large_snap_id, "snap3"));
946 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
947 ASSERT_EQ(2u, snapc.snaps.size());
948 ASSERT_EQ(large_snap_id, snapc.snaps[0]);
949 ASSERT_EQ(1u, snapc.snaps[1]);
950 ASSERT_EQ(large_snap_id, snapc.seq);
951 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
952 &snap_sizes, &parents, &protection_status));
953 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
954 ASSERT_EQ(2u, snap_names.size());
955 ASSERT_EQ(2u, snap_namespaces.size());
956 ASSERT_EQ("snap3", snap_names[0]);
957 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
958 ASSERT_EQ(0u, snap_sizes[0]);
959 ASSERT_EQ("snap2", snap_names[1]);
960 ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
961 ASSERT_EQ(10u, snap_sizes[1]);
962 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
963 ASSERT_EQ(2u, snap_timestamps.size());
965 ASSERT_EQ(0, get_size(&ioctx, oid, large_snap_id, &size, &order));
967 ASSERT_EQ(22u, order);
969 ASSERT_EQ(0, get_size(&ioctx, oid, 1, &size, &order));
970 ASSERT_EQ(10u, size);
971 ASSERT_EQ(22u, order);
973 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, large_snap_id));
974 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
975 ASSERT_EQ(1u, snapc.snaps.size());
976 ASSERT_EQ(1u, snapc.snaps[0]);
977 ASSERT_EQ(large_snap_id, snapc.seq);
978 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
979 &snap_sizes, &parents, &protection_status));
980 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
981 ASSERT_EQ(1u, snap_names.size());
982 ASSERT_EQ(1u, snap_namespaces.size());
983 ASSERT_EQ("snap2", snap_names[0]);
984 ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
985 ASSERT_EQ(10u, snap_sizes[0]);
986 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
987 ASSERT_EQ(1u, snap_timestamps.size());
989 ASSERT_EQ(-ENOENT, snapshot_remove(&ioctx, oid, large_snap_id));
990 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 1));
991 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
992 ASSERT_EQ(0u, snapc.snaps.size());
993 ASSERT_EQ(large_snap_id, snapc.seq);
994 ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
995 &snap_sizes, &parents, &protection_status));
996 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
997 ASSERT_EQ(0u, snap_names.size());
998 ASSERT_EQ(0u, snap_namespaces.size());
999 ASSERT_EQ(0u, snap_sizes.size());
1000 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
1001 ASSERT_EQ(0u, snap_timestamps.size());
1006 TEST_F(TestClsRbd, snapshots_namespaces)
1008 cls::rbd::SnapshotNamespace groupSnapNamespace = cls::rbd::GroupSnapshotNamespace(5, "1018643c9869", 3);
1009 cls::rbd::SnapshotNamespace userSnapNamespace = cls::rbd::UserSnapshotNamespace();
1010 librados::IoCtx ioctx;
1011 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1013 string oid = get_temp_image_name();
1015 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
1017 vector<cls::rbd::SnapshotNamespace> snap_namespaces;
1020 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
1021 ASSERT_EQ(0u, snapc.snaps.size());
1022 ASSERT_EQ(0u, snapc.seq);
1023 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
1024 ASSERT_EQ(0u, snap_namespaces.size());
1026 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
1028 librados::ObjectWriteOperation op;
1029 ::librbd::cls_client::snapshot_add(&op, 1, "snap1", groupSnapNamespace);
1030 int r = ioctx.operate(oid, &op);
1033 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
1034 ASSERT_EQ(2u, snapc.snaps.size());
1035 ASSERT_EQ(1u, snapc.snaps[0]);
1036 ASSERT_EQ(0u, snapc.snaps[1]);
1037 ASSERT_EQ(1u, snapc.seq);
1038 ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
1039 ASSERT_EQ(groupSnapNamespace, snap_namespaces[0]);
1040 ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
1045 TEST_F(TestClsRbd, snapshots_timestamps)
1047 librados::IoCtx ioctx;
1048 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1050 string oid = get_temp_image_name();
1052 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
1054 vector<utime_t> snap_timestamps;
1057 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
1058 ASSERT_EQ(0u, snapc.snaps.size());
1059 ASSERT_EQ(0u, snapc.seq);
1060 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
1061 ASSERT_EQ(0u, snap_timestamps.size());
1063 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
1065 ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
1066 ASSERT_EQ(1u, snapc.snaps.size());
1067 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
1068 ASSERT_LT(0U, snap_timestamps[0].tv.tv_sec);
1073 TEST_F(TestClsRbd, snapid_race)
1075 librados::IoCtx ioctx;
1076 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1079 buffer::ptr bp(4096);
1083 string oid = get_temp_image_name();
1084 ASSERT_EQ(0, ioctx.write(oid, bl, 4096, 0));
1085 ASSERT_EQ(0, old_snapshot_add(&ioctx, oid, 1, "test1"));
1086 ASSERT_EQ(0, old_snapshot_add(&ioctx, oid, 3, "test3"));
1087 ASSERT_EQ(-ESTALE, old_snapshot_add(&ioctx, oid, 2, "test2"));
1092 TEST_F(TestClsRbd, stripingv2)
1094 librados::IoCtx ioctx;
1095 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1097 string oid = get_temp_image_name();
1098 string oid2 = get_temp_image_name();
1099 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
1101 uint64_t su = 65536, sc = 12;
1102 ASSERT_EQ(-ENOEXEC, get_stripe_unit_count(&ioctx, oid, &su, &sc));
1103 ASSERT_EQ(-ENOEXEC, set_stripe_unit_count(&ioctx, oid, su, sc));
1105 ASSERT_EQ(0, create_image(&ioctx, oid2, 10, 22, RBD_FEATURE_STRIPINGV2,
1107 ASSERT_EQ(0, get_stripe_unit_count(&ioctx, oid2, &su, &sc));
1108 ASSERT_EQ(1ull << 22, su);
1109 ASSERT_EQ(1ull, sc);
1112 ASSERT_EQ(0, set_stripe_unit_count(&ioctx, oid2, su, sc));
1114 ASSERT_EQ(0, get_stripe_unit_count(&ioctx, oid2, &su, &sc));
1115 ASSERT_EQ(8192ull, su);
1116 ASSERT_EQ(456ull, sc);
1118 // su must not be larger than an object
1119 ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 1 << 23, 1));
1120 // su must be a factor of object size
1121 ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 511, 1));
1122 // su and sc must be non-zero
1123 ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 0, 1));
1124 ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 1, 0));
1125 ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 0, 0));
1130 TEST_F(TestClsRbd, get_mutable_metadata_features)
1132 librados::IoCtx ioctx;
1133 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1135 string oid = get_temp_image_name();
1136 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, RBD_FEATURE_EXCLUSIVE_LOCK,
1139 uint64_t size, features, incompatible_features;
1140 std::map<rados::cls::lock::locker_id_t,
1141 rados::cls::lock::locker_info_t> lockers;
1142 bool exclusive_lock;
1143 std::string lock_tag;
1144 ::SnapContext snapc;
1147 ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, true, &size, &features,
1148 &incompatible_features, &lockers,
1149 &exclusive_lock, &lock_tag, &snapc,
1151 ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK), features);
1152 ASSERT_EQ(0U, incompatible_features);
1154 ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, false, &size, &features,
1155 &incompatible_features, &lockers,
1156 &exclusive_lock, &lock_tag, &snapc,
1158 ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK), features);
1159 ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK),
1160 incompatible_features);
1165 TEST_F(TestClsRbd, object_map_save)
1167 librados::IoCtx ioctx;
1168 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1170 string oid = get_temp_image_name();
1171 BitVector<2> ref_bit_vector;
1172 ref_bit_vector.resize(32);
1173 for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1174 ref_bit_vector[i] = 1;
1177 librados::ObjectWriteOperation op;
1178 object_map_save(&op, ref_bit_vector);
1179 ASSERT_EQ(0, ioctx.operate(oid, &op));
1181 BitVector<2> osd_bit_vector;
1182 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1183 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1186 TEST_F(TestClsRbd, object_map_resize)
1188 librados::IoCtx ioctx;
1189 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1191 string oid = get_temp_image_name();
1192 BitVector<2> ref_bit_vector;
1193 ref_bit_vector.resize(32);
1194 for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1195 ref_bit_vector[i] = 1;
1198 librados::ObjectWriteOperation op1;
1199 object_map_resize(&op1, ref_bit_vector.size(), 1);
1200 ASSERT_EQ(0, ioctx.operate(oid, &op1));
1202 BitVector<2> osd_bit_vector;
1203 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1204 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1206 ref_bit_vector.resize(64);
1207 for (uint64_t i = 32; i < ref_bit_vector.size(); ++i) {
1208 ref_bit_vector[i] = 2;
1211 librados::ObjectWriteOperation op2;
1212 object_map_resize(&op2, ref_bit_vector.size(), 2);
1213 ASSERT_EQ(0, ioctx.operate(oid, &op2));
1214 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1215 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1217 ref_bit_vector.resize(32);
1219 librados::ObjectWriteOperation op3;
1220 object_map_resize(&op3, ref_bit_vector.size(), 1);
1221 ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op3));
1223 librados::ObjectWriteOperation op4;
1224 object_map_resize(&op4, ref_bit_vector.size(), 2);
1225 ASSERT_EQ(0, ioctx.operate(oid, &op4));
1227 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1228 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1233 TEST_F(TestClsRbd, object_map_update)
1235 librados::IoCtx ioctx;
1236 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1238 string oid = get_temp_image_name();
1239 BitVector<2> ref_bit_vector;
1240 ref_bit_vector.resize(16);
1241 for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1242 ref_bit_vector[i] = 2;
1245 BitVector<2> osd_bit_vector;
1247 librados::ObjectWriteOperation op1;
1248 object_map_resize(&op1, ref_bit_vector.size(), 2);
1249 ASSERT_EQ(0, ioctx.operate(oid, &op1));
1250 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1251 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1253 ref_bit_vector[7] = 1;
1254 ref_bit_vector[8] = 1;
1256 librados::ObjectWriteOperation op2;
1257 object_map_update(&op2, 7, 9, 1, boost::optional<uint8_t>());
1258 ASSERT_EQ(0, ioctx.operate(oid, &op2));
1259 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1260 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1262 ref_bit_vector[7] = 3;
1263 ref_bit_vector[8] = 3;
1265 librados::ObjectWriteOperation op3;
1266 object_map_update(&op3, 6, 10, 3, 1);
1267 ASSERT_EQ(0, ioctx.operate(oid, &op3));
1268 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1269 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1274 TEST_F(TestClsRbd, object_map_load_enoent)
1276 librados::IoCtx ioctx;
1277 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1279 string oid = get_temp_image_name();
1280 BitVector<2> osd_bit_vector;
1281 ASSERT_EQ(-ENOENT, object_map_load(&ioctx, oid, &osd_bit_vector));
1286 TEST_F(TestClsRbd, object_map_snap_add)
1288 librados::IoCtx ioctx;
1289 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1291 string oid = get_temp_image_name();
1292 BitVector<2> ref_bit_vector;
1293 ref_bit_vector.resize(16);
1294 for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1296 ref_bit_vector[i] = OBJECT_NONEXISTENT;
1298 ref_bit_vector[i] = OBJECT_EXISTS;
1302 BitVector<2> osd_bit_vector;
1304 librados::ObjectWriteOperation op1;
1305 object_map_resize(&op1, ref_bit_vector.size(), OBJECT_EXISTS);
1306 ASSERT_EQ(0, ioctx.operate(oid, &op1));
1308 librados::ObjectWriteOperation op2;
1309 object_map_update(&op2, 0, 4, OBJECT_NONEXISTENT, boost::optional<uint8_t>());
1310 ASSERT_EQ(0, ioctx.operate(oid, &op2));
1312 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1313 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1315 librados::ObjectWriteOperation op3;
1316 object_map_snap_add(&op3);
1317 ASSERT_EQ(0, ioctx.operate(oid, &op3));
1319 for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1320 if (ref_bit_vector[i] == OBJECT_EXISTS) {
1321 ref_bit_vector[i] = OBJECT_EXISTS_CLEAN;
1325 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1326 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1329 TEST_F(TestClsRbd, object_map_snap_remove)
1331 librados::IoCtx ioctx;
1332 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1334 string oid = get_temp_image_name();
1335 BitVector<2> ref_bit_vector;
1336 ref_bit_vector.resize(16);
1337 for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1339 ref_bit_vector[i] = OBJECT_EXISTS_CLEAN;
1341 ref_bit_vector[i] = OBJECT_EXISTS;
1345 BitVector<2> osd_bit_vector;
1347 librados::ObjectWriteOperation op1;
1348 object_map_resize(&op1, ref_bit_vector.size(), OBJECT_EXISTS);
1349 ASSERT_EQ(0, ioctx.operate(oid, &op1));
1351 librados::ObjectWriteOperation op2;
1352 object_map_update(&op2, 0, 4, OBJECT_EXISTS_CLEAN, boost::optional<uint8_t>());
1353 ASSERT_EQ(0, ioctx.operate(oid, &op2));
1355 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1356 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1358 BitVector<2> snap_bit_vector;
1359 snap_bit_vector.resize(4);
1360 for (uint64_t i = 0; i < snap_bit_vector.size(); ++i) {
1361 if (i == 1 || i == 2) {
1362 snap_bit_vector[i] = OBJECT_EXISTS;
1364 snap_bit_vector[i] = OBJECT_NONEXISTENT;
1368 librados::ObjectWriteOperation op3;
1369 object_map_snap_remove(&op3, snap_bit_vector);
1370 ASSERT_EQ(0, ioctx.operate(oid, &op3));
1372 ref_bit_vector[1] = OBJECT_EXISTS;
1373 ref_bit_vector[2] = OBJECT_EXISTS;
1374 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1375 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1378 TEST_F(TestClsRbd, flags)
1380 librados::IoCtx ioctx;
1381 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1383 string oid = get_temp_image_name();
1384 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
1387 std::vector<snapid_t> snap_ids;
1388 std::vector<uint64_t> snap_flags;
1389 ASSERT_EQ(0, get_flags(&ioctx, oid, &flags, snap_ids, &snap_flags));
1390 ASSERT_EQ(0U, flags);
1392 librados::ObjectWriteOperation op1;
1393 set_flags(&op1, CEPH_NOSNAP, 3, 2);
1394 ASSERT_EQ(0, ioctx.operate(oid, &op1));
1395 ASSERT_EQ(0, get_flags(&ioctx, oid, &flags, snap_ids, &snap_flags));
1396 ASSERT_EQ(2U, flags);
1398 uint64_t snap_id = 10;
1399 snap_ids.push_back(snap_id);
1400 ASSERT_EQ(-ENOENT, get_flags(&ioctx, oid, &flags, snap_ids, &snap_flags));
1401 ASSERT_EQ(0, snapshot_add(&ioctx, oid, snap_id, "snap"));
1403 librados::ObjectWriteOperation op2;
1404 set_flags(&op2, snap_id, 31, 4);
1405 ASSERT_EQ(0, ioctx.operate(oid, &op2));
1406 ASSERT_EQ(0, get_flags(&ioctx, oid, &flags, snap_ids, &snap_flags));
1407 ASSERT_EQ(2U, flags);
1408 ASSERT_EQ(snap_ids.size(), snap_flags.size());
1409 ASSERT_EQ(6U, snap_flags[0]);
1414 TEST_F(TestClsRbd, metadata)
1416 librados::IoCtx ioctx;
1417 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1419 string oid = get_temp_image_name();
1420 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
1422 map<string, bufferlist> pairs;
1424 ASSERT_EQ(0, metadata_list(&ioctx, oid, "", 0, &pairs));
1425 ASSERT_TRUE(pairs.empty());
1427 pairs["key1"].append("value1");
1428 pairs["key2"].append("value2");
1429 ASSERT_EQ(0, metadata_set(&ioctx, oid, pairs));
1430 ASSERT_EQ(0, metadata_get(&ioctx, oid, "key1", &value));
1431 ASSERT_EQ(0, strcmp("value1", value.c_str()));
1433 ASSERT_EQ(0, metadata_list(&ioctx, oid, "", 0, &pairs));
1434 ASSERT_EQ(2U, pairs.size());
1435 ASSERT_EQ(0, strncmp("value1", pairs["key1"].c_str(), 6));
1436 ASSERT_EQ(0, strncmp("value2", pairs["key2"].c_str(), 6));
1439 ASSERT_EQ(0, metadata_remove(&ioctx, oid, "key1"));
1440 ASSERT_EQ(0, metadata_remove(&ioctx, oid, "key3"));
1441 ASSERT_TRUE(metadata_get(&ioctx, oid, "key1", &value) < 0);
1442 ASSERT_EQ(0, metadata_list(&ioctx, oid, "", 0, &pairs));
1443 ASSERT_EQ(1U, pairs.size());
1444 ASSERT_EQ(0, strncmp("value2", pairs["key2"].c_str(), 6));
1447 char key[10], val[20];
1448 for (int i = 0; i < 1024; i++) {
1449 sprintf(key, "key%d", i);
1450 sprintf(val, "value%d", i);
1451 pairs[key].append(val, strlen(val));
1453 ASSERT_EQ(0, metadata_set(&ioctx, oid, pairs));
1455 string last_read = "";
1456 uint64_t max_read = 48, r;
1458 map<string, bufferlist> data;
1460 map<string, bufferlist> cur;
1461 metadata_list(&ioctx, oid, last_read, max_read, &cur);
1463 for (map<string, bufferlist>::iterator it = cur.begin();
1464 it != cur.end(); ++it)
1465 data[it->first] = it->second;
1466 last_read = cur.rbegin()->first;
1468 } while (r == max_read);
1469 ASSERT_EQ(size, 1024U);
1470 for (map<string, bufferlist>::iterator it = data.begin();
1471 it != data.end(); ++it) {
1472 ASSERT_TRUE(it->second.contents_equal(pairs[it->first]));
1478 TEST_F(TestClsRbd, set_features)
1480 librados::IoCtx ioctx;
1481 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1483 string oid = get_temp_image_name();
1484 uint64_t base_features = RBD_FEATURE_LAYERING | RBD_FEATURE_DEEP_FLATTEN;
1485 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, base_features, oid, -1));
1487 uint64_t features = RBD_FEATURES_MUTABLE;
1488 uint64_t mask = RBD_FEATURES_MUTABLE;
1489 ASSERT_EQ(0, set_features(&ioctx, oid, features, mask));
1491 uint64_t actual_features;
1492 ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &actual_features));
1494 uint64_t expected_features = RBD_FEATURES_MUTABLE | base_features;
1495 ASSERT_EQ(expected_features, actual_features);
1498 mask = RBD_FEATURE_OBJECT_MAP;
1499 ASSERT_EQ(0, set_features(&ioctx, oid, features, mask));
1501 ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &actual_features));
1503 expected_features = (RBD_FEATURES_MUTABLE | base_features) &
1504 ~RBD_FEATURE_OBJECT_MAP;
1505 ASSERT_EQ(expected_features, actual_features);
1507 ASSERT_EQ(0, set_features(&ioctx, oid, 0, RBD_FEATURE_DEEP_FLATTEN));
1508 ASSERT_EQ(-EINVAL, set_features(&ioctx, oid, RBD_FEATURE_DEEP_FLATTEN,
1509 RBD_FEATURE_DEEP_FLATTEN));
1511 ASSERT_EQ(-EINVAL, set_features(&ioctx, oid, 0, RBD_FEATURE_LAYERING));
1514 TEST_F(TestClsRbd, mirror) {
1515 librados::IoCtx ioctx;
1516 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1517 ioctx.remove(RBD_MIRRORING);
1519 std::vector<cls::rbd::MirrorPeer> peers;
1520 ASSERT_EQ(-ENOENT, mirror_peer_list(&ioctx, &peers));
1523 ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid));
1524 ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client"));
1526 cls::rbd::MirrorMode mirror_mode;
1527 ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
1528 ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED, mirror_mode);
1530 ASSERT_EQ(-EINVAL, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_IMAGE));
1531 ASSERT_EQ(-EINVAL, mirror_uuid_set(&ioctx, ""));
1532 ASSERT_EQ(0, mirror_uuid_set(&ioctx, "mirror-uuid"));
1533 ASSERT_EQ(0, mirror_uuid_get(&ioctx, &uuid));
1534 ASSERT_EQ("mirror-uuid", uuid);
1536 ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_IMAGE));
1537 ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
1538 ASSERT_EQ(cls::rbd::MIRROR_MODE_IMAGE, mirror_mode);
1540 ASSERT_EQ(-EINVAL, mirror_uuid_set(&ioctx, "new-mirror-uuid"));
1542 ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_POOL));
1543 ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
1544 ASSERT_EQ(cls::rbd::MIRROR_MODE_POOL, mirror_mode);
1546 ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, "mirror-uuid", "cluster1", "client"));
1547 ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client"));
1548 ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid2", "cluster2", "admin"));
1549 ASSERT_EQ(-ESTALE, mirror_peer_add(&ioctx, "uuid2", "cluster3", "foo"));
1550 ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid3", "cluster1", "foo"));
1551 ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid3", "cluster3", "admin", 123));
1552 ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin"));
1553 ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin", 123));
1554 ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin", 234));
1556 ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
1557 std::vector<cls::rbd::MirrorPeer> expected_peers = {
1558 {"uuid1", "cluster1", "client", -1},
1559 {"uuid2", "cluster2", "admin", -1},
1560 {"uuid3", "cluster3", "admin", 123},
1561 {"uuid4", "cluster3", "admin", 234}};
1562 ASSERT_EQ(expected_peers, peers);
1564 ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid5"));
1565 ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid4"));
1566 ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid2"));
1568 ASSERT_EQ(-ENOENT, mirror_peer_set_client(&ioctx, "uuid4", "new client"));
1569 ASSERT_EQ(0, mirror_peer_set_client(&ioctx, "uuid1", "new client"));
1571 ASSERT_EQ(-ENOENT, mirror_peer_set_cluster(&ioctx, "uuid4", "new cluster"));
1572 ASSERT_EQ(0, mirror_peer_set_cluster(&ioctx, "uuid3", "new cluster"));
1574 ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
1576 {"uuid1", "cluster1", "new client", -1},
1577 {"uuid3", "new cluster", "admin", 123}};
1578 ASSERT_EQ(expected_peers, peers);
1579 ASSERT_EQ(-EBUSY, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_DISABLED));
1581 ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid3"));
1582 ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid1"));
1583 ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
1584 expected_peers = {};
1585 ASSERT_EQ(expected_peers, peers);
1587 ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_DISABLED));
1588 ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
1589 ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED, mirror_mode);
1590 ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid));
1593 TEST_F(TestClsRbd, mirror_image) {
1594 librados::IoCtx ioctx;
1595 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1596 ioctx.remove(RBD_MIRRORING);
1598 std::map<std::string, std::string> mirror_image_ids;
1599 ASSERT_EQ(-ENOENT, mirror_image_list(&ioctx, "", 0, &mirror_image_ids));
1601 cls::rbd::MirrorImage image1("uuid1", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1602 cls::rbd::MirrorImage image2("uuid2", cls::rbd::MIRROR_IMAGE_STATE_DISABLING);
1603 cls::rbd::MirrorImage image3("uuid3", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1605 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id1", image1));
1606 ASSERT_EQ(-ENOENT, mirror_image_set(&ioctx, "image_id2", image2));
1607 image2.state = cls::rbd::MIRROR_IMAGE_STATE_ENABLED;
1608 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id2", image2));
1609 image2.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1610 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id2", image2));
1611 ASSERT_EQ(-EINVAL, mirror_image_set(&ioctx, "image_id1", image2));
1612 ASSERT_EQ(-EEXIST, mirror_image_set(&ioctx, "image_id3", image2));
1613 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id3", image3));
1615 std::string image_id;
1616 ASSERT_EQ(0, mirror_image_get_image_id(&ioctx, "uuid2", &image_id));
1617 ASSERT_EQ("image_id2", image_id);
1619 cls::rbd::MirrorImage read_image;
1620 ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id1", &read_image));
1621 ASSERT_EQ(read_image, image1);
1622 ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id2", &read_image));
1623 ASSERT_EQ(read_image, image2);
1624 ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id3", &read_image));
1625 ASSERT_EQ(read_image, image3);
1627 ASSERT_EQ(0, mirror_image_list(&ioctx, "", 1, &mirror_image_ids));
1628 std::map<std::string, std::string> expected_mirror_image_ids = {
1629 {"image_id1", "uuid1"}};
1630 ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
1632 ASSERT_EQ(0, mirror_image_list(&ioctx, "image_id1", 2, &mirror_image_ids));
1633 expected_mirror_image_ids = {{"image_id2", "uuid2"}, {"image_id3", "uuid3"}};
1634 ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
1636 ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id2"));
1637 ASSERT_EQ(-ENOENT, mirror_image_get_image_id(&ioctx, "uuid2", &image_id));
1638 ASSERT_EQ(-EBUSY, mirror_image_remove(&ioctx, "image_id1"));
1640 ASSERT_EQ(0, mirror_image_list(&ioctx, "", 3, &mirror_image_ids));
1641 expected_mirror_image_ids = {{"image_id1", "uuid1"}, {"image_id3", "uuid3"}};
1642 ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
1644 image1.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1645 image3.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1646 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id1", image1));
1647 ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id1", &read_image));
1648 ASSERT_EQ(read_image, image1);
1649 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id3", image3));
1650 ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id1"));
1651 ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id3"));
1653 ASSERT_EQ(0, mirror_image_list(&ioctx, "", 3, &mirror_image_ids));
1654 expected_mirror_image_ids = {};
1655 ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
1658 TEST_F(TestClsRbd, mirror_image_status) {
1659 struct WatchCtx : public librados::WatchCtx2 {
1660 librados::IoCtx *m_ioctx;
1662 WatchCtx(librados::IoCtx *ioctx) : m_ioctx(ioctx) {}
1663 void handle_notify(uint64_t notify_id, uint64_t cookie,
1664 uint64_t notifier_id, bufferlist& bl_) override {
1666 m_ioctx->notify_ack(RBD_MIRRORING, notify_id, cookie, bl);
1668 void handle_error(uint64_t cookie, int err) override {}
1671 map<std::string, cls::rbd::MirrorImage> images;
1672 map<std::string, cls::rbd::MirrorImageStatus> statuses;
1673 std::map<cls::rbd::MirrorImageStatusState, int> states;
1674 cls::rbd::MirrorImageStatus read_status;
1675 uint64_t watch_handle;
1676 librados::IoCtx ioctx;
1678 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1679 ioctx.remove(RBD_MIRRORING);
1681 // Test list fails on nonexistent RBD_MIRRORING object
1683 ASSERT_EQ(-ENOENT, mirror_image_status_list(&ioctx, "", 1024, &images,
1688 cls::rbd::MirrorImage image1("uuid1", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1689 cls::rbd::MirrorImage image2("uuid2", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1690 cls::rbd::MirrorImage image3("uuid3", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1692 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id1", image1));
1693 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id2", image2));
1694 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id3", image3));
1696 cls::rbd::MirrorImageStatus status1(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN);
1697 cls::rbd::MirrorImageStatus status2(cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING);
1698 cls::rbd::MirrorImageStatus status3(cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR);
1700 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1703 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1704 ASSERT_EQ(3U, images.size());
1705 ASSERT_EQ(1U, statuses.size());
1707 // Test status is down due to RBD_MIRRORING is not watched
1710 ASSERT_EQ(statuses["image_id1"], status1);
1711 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1712 ASSERT_EQ(read_status, status1);
1714 // Test status summary. All statuses are unknown due to down.
1716 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1717 ASSERT_EQ(1U, states.size());
1718 ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1720 // Test remove_down removes stale statuses
1722 ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx));
1723 ASSERT_EQ(-ENOENT, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1724 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1725 ASSERT_EQ(3U, images.size());
1726 ASSERT_TRUE(statuses.empty());
1727 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1728 ASSERT_EQ(1U, states.size());
1729 ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1731 // Test statuses are not down after watcher is started
1733 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1735 WatchCtx watch_ctx(&ioctx);
1736 ASSERT_EQ(0, ioctx.watch2(RBD_MIRRORING, &watch_handle, &watch_ctx));
1738 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid2", status2));
1739 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid3", status3));
1741 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1743 ASSERT_EQ(read_status, status1);
1744 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid2", &read_status));
1746 ASSERT_EQ(read_status, status2);
1747 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid3", &read_status));
1749 ASSERT_EQ(read_status, status3);
1753 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1754 ASSERT_EQ(3U, images.size());
1755 ASSERT_EQ(3U, statuses.size());
1756 ASSERT_EQ(statuses["image_id1"], status1);
1757 ASSERT_EQ(statuses["image_id2"], status2);
1758 ASSERT_EQ(statuses["image_id3"], status3);
1760 ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx));
1761 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1762 ASSERT_EQ(read_status, status1);
1765 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1766 ASSERT_EQ(3U, images.size());
1767 ASSERT_EQ(3U, statuses.size());
1768 ASSERT_EQ(statuses["image_id1"], status1);
1769 ASSERT_EQ(statuses["image_id2"], status2);
1770 ASSERT_EQ(statuses["image_id3"], status3);
1773 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1774 ASSERT_EQ(3U, states.size());
1775 ASSERT_EQ(1, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1776 ASSERT_EQ(1, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING]);
1777 ASSERT_EQ(1, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR]);
1781 status1.state = status3.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING;
1782 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1783 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid3", status3));
1784 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid3", &read_status));
1785 ASSERT_EQ(read_status, status3);
1788 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1789 ASSERT_EQ(1U, states.size());
1790 ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING]);
1794 ASSERT_EQ(0, mirror_image_status_remove(&ioctx, "uuid3"));
1795 ASSERT_EQ(-ENOENT, mirror_image_status_get(&ioctx, "uuid3", &read_status));
1798 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1799 ASSERT_EQ(3U, images.size());
1800 ASSERT_EQ(2U, statuses.size());
1801 ASSERT_EQ(statuses["image_id1"], status1);
1802 ASSERT_EQ(statuses["image_id2"], status2);
1805 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1806 ASSERT_EQ(2U, states.size());
1807 ASSERT_EQ(1, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1808 ASSERT_EQ(2, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING]);
1810 // Test statuses are down after removing watcher
1812 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1813 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid2", status2));
1814 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid3", status3));
1818 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1819 ASSERT_EQ(3U, images.size());
1820 ASSERT_EQ(3U, statuses.size());
1821 ASSERT_EQ(statuses["image_id1"], status1);
1822 ASSERT_EQ(statuses["image_id2"], status2);
1823 ASSERT_EQ(statuses["image_id3"], status3);
1825 ioctx.unwatch2(watch_handle);
1827 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1828 ASSERT_EQ(3U, images.size());
1829 ASSERT_EQ(3U, statuses.size());
1831 ASSERT_EQ(statuses["image_id1"], status1);
1833 ASSERT_EQ(statuses["image_id2"], status2);
1835 ASSERT_EQ(statuses["image_id3"], status3);
1837 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1838 ASSERT_EQ(read_status, status1);
1841 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1842 ASSERT_EQ(1U, states.size());
1843 ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1845 ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx));
1846 ASSERT_EQ(-ENOENT, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1850 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1851 ASSERT_EQ(3U, images.size());
1852 ASSERT_TRUE(statuses.empty());
1855 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1856 ASSERT_EQ(1U, states.size());
1857 ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1861 image1.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1862 image2.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1863 image3.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1865 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id1", image1));
1866 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id2", image2));
1867 ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id3", image3));
1869 ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id1"));
1870 ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id2"));
1871 ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id3"));
1874 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1875 ASSERT_EQ(0U, states.size());
1877 // Test status list with large number of images
1880 ASSERT_EQ(0U, N % 2);
1882 for (size_t i = 0; i < N; i++) {
1883 std::string id = "id" + stringify(i);
1884 std::string uuid = "uuid" + stringify(i);
1885 cls::rbd::MirrorImage image(uuid, cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1886 cls::rbd::MirrorImageStatus status(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN);
1887 ASSERT_EQ(0, mirror_image_set(&ioctx, id, image));
1888 ASSERT_EQ(0, mirror_image_status_set(&ioctx, uuid, status));
1891 std::string last_read = "";
1894 ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N * 2, &images,
1896 ASSERT_EQ(N, images.size());
1897 ASSERT_EQ(N, statuses.size());
1901 ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1903 ASSERT_EQ(N / 2, images.size());
1904 ASSERT_EQ(N / 2, statuses.size());
1906 last_read = images.rbegin()->first;
1909 ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1911 ASSERT_EQ(N / 2, images.size());
1912 ASSERT_EQ(N / 2, statuses.size());
1914 last_read = images.rbegin()->first;
1917 ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1919 ASSERT_EQ(0U, images.size());
1920 ASSERT_EQ(0U, statuses.size());
1923 TEST_F(TestClsRbd, mirror_instances) {
1924 librados::IoCtx ioctx;
1925 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1926 ioctx.remove(RBD_MIRROR_LEADER);
1928 std::vector<std::string> instance_ids;
1929 ASSERT_EQ(-ENOENT, mirror_instances_list(&ioctx, &instance_ids));
1931 ASSERT_EQ(0, ioctx.create(RBD_MIRROR_LEADER, true));
1932 ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1933 ASSERT_EQ(0U, instance_ids.size());
1935 ASSERT_EQ(0, mirror_instances_add(&ioctx, "instance_id1"));
1936 ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1937 ASSERT_EQ(1U, instance_ids.size());
1938 ASSERT_EQ(instance_ids[0], "instance_id1");
1940 ASSERT_EQ(0, mirror_instances_add(&ioctx, "instance_id1"));
1941 ASSERT_EQ(0, mirror_instances_add(&ioctx, "instance_id2"));
1942 ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1943 ASSERT_EQ(2U, instance_ids.size());
1945 ASSERT_EQ(0, mirror_instances_remove(&ioctx, "instance_id1"));
1946 ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1947 ASSERT_EQ(1U, instance_ids.size());
1948 ASSERT_EQ(instance_ids[0], "instance_id2");
1950 ASSERT_EQ(0, mirror_instances_remove(&ioctx, "instance_id2"));
1951 ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1952 ASSERT_EQ(0U, instance_ids.size());
1955 TEST_F(TestClsRbd, group_create) {
1956 librados::IoCtx ioctx;
1957 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1959 string group_id = "group_id";
1960 ASSERT_EQ(0, group_create(&ioctx, group_id));
1964 ASSERT_EQ(0, ioctx.stat(group_id, &psize, &pmtime));
1967 TEST_F(TestClsRbd, group_dir_list) {
1968 librados::IoCtx ioctx;
1969 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1971 string group_id1 = "cgid1";
1972 string group_name1 = "cgname1";
1973 string group_id2 = "cgid2";
1974 string group_name2 = "cgname2";
1975 ASSERT_EQ(0, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name1, group_id1));
1976 ASSERT_EQ(0, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name2, group_id2));
1978 map<string, string> cgs;
1979 ASSERT_EQ(0, group_dir_list(&ioctx, RBD_GROUP_DIRECTORY, "", 10, &cgs));
1981 ASSERT_EQ(2U, cgs.size());
1983 auto it = cgs.begin();
1984 ASSERT_EQ(group_id1, it->second);
1985 ASSERT_EQ(group_name1, it->first);
1988 ASSERT_EQ(group_id2, it->second);
1989 ASSERT_EQ(group_name2, it->first);
1992 void add_group_to_dir(librados::IoCtx ioctx, string group_id, string group_name) {
1993 ASSERT_EQ(0, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
1996 ASSERT_EQ(0, ioctx.omap_get_keys(RBD_GROUP_DIRECTORY, "", 10, &keys));
1997 ASSERT_EQ(2U, keys.size());
1998 ASSERT_EQ("id_" + group_id, *keys.begin());
1999 ASSERT_EQ("name_" + group_name, *keys.rbegin());
2002 TEST_F(TestClsRbd, group_dir_add) {
2003 librados::IoCtx ioctx;
2004 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2005 ioctx.remove(RBD_GROUP_DIRECTORY);
2007 string group_id = "cgid";
2008 string group_name = "cgname";
2009 add_group_to_dir(ioctx, group_id, group_name);
2012 TEST_F(TestClsRbd, dir_add_already_existing) {
2013 librados::IoCtx ioctx;
2014 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2015 ioctx.remove(RBD_GROUP_DIRECTORY);
2017 string group_id = "cgidexisting";
2018 string group_name = "cgnameexisting";
2019 add_group_to_dir(ioctx, group_id, group_name);
2021 ASSERT_EQ(-EEXIST, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2024 TEST_F(TestClsRbd, group_dir_remove) {
2025 librados::IoCtx ioctx;
2026 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2027 ioctx.remove(RBD_GROUP_DIRECTORY);
2029 string group_id = "cgidtodel";
2030 string group_name = "cgnametodel";
2031 add_group_to_dir(ioctx, group_id, group_name);
2033 ASSERT_EQ(0, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2036 ASSERT_EQ(0, ioctx.omap_get_keys(RBD_GROUP_DIRECTORY, "", 10, &keys));
2037 ASSERT_EQ(0U, keys.size());
2040 TEST_F(TestClsRbd, group_dir_remove_missing) {
2041 librados::IoCtx ioctx;
2042 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2043 ioctx.remove(RBD_GROUP_DIRECTORY);
2045 string group_id = "cgidtodelmissing";
2046 string group_name = "cgnametodelmissing";
2047 // These two lines ensure that RBD_GROUP_DIRECTORY exists. It's important for the
2049 add_group_to_dir(ioctx, group_id, group_name);
2051 ASSERT_EQ(0, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2054 ASSERT_EQ(-ENOENT, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2057 ASSERT_EQ(0, ioctx.omap_get_keys(RBD_GROUP_DIRECTORY, "", 10, &keys));
2058 ASSERT_EQ(0U, keys.size());
2061 void test_image_add(librados::IoCtx &ioctx, const string& group_id,
2062 const string& image_id, int64_t pool_id) {
2064 cls::rbd::GroupImageStatus st(image_id, pool_id,
2065 cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE);
2066 ASSERT_EQ(0, group_image_set(&ioctx, group_id, st));
2069 ASSERT_EQ(0, ioctx.omap_get_keys(group_id, "", 10, &keys));
2071 auto it = keys.begin();
2072 ASSERT_EQ(2U, keys.size());
2074 string image_key = cls::rbd::GroupImageSpec(image_id, pool_id).image_key();
2075 ASSERT_EQ(image_key, *it);
2077 ASSERT_EQ("snap_seq", *it);
2080 TEST_F(TestClsRbd, group_image_add) {
2081 librados::IoCtx ioctx;
2082 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2084 string group_id = "group_id";
2085 ASSERT_EQ(0, group_create(&ioctx, group_id));
2087 int64_t pool_id = ioctx.get_id();
2088 string image_id = "image_id";
2089 test_image_add(ioctx, group_id, image_id, pool_id);
2092 TEST_F(TestClsRbd, group_image_remove) {
2093 librados::IoCtx ioctx;
2094 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2096 string group_id = "group_id";
2097 ASSERT_EQ(0, group_create(&ioctx, group_id));
2099 int64_t pool_id = ioctx.get_id();
2100 string image_id = "image_id";
2101 test_image_add(ioctx, group_id, image_id, pool_id);
2103 cls::rbd::GroupImageSpec spec(image_id, pool_id);
2104 ASSERT_EQ(0, group_image_remove(&ioctx, group_id, spec));
2106 ASSERT_EQ(0, ioctx.omap_get_keys(group_id, "", 10, &keys));
2107 ASSERT_EQ(1U, keys.size());
2108 ASSERT_EQ("snap_seq", *(keys.begin()));
2111 TEST_F(TestClsRbd, group_image_list) {
2112 librados::IoCtx ioctx;
2113 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2115 string group_id = "group_id";
2116 ASSERT_EQ(0, group_create(&ioctx, group_id));
2118 int64_t pool_id = ioctx.get_id();
2119 string image_id = "imageid"; // Image id shouldn't contain underscores
2120 test_image_add(ioctx, group_id, image_id, pool_id);
2122 vector<cls::rbd::GroupImageStatus> images;
2123 cls::rbd::GroupImageSpec empty_image_spec = cls::rbd::GroupImageSpec();
2124 ASSERT_EQ(0, group_image_list(&ioctx, group_id, empty_image_spec, 1024,
2126 ASSERT_EQ(1U, images.size());
2127 ASSERT_EQ(image_id, images[0].spec.image_id);
2128 ASSERT_EQ(pool_id, images[0].spec.pool_id);
2129 ASSERT_EQ(cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE, images[0].state);
2131 cls::rbd::GroupImageStatus last_image = *images.rbegin();
2132 ASSERT_EQ(0, group_image_list(&ioctx, group_id, last_image.spec, 1024,
2134 ASSERT_EQ(0U, images.size());
2137 TEST_F(TestClsRbd, group_image_clean) {
2138 librados::IoCtx ioctx;
2139 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2141 string group_id = "group_id1";
2142 ASSERT_EQ(0, group_create(&ioctx, group_id));
2144 int64_t pool_id = ioctx.get_id();
2145 string image_id = "image_id";
2146 test_image_add(ioctx, group_id, image_id, pool_id);
2148 cls::rbd::GroupImageStatus incomplete_st(image_id, pool_id,
2149 cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE);
2151 ASSERT_EQ(0, group_image_set(&ioctx, group_id, incomplete_st));
2152 // Set to dirty first in order to make sure that group_image_clean
2153 // actually does something.
2154 cls::rbd::GroupImageStatus attached_st(image_id, pool_id,
2155 cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED);
2156 ASSERT_EQ(0, group_image_set(&ioctx, group_id, attached_st));
2158 string image_key = cls::rbd::GroupImageSpec(image_id, pool_id).image_key();
2160 map<string, bufferlist> vals;
2161 ASSERT_EQ(0, ioctx.omap_get_vals(group_id, "", 10, &vals));
2163 cls::rbd::GroupImageLinkState ref_state;
2164 bufferlist::iterator it = vals[image_key].begin();
2165 ::decode(ref_state, it);
2166 ASSERT_EQ(cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED, ref_state);
2169 TEST_F(TestClsRbd, image_add_group) {
2170 librados::IoCtx ioctx;
2171 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2173 int64_t pool_id = ioctx.get_id();
2174 string image_id = "imageid";
2176 ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2177 RBD_FEATURE_LAYERING, image_id, -1));
2179 string group_id = "group_id";
2181 cls::rbd::GroupSpec spec(group_id, pool_id);
2182 ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec));
2184 map<string, bufferlist> vals;
2185 ASSERT_EQ(0, ioctx.omap_get_vals(image_id, "", RBD_GROUP_REF, 10, &vals));
2187 cls::rbd::GroupSpec val_spec;
2188 bufferlist::iterator it = vals[RBD_GROUP_REF].begin();
2189 ::decode(val_spec, it);
2191 ASSERT_EQ(group_id, val_spec.group_id);
2192 ASSERT_EQ(pool_id, val_spec.pool_id);
2195 TEST_F(TestClsRbd, image_remove_group) {
2196 librados::IoCtx ioctx;
2197 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2199 int64_t pool_id = ioctx.get_id();
2200 string image_id = "image_id";
2202 ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2203 RBD_FEATURE_LAYERING, image_id, -1));
2205 string group_id = "group_id";
2207 cls::rbd::GroupSpec spec(group_id, pool_id);
2208 ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec));
2209 // Add reference in order to make sure that image_remove_group actually
2211 ASSERT_EQ(0, image_remove_group(&ioctx, image_id, spec));
2213 map<string, bufferlist> vals;
2214 ASSERT_EQ(0, ioctx.omap_get_vals(image_id, "", RBD_GROUP_REF, 10, &vals));
2216 ASSERT_EQ(0U, vals.size());
2219 TEST_F(TestClsRbd, image_get_group) {
2220 librados::IoCtx ioctx;
2221 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2223 int64_t pool_id = ioctx.get_id();
2224 string image_id = "imageidgroupspec";
2226 ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2227 RBD_FEATURE_LAYERING, image_id, -1));
2229 string group_id = "group_id_get_group_spec";
2231 cls::rbd::GroupSpec spec_add(group_id, pool_id);
2232 ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec_add));
2234 cls::rbd::GroupSpec spec;
2235 ASSERT_EQ(0, image_get_group(&ioctx, image_id, &spec));
2237 ASSERT_EQ(group_id, spec.group_id);
2238 ASSERT_EQ(pool_id, spec.pool_id);
2241 TEST_F(TestClsRbd, trash_methods)
2243 librados::IoCtx ioctx;
2244 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2246 string id = "123456789";
2247 string id2 = "123456780";
2249 std::map<string, cls::rbd::TrashImageSpec> entries;
2250 ASSERT_EQ(-ENOENT, trash_list(&ioctx, "", 1024, &entries));
2252 utime_t now1 = ceph_clock_now();
2253 utime_t now1_delay = now1;
2255 cls::rbd::TrashImageSpec trash_spec(cls::rbd::TRASH_IMAGE_SOURCE_USER, "name",
2257 ASSERT_EQ(0, trash_add(&ioctx, id, trash_spec));
2259 utime_t now2 = ceph_clock_now();
2260 utime_t now2_delay = now2;
2262 cls::rbd::TrashImageSpec trash_spec2(cls::rbd::TRASH_IMAGE_SOURCE_MIRRORING,
2263 "name2", now2, now2_delay);
2264 ASSERT_EQ(-EEXIST, trash_add(&ioctx, id, trash_spec2));
2266 ASSERT_EQ(0, trash_remove(&ioctx, id));
2267 ASSERT_EQ(-ENOENT, trash_remove(&ioctx, id));
2269 ASSERT_EQ(0, trash_list(&ioctx, "", 1024, &entries));
2270 ASSERT_TRUE(entries.empty());
2272 ASSERT_EQ(0, trash_add(&ioctx, id, trash_spec2));
2273 ASSERT_EQ(0, trash_add(&ioctx, id2, trash_spec));
2275 ASSERT_EQ(0, trash_list(&ioctx, "", 1, &entries));
2276 ASSERT_TRUE(entries.find(id2) != entries.end());
2277 ASSERT_EQ(cls::rbd::TRASH_IMAGE_SOURCE_USER, entries[id2].source);
2278 ASSERT_EQ(std::string("name"), entries[id2].name);
2279 ASSERT_EQ(now1, entries[id2].deletion_time);
2280 ASSERT_EQ(now1_delay, entries[id2].deferment_end_time);
2282 ASSERT_EQ(0, trash_list(&ioctx, id2, 1, &entries));
2283 ASSERT_TRUE(entries.find(id) != entries.end());
2284 ASSERT_EQ(cls::rbd::TRASH_IMAGE_SOURCE_MIRRORING, entries[id].source);
2285 ASSERT_EQ(std::string("name2"), entries[id].name);
2286 ASSERT_EQ(now2, entries[id].deletion_time);
2287 ASSERT_EQ(now2_delay, entries[id].deferment_end_time);
2289 ASSERT_EQ(0, trash_list(&ioctx, id, 1, &entries));
2290 ASSERT_TRUE(entries.empty());
2292 cls::rbd::TrashImageSpec spec_res1;
2293 ASSERT_EQ(0, trash_get(&ioctx, id, &spec_res1));
2294 cls::rbd::TrashImageSpec spec_res2;
2295 ASSERT_EQ(0, trash_get(&ioctx, id2, &spec_res2));
2297 ASSERT_EQ(spec_res1.name, "name2");
2298 ASSERT_EQ(spec_res1.deletion_time, now2);
2299 ASSERT_EQ(spec_res1.deferment_end_time, now2_delay);
2301 ASSERT_EQ(spec_res2.name, "name");
2302 ASSERT_EQ(spec_res2.deletion_time, now1);
2303 ASSERT_EQ(spec_res2.deferment_end_time, now1_delay);