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(RBD_FEATURES_ALL
, all_features
);
108 TEST_F(TestClsRbd
, copyup
)
110 librados::IoCtx ioctx
;
111 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
113 string oid
= get_temp_image_name();
114 bufferlist inbl
, outbl
;
116 // copyup of 0-len nonexistent object should create new 0-len object
118 ASSERT_EQ(0, copyup(&ioctx
, oid
, inbl
));
120 ASSERT_EQ(0, ioctx
.stat(oid
, &size
, NULL
));
123 // create some random data to write
125 char *b
= random_buf(l
);
128 ASSERT_EQ(l
, inbl
.length());
130 // copyup to nonexistent object should create new object
132 ASSERT_EQ(-ENOENT
, ioctx
.remove(oid
));
133 ASSERT_EQ(0, copyup(&ioctx
, oid
, inbl
));
134 // and its contents should match
135 ASSERT_EQ(l
, (size_t)ioctx
.read(oid
, outbl
, l
, 0));
136 ASSERT_TRUE(outbl
.contents_equal(inbl
));
138 // now send different data, but with a preexisting object
143 ASSERT_EQ(l
, inbl2
.length());
145 // should still succeed
146 ASSERT_EQ(0, copyup(&ioctx
, oid
, inbl
));
147 ASSERT_EQ(l
, (size_t)ioctx
.read(oid
, outbl
, l
, 0));
148 // but contents should not have changed
149 ASSERT_FALSE(outbl
.contents_equal(inbl2
));
150 ASSERT_TRUE(outbl
.contents_equal(inbl
));
152 ASSERT_EQ(0, ioctx
.remove(oid
));
156 TEST_F(TestClsRbd
, get_and_set_id
)
158 librados::IoCtx ioctx
;
159 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
161 string oid
= get_temp_image_name();
163 string valid_id
= "0123abcxyzZYXCBA";
164 string invalid_id
= ".abc";
167 ASSERT_EQ(-ENOENT
, get_id(&ioctx
, oid
, &id
));
168 ASSERT_EQ(-ENOENT
, set_id(&ioctx
, oid
, valid_id
));
170 ASSERT_EQ(0, ioctx
.create(oid
, true));
171 ASSERT_EQ(-EINVAL
, set_id(&ioctx
, oid
, invalid_id
));
172 ASSERT_EQ(-EINVAL
, set_id(&ioctx
, oid
, empty_id
));
173 ASSERT_EQ(-ENOENT
, get_id(&ioctx
, oid
, &id
));
175 ASSERT_EQ(0, set_id(&ioctx
, oid
, valid_id
));
176 ASSERT_EQ(-EEXIST
, set_id(&ioctx
, oid
, valid_id
));
177 ASSERT_EQ(-EEXIST
, set_id(&ioctx
, oid
, valid_id
+ valid_id
));
178 ASSERT_EQ(0, get_id(&ioctx
, oid
, &id
));
179 ASSERT_EQ(id
, valid_id
);
184 TEST_F(TestClsRbd
, add_remove_child
)
186 librados::IoCtx ioctx
;
187 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
189 string oid
= get_temp_image_name();
190 ASSERT_EQ(0, ioctx
.create(oid
, true));
192 string snapname
= "parent_snap";
194 string parent_image
= "parent_id";
196 ParentSpec
pspec(ioctx
.get_id(), parent_image
, snapid
);
198 // nonexistent children cannot be listed or removed
199 ASSERT_EQ(-ENOENT
, get_children(&ioctx
, oid
, pspec
, children
));
200 ASSERT_EQ(-ENOENT
, remove_child(&ioctx
, oid
, pspec
, "child1"));
202 // create the parent and snapshot
203 ASSERT_EQ(0, create_image(&ioctx
, parent_image
, 2<<20, 0,
204 RBD_FEATURE_LAYERING
, parent_image
, -1));
205 ASSERT_EQ(0, snapshot_add(&ioctx
, parent_image
, snapid
, snapname
));
207 // add child to it, verify it showed up
208 ASSERT_EQ(0, add_child(&ioctx
, oid
, pspec
, "child1"));
209 ASSERT_EQ(0, get_children(&ioctx
, oid
, pspec
, children
));
210 ASSERT_TRUE(children
.find("child1") != children
.end());
211 // add another child to it, verify it showed up
212 ASSERT_EQ(0, add_child(&ioctx
, oid
, pspec
, "child2"));
213 ASSERT_EQ(0, get_children(&ioctx
, oid
, pspec
, children
));
214 ASSERT_TRUE(children
.find("child2") != children
.end());
215 // add child2 again, expect -EEXIST
216 ASSERT_EQ(-EEXIST
, add_child(&ioctx
, oid
, pspec
, "child2"));
217 // remove first, verify it's gone
218 ASSERT_EQ(0, remove_child(&ioctx
, oid
, pspec
, "child1"));
219 ASSERT_EQ(0, get_children(&ioctx
, oid
, pspec
, children
));
220 ASSERT_FALSE(children
.find("child1") != children
.end());
221 // remove second, verify list empty
222 ASSERT_EQ(0, remove_child(&ioctx
, oid
, pspec
, "child2"));
223 ASSERT_EQ(-ENOENT
, get_children(&ioctx
, oid
, pspec
, children
));
224 // try to remove again, validate -ENOENT to that as well
225 ASSERT_EQ(-ENOENT
, remove_child(&ioctx
, oid
, pspec
, "child2"));
230 TEST_F(TestClsRbd
, directory_methods
)
232 librados::IoCtx ioctx
;
233 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
235 string oid
= get_temp_image_name();
237 string imgname
= get_temp_image_name();
238 string imgname2
= get_temp_image_name();
239 string imgname3
= get_temp_image_name();
240 string valid_id
= "0123abcxyzZYXCBA";
241 string valid_id2
= "5";
242 string invalid_id
= ".abc";
245 ASSERT_EQ(-ENOENT
, dir_get_id(&ioctx
, oid
, imgname
, &id
));
246 ASSERT_EQ(-ENOENT
, dir_get_name(&ioctx
, oid
, valid_id
, &name
));
247 ASSERT_EQ(-ENOENT
, dir_remove_image(&ioctx
, oid
, imgname
, valid_id
));
249 ASSERT_EQ(-EINVAL
, dir_add_image(&ioctx
, oid
, imgname
, invalid_id
));
250 ASSERT_EQ(-EINVAL
, dir_add_image(&ioctx
, oid
, imgname
, empty
));
251 ASSERT_EQ(-EINVAL
, dir_add_image(&ioctx
, oid
, empty
, valid_id
));
253 map
<string
, string
> images
;
254 ASSERT_EQ(-ENOENT
, dir_list(&ioctx
, oid
, "", 30, &images
));
256 ASSERT_EQ(0, ioctx
.create(oid
, true));
257 ASSERT_EQ(0, dir_list(&ioctx
, oid
, "", 30, &images
));
258 ASSERT_EQ(0u, images
.size());
259 ASSERT_EQ(0, ioctx
.remove(oid
));
261 ASSERT_EQ(0, dir_add_image(&ioctx
, oid
, imgname
, valid_id
));
262 ASSERT_EQ(-EEXIST
, dir_add_image(&ioctx
, oid
, imgname
, valid_id2
));
263 ASSERT_EQ(-EBADF
, dir_add_image(&ioctx
, oid
, imgname2
, valid_id
));
264 ASSERT_EQ(0, dir_list(&ioctx
, oid
, "", 30, &images
));
265 ASSERT_EQ(1u, images
.size());
266 ASSERT_EQ(valid_id
, images
[imgname
]);
267 ASSERT_EQ(0, dir_list(&ioctx
, oid
, "", 0, &images
));
268 ASSERT_EQ(0u, images
.size());
269 ASSERT_EQ(0, dir_get_name(&ioctx
, oid
, valid_id
, &name
));
270 ASSERT_EQ(imgname
, name
);
271 ASSERT_EQ(0, dir_get_id(&ioctx
, oid
, imgname
, &id
));
272 ASSERT_EQ(valid_id
, id
);
274 ASSERT_EQ(0, dir_add_image(&ioctx
, oid
, imgname2
, valid_id2
));
275 ASSERT_EQ(0, dir_list(&ioctx
, oid
, "", 30, &images
));
276 ASSERT_EQ(2u, images
.size());
277 ASSERT_EQ(valid_id
, images
[imgname
]);
278 ASSERT_EQ(valid_id2
, images
[imgname2
]);
279 ASSERT_EQ(0, dir_list(&ioctx
, oid
, imgname
, 0, &images
));
280 ASSERT_EQ(0u, images
.size());
281 ASSERT_EQ(0, dir_list(&ioctx
, oid
, imgname
, 2, &images
));
282 ASSERT_EQ(1u, images
.size());
283 ASSERT_EQ(valid_id2
, images
[imgname2
]);
284 ASSERT_EQ(0, dir_get_name(&ioctx
, oid
, valid_id2
, &name
));
285 ASSERT_EQ(imgname2
, name
);
286 ASSERT_EQ(0, dir_get_id(&ioctx
, oid
, imgname2
, &id
));
287 ASSERT_EQ(valid_id2
, id
);
289 librados::ObjectWriteOperation op1
;
290 dir_rename_image(&op1
, imgname
, imgname2
, valid_id2
);
291 ASSERT_EQ(-ESTALE
, ioctx
.operate(oid
, &op1
));
292 ASSERT_EQ(-ESTALE
, dir_remove_image(&ioctx
, oid
, imgname
, valid_id2
));
293 librados::ObjectWriteOperation op2
;
294 dir_rename_image(&op2
, imgname
, imgname2
, valid_id
);
295 ASSERT_EQ(-EEXIST
, ioctx
.operate(oid
, &op2
));
296 ASSERT_EQ(0, dir_get_id(&ioctx
, oid
, imgname
, &id
));
297 ASSERT_EQ(valid_id
, id
);
298 ASSERT_EQ(0, dir_get_name(&ioctx
, oid
, valid_id2
, &name
));
299 ASSERT_EQ(imgname2
, name
);
301 librados::ObjectWriteOperation op3
;
302 dir_rename_image(&op3
, imgname
, imgname3
, valid_id
);
303 ASSERT_EQ(0, ioctx
.operate(oid
, &op3
));
304 ASSERT_EQ(0, dir_get_id(&ioctx
, oid
, imgname3
, &id
));
305 ASSERT_EQ(valid_id
, id
);
306 ASSERT_EQ(0, dir_get_name(&ioctx
, oid
, valid_id
, &name
));
307 ASSERT_EQ(imgname3
, name
);
308 librados::ObjectWriteOperation op4
;
309 dir_rename_image(&op4
, imgname3
, imgname
, valid_id
);
310 ASSERT_EQ(0, ioctx
.operate(oid
, &op4
));
312 ASSERT_EQ(0, dir_remove_image(&ioctx
, oid
, imgname
, valid_id
));
313 ASSERT_EQ(0, dir_list(&ioctx
, oid
, "", 30, &images
));
314 ASSERT_EQ(1u, images
.size());
315 ASSERT_EQ(valid_id2
, images
[imgname2
]);
316 ASSERT_EQ(0, dir_list(&ioctx
, oid
, imgname2
, 30, &images
));
317 ASSERT_EQ(0u, images
.size());
318 ASSERT_EQ(0, dir_get_name(&ioctx
, oid
, valid_id2
, &name
));
319 ASSERT_EQ(imgname2
, name
);
320 ASSERT_EQ(0, dir_get_id(&ioctx
, oid
, imgname2
, &id
));
321 ASSERT_EQ(valid_id2
, id
);
322 ASSERT_EQ(-ENOENT
, dir_get_name(&ioctx
, oid
, valid_id
, &name
));
323 ASSERT_EQ(-ENOENT
, dir_get_id(&ioctx
, oid
, imgname
, &id
));
325 ASSERT_EQ(0, dir_add_image(&ioctx
, oid
, imgname
, valid_id
));
326 ASSERT_EQ(0, dir_list(&ioctx
, oid
, "", 30, &images
));
327 ASSERT_EQ(2u, images
.size());
328 ASSERT_EQ(valid_id
, images
[imgname
]);
329 ASSERT_EQ(valid_id2
, images
[imgname2
]);
330 ASSERT_EQ(0, dir_remove_image(&ioctx
, oid
, imgname
, valid_id
));
331 ASSERT_EQ(-ENOENT
, dir_remove_image(&ioctx
, oid
, imgname
, valid_id
));
332 ASSERT_EQ(0, dir_remove_image(&ioctx
, oid
, imgname2
, valid_id2
));
333 ASSERT_EQ(0, dir_list(&ioctx
, oid
, "", 30, &images
));
334 ASSERT_EQ(0u, images
.size());
339 TEST_F(TestClsRbd
, create
)
341 librados::IoCtx ioctx
;
342 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
344 string oid
= get_temp_image_name();
345 uint64_t size
= 20ULL << 30;
346 uint64_t features
= 0;
348 string object_prefix
= oid
;
350 ASSERT_EQ(0, create_image(&ioctx
, oid
, size
, order
,
351 features
, object_prefix
, -1));
352 ASSERT_EQ(-EEXIST
, create_image(&ioctx
, oid
, size
, order
,
353 features
, object_prefix
, -1));
354 ASSERT_EQ(0, ioctx
.remove(oid
));
356 ASSERT_EQ(-EINVAL
, create_image(&ioctx
, oid
, size
, order
,
358 ASSERT_EQ(-ENOENT
, ioctx
.remove(oid
));
360 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, order
,
361 features
, object_prefix
, -1));
362 ASSERT_EQ(0, ioctx
.remove(oid
));
364 ASSERT_EQ(-ENOSYS
, create_image(&ioctx
, oid
, size
, order
,
365 -1, object_prefix
, -1));
366 ASSERT_EQ(-ENOENT
, ioctx
.remove(oid
));
368 ASSERT_EQ(0, create_image(&ioctx
, oid
, size
, order
, RBD_FEATURE_DATA_POOL
,
369 object_prefix
, 123));
370 ASSERT_EQ(0, ioctx
.remove(oid
));
371 ASSERT_EQ(-EINVAL
, create_image(&ioctx
, oid
, size
, order
,
372 RBD_FEATURE_DATA_POOL
, object_prefix
, -1));
373 ASSERT_EQ(-EINVAL
, create_image(&ioctx
, oid
, size
, order
, 0, object_prefix
,
376 bufferlist inbl
, outbl
;
377 ASSERT_EQ(-EINVAL
, ioctx
.exec(oid
, "rbd", "create", inbl
, outbl
));
382 TEST_F(TestClsRbd
, get_features
)
384 librados::IoCtx ioctx
;
385 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
387 string oid
= get_temp_image_name();
390 ASSERT_EQ(-ENOENT
, get_features(&ioctx
, oid
, CEPH_NOSNAP
, &features
));
392 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, 0, oid
, -1));
393 ASSERT_EQ(0, get_features(&ioctx
, oid
, CEPH_NOSNAP
, &features
));
394 ASSERT_EQ(0u, features
);
396 int r
= get_features(&ioctx
, oid
, 1, &features
);
398 ASSERT_EQ(0u, features
);
400 // deprecated snapshot handling
401 ASSERT_EQ(-ENOENT
, r
);
407 TEST_F(TestClsRbd
, get_object_prefix
)
409 librados::IoCtx ioctx
;
410 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
412 string oid
= get_temp_image_name();
414 string object_prefix
;
415 ASSERT_EQ(-ENOENT
, get_object_prefix(&ioctx
, oid
, &object_prefix
));
417 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, 0, oid
, -1));
418 ASSERT_EQ(0, get_object_prefix(&ioctx
, oid
, &object_prefix
));
419 ASSERT_EQ(oid
, object_prefix
);
424 TEST_F(TestClsRbd
, get_data_pool
)
426 librados::IoCtx ioctx
;
427 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
429 string oid
= get_temp_image_name();
431 int64_t data_pool_id
;
432 ASSERT_EQ(0, ioctx
.create(oid
, true));
433 ASSERT_EQ(0, get_data_pool(&ioctx
, oid
, &data_pool_id
));
434 ASSERT_EQ(-1, data_pool_id
);
435 ASSERT_EQ(0, ioctx
.remove(oid
));
437 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, RBD_FEATURE_DATA_POOL
, oid
,
439 ASSERT_EQ(0, get_data_pool(&ioctx
, oid
, &data_pool_id
));
440 ASSERT_EQ(12, data_pool_id
);
443 TEST_F(TestClsRbd
, get_size
)
445 librados::IoCtx ioctx
;
446 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
448 string oid
= get_temp_image_name();
451 ASSERT_EQ(-ENOENT
, get_size(&ioctx
, oid
, CEPH_NOSNAP
, &size
, &order
));
453 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, 0, oid
, -1));
454 ASSERT_EQ(0, get_size(&ioctx
, oid
, CEPH_NOSNAP
, &size
, &order
));
456 ASSERT_EQ(22, order
);
457 ASSERT_EQ(0, ioctx
.remove(oid
));
459 ASSERT_EQ(0, create_image(&ioctx
, oid
, 2 << 22, 0, 0, oid
, -1));
460 ASSERT_EQ(0, get_size(&ioctx
, oid
, CEPH_NOSNAP
, &size
, &order
));
461 ASSERT_EQ(2u << 22, size
);
464 ASSERT_EQ(-ENOENT
, get_size(&ioctx
, oid
, 1, &size
, &order
));
469 TEST_F(TestClsRbd
, set_size
)
471 librados::IoCtx ioctx
;
472 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
474 string oid
= get_temp_image_name();
475 ASSERT_EQ(-ENOENT
, set_size(&ioctx
, oid
, 5));
479 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, 0, oid
, -1));
480 ASSERT_EQ(0, get_size(&ioctx
, oid
, CEPH_NOSNAP
, &size
, &order
));
482 ASSERT_EQ(22, order
);
484 ASSERT_EQ(0, set_size(&ioctx
, oid
, 0));
485 ASSERT_EQ(0, get_size(&ioctx
, oid
, CEPH_NOSNAP
, &size
, &order
));
487 ASSERT_EQ(22, order
);
489 ASSERT_EQ(0, set_size(&ioctx
, oid
, 3 << 22));
490 ASSERT_EQ(0, get_size(&ioctx
, oid
, CEPH_NOSNAP
, &size
, &order
));
491 ASSERT_EQ(3u << 22, size
);
492 ASSERT_EQ(22, order
);
497 TEST_F(TestClsRbd
, protection_status
)
499 librados::IoCtx ioctx
;
500 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
502 string oid
= get_temp_image_name();
503 string oid2
= get_temp_image_name();
504 uint8_t status
= RBD_PROTECTION_STATUS_UNPROTECTED
;
505 ASSERT_EQ(-ENOENT
, get_protection_status(&ioctx
, oid
,
506 CEPH_NOSNAP
, &status
));
507 ASSERT_EQ(-ENOENT
, set_protection_status(&ioctx
, oid
,
508 CEPH_NOSNAP
, status
));
510 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, RBD_FEATURE_LAYERING
, oid
, -1));
511 ASSERT_EQ(0, create_image(&ioctx
, oid2
, 0, 22, 0, oid
, -1));
512 ASSERT_EQ(-EINVAL
, get_protection_status(&ioctx
, oid2
,
513 CEPH_NOSNAP
, &status
));
514 ASSERT_EQ(-ENOEXEC
, set_protection_status(&ioctx
, oid2
,
515 CEPH_NOSNAP
, status
));
516 ASSERT_EQ(-EINVAL
, get_protection_status(&ioctx
, oid
,
517 CEPH_NOSNAP
, &status
));
518 ASSERT_EQ(-EINVAL
, set_protection_status(&ioctx
, oid
,
519 CEPH_NOSNAP
, status
));
520 ASSERT_EQ(-ENOENT
, get_protection_status(&ioctx
, oid
,
522 ASSERT_EQ(-ENOENT
, set_protection_status(&ioctx
, oid
,
525 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 10, "snap1"));
526 ASSERT_EQ(0, get_protection_status(&ioctx
, oid
,
528 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED
, status
);
530 ASSERT_EQ(0, set_protection_status(&ioctx
, oid
,
531 10, RBD_PROTECTION_STATUS_PROTECTED
));
532 ASSERT_EQ(0, get_protection_status(&ioctx
, oid
,
534 ASSERT_EQ(+RBD_PROTECTION_STATUS_PROTECTED
, status
);
535 ASSERT_EQ(-EBUSY
, snapshot_remove(&ioctx
, oid
, 10));
537 ASSERT_EQ(0, set_protection_status(&ioctx
, oid
,
538 10, RBD_PROTECTION_STATUS_UNPROTECTING
));
539 ASSERT_EQ(0, get_protection_status(&ioctx
, oid
,
541 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTING
, status
);
542 ASSERT_EQ(-EBUSY
, snapshot_remove(&ioctx
, oid
, 10));
544 ASSERT_EQ(-EINVAL
, set_protection_status(&ioctx
, oid
,
545 10, RBD_PROTECTION_STATUS_LAST
));
546 ASSERT_EQ(0, get_protection_status(&ioctx
, oid
,
548 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTING
, status
);
550 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 20, "snap2"));
551 ASSERT_EQ(0, get_protection_status(&ioctx
, oid
,
553 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED
, status
);
554 ASSERT_EQ(0, set_protection_status(&ioctx
, oid
,
555 10, RBD_PROTECTION_STATUS_UNPROTECTED
));
556 ASSERT_EQ(0, get_protection_status(&ioctx
, oid
,
558 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED
, status
);
560 ASSERT_EQ(0, snapshot_remove(&ioctx
, oid
, 10));
561 ASSERT_EQ(0, snapshot_remove(&ioctx
, oid
, 20));
566 TEST_F(TestClsRbd
, snapshot_limits
)
568 librados::IoCtx ioctx
;
569 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
571 librados::ObjectWriteOperation op
;
572 string oid
= get_temp_image_name();
575 ASSERT_EQ(-ENOENT
, snapshot_get_limit(&ioctx
, oid
, &limit
));
577 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, RBD_FEATURE_LAYERING
, oid
, -1));
579 snapshot_set_limit(&op
, 2);
581 ASSERT_EQ(0, ioctx
.operate(oid
, &op
));
583 ASSERT_EQ(0, snapshot_get_limit(&ioctx
, oid
, &limit
));
584 ASSERT_EQ(2U, limit
);
586 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 10, "snap1"));
587 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 20, "snap2"));
588 ASSERT_EQ(-EDQUOT
, snapshot_add(&ioctx
, oid
, 30, "snap3"));
590 ASSERT_EQ(0, snapshot_remove(&ioctx
, oid
, 10));
591 ASSERT_EQ(0, snapshot_remove(&ioctx
, oid
, 20));
596 TEST_F(TestClsRbd
, parents
)
598 librados::IoCtx ioctx
;
599 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
601 string oid
= get_temp_image_name();
605 ASSERT_EQ(-ENOENT
, get_parent(&ioctx
, "doesnotexist", CEPH_NOSNAP
, &pspec
, &size
));
607 // old image should fail
608 ASSERT_EQ(0, create_image(&ioctx
, "old", 33<<20, 22, 0, "old_blk.", -1));
609 // get nonexistent parent: succeed, return (-1, "", CEPH_NOSNAP), overlap 0
610 ASSERT_EQ(0, get_parent(&ioctx
, "old", CEPH_NOSNAP
, &pspec
, &size
));
611 ASSERT_EQ(pspec
.pool_id
, -1);
612 ASSERT_STREQ("", pspec
.image_id
.c_str());
613 ASSERT_EQ(pspec
.snap_id
, CEPH_NOSNAP
);
614 ASSERT_EQ(size
, 0ULL);
615 pspec
= ParentSpec(-1, "parent", 3);
616 ASSERT_EQ(-ENOEXEC
, set_parent(&ioctx
, "old", ParentSpec(-1, "parent", 3), 10<<20));
617 ASSERT_EQ(-ENOEXEC
, remove_parent(&ioctx
, "old"));
619 // new image will work
620 ASSERT_EQ(0, create_image(&ioctx
, oid
, 33<<20, 22, RBD_FEATURE_LAYERING
,
623 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
624 ASSERT_EQ(-1, pspec
.pool_id
);
625 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 123, &pspec
, &size
));
626 ASSERT_EQ(-1, pspec
.pool_id
);
628 ASSERT_EQ(-EINVAL
, set_parent(&ioctx
, oid
, ParentSpec(-1, "parent", 3), 10<<20));
629 ASSERT_EQ(-EINVAL
, set_parent(&ioctx
, oid
, ParentSpec(1, "", 3), 10<<20));
630 ASSERT_EQ(-EINVAL
, set_parent(&ioctx
, oid
, ParentSpec(1, "parent", CEPH_NOSNAP
), 10<<20));
631 ASSERT_EQ(-EINVAL
, set_parent(&ioctx
, oid
, ParentSpec(1, "parent", 3), 0));
633 pspec
= ParentSpec(1, "parent", 3);
634 ASSERT_EQ(0, set_parent(&ioctx
, oid
, pspec
, 10<<20));
635 ASSERT_EQ(-EEXIST
, set_parent(&ioctx
, oid
, pspec
, 10<<20));
636 ASSERT_EQ(-EEXIST
, set_parent(&ioctx
, oid
, ParentSpec(2, "parent", 34), 10<<20));
638 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
639 ASSERT_EQ(pspec
.pool_id
, 1);
640 ASSERT_EQ(pspec
.image_id
, "parent");
641 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
643 ASSERT_EQ(0, remove_parent(&ioctx
, oid
));
644 ASSERT_EQ(-ENOENT
, remove_parent(&ioctx
, oid
));
645 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
646 ASSERT_EQ(-1, pspec
.pool_id
);
649 ASSERT_EQ(0, set_parent(&ioctx
, oid
, ParentSpec(1, "parent", 3), 10<<20));
650 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 10, "snap1"));
651 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 10, &pspec
, &size
));
652 ASSERT_EQ(pspec
.pool_id
, 1);
653 ASSERT_EQ(pspec
.image_id
, "parent");
654 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
655 ASSERT_EQ(size
, 10ull<<20);
657 ASSERT_EQ(0, remove_parent(&ioctx
, oid
));
658 ASSERT_EQ(0, set_parent(&ioctx
, oid
, ParentSpec(4, "parent2", 6), 5<<20));
659 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 11, "snap2"));
660 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 10, &pspec
, &size
));
661 ASSERT_EQ(pspec
.pool_id
, 1);
662 ASSERT_EQ(pspec
.image_id
, "parent");
663 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
664 ASSERT_EQ(size
, 10ull<<20);
665 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 11, &pspec
, &size
));
666 ASSERT_EQ(pspec
.pool_id
, 4);
667 ASSERT_EQ(pspec
.image_id
, "parent2");
668 ASSERT_EQ(pspec
.snap_id
, snapid_t(6));
669 ASSERT_EQ(size
, 5ull<<20);
671 ASSERT_EQ(0, remove_parent(&ioctx
, oid
));
672 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 12, "snap3"));
673 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 10, &pspec
, &size
));
674 ASSERT_EQ(pspec
.pool_id
, 1);
675 ASSERT_EQ(pspec
.image_id
, "parent");
676 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
677 ASSERT_EQ(size
, 10ull<<20);
678 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 11, &pspec
, &size
));
679 ASSERT_EQ(pspec
.pool_id
, 4);
680 ASSERT_EQ(pspec
.image_id
, "parent2");
681 ASSERT_EQ(pspec
.snap_id
, snapid_t(6));
682 ASSERT_EQ(size
, 5ull<<20);
683 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 12, &pspec
, &size
));
684 ASSERT_EQ(-1, pspec
.pool_id
);
686 // make sure set_parent takes min of our size and parent's size
687 ASSERT_EQ(0, set_parent(&ioctx
, oid
, ParentSpec(1, "parent", 3), 1<<20));
688 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
689 ASSERT_EQ(pspec
.pool_id
, 1);
690 ASSERT_EQ(pspec
.image_id
, "parent");
691 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
692 ASSERT_EQ(size
, 1ull<<20);
693 ASSERT_EQ(0, remove_parent(&ioctx
, oid
));
695 ASSERT_EQ(0, set_parent(&ioctx
, oid
, ParentSpec(1, "parent", 3), 100<<20));
696 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
697 ASSERT_EQ(pspec
.pool_id
, 1);
698 ASSERT_EQ(pspec
.image_id
, "parent");
699 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
700 ASSERT_EQ(size
, 33ull<<20);
701 ASSERT_EQ(0, remove_parent(&ioctx
, oid
));
703 // make sure resize adjust parent overlap
704 ASSERT_EQ(0, set_parent(&ioctx
, oid
, ParentSpec(1, "parent", 3), 10<<20));
706 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 14, "snap4"));
707 ASSERT_EQ(0, set_size(&ioctx
, oid
, 3 << 20));
708 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
709 ASSERT_EQ(pspec
.pool_id
, 1);
710 ASSERT_EQ(pspec
.image_id
, "parent");
711 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
712 ASSERT_EQ(size
, 3ull<<20);
713 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 14, &pspec
, &size
));
714 ASSERT_EQ(pspec
.pool_id
, 1);
715 ASSERT_EQ(pspec
.image_id
, "parent");
716 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
717 ASSERT_EQ(size
, 10ull<<20);
719 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 15, "snap5"));
720 ASSERT_EQ(0, set_size(&ioctx
, oid
, 30 << 20));
721 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
722 ASSERT_EQ(pspec
.pool_id
, 1);
723 ASSERT_EQ(pspec
.image_id
, "parent");
724 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
725 ASSERT_EQ(size
, 3ull<<20);
726 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 14, &pspec
, &size
));
727 ASSERT_EQ(pspec
.pool_id
, 1);
728 ASSERT_EQ(pspec
.image_id
, "parent");
729 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
730 ASSERT_EQ(size
, 10ull<<20);
731 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 15, &pspec
, &size
));
732 ASSERT_EQ(pspec
.pool_id
, 1);
733 ASSERT_EQ(pspec
.image_id
, "parent");
734 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
735 ASSERT_EQ(size
, 3ull<<20);
737 ASSERT_EQ(0, set_size(&ioctx
, oid
, 2 << 20));
738 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
739 ASSERT_EQ(pspec
.pool_id
, 1);
740 ASSERT_EQ(pspec
.image_id
, "parent");
741 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
742 ASSERT_EQ(size
, 2ull<<20);
744 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 16, "snap6"));
745 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 16, &pspec
, &size
));
746 ASSERT_EQ(pspec
.pool_id
, 1);
747 ASSERT_EQ(pspec
.image_id
, "parent");
748 ASSERT_EQ(pspec
.snap_id
, snapid_t(3));
749 ASSERT_EQ(size
, 2ull<<20);
751 ASSERT_EQ(0, ioctx
.remove(oid
));
752 ASSERT_EQ(0, create_image(&ioctx
, oid
, 33<<20, 22,
753 RBD_FEATURE_LAYERING
| RBD_FEATURE_DEEP_FLATTEN
,
755 ASSERT_EQ(0, set_parent(&ioctx
, oid
, ParentSpec(1, "parent", 3), 100<<20));
756 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 1, "snap1"));
757 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 2, "snap2"));
758 ASSERT_EQ(0, remove_parent(&ioctx
, oid
));
760 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 1, &pspec
, &size
));
761 ASSERT_EQ(-1, pspec
.pool_id
);
762 ASSERT_EQ(0, get_parent(&ioctx
, oid
, 2, &pspec
, &size
));
763 ASSERT_EQ(-1, pspec
.pool_id
);
764 ASSERT_EQ(0, get_parent(&ioctx
, oid
, CEPH_NOSNAP
, &pspec
, &size
));
765 ASSERT_EQ(-1, pspec
.pool_id
);
770 TEST_F(TestClsRbd
, snapshots
)
772 cls::rbd::SnapshotNamespace userSnapNamespace
= cls::rbd::UserSnapshotNamespace();
773 librados::IoCtx ioctx
;
774 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
776 string oid
= get_temp_image_name();
777 ASSERT_EQ(-ENOENT
, snapshot_add(&ioctx
, oid
, 0, "snap1"));
779 ASSERT_EQ(0, create_image(&ioctx
, oid
, 10, 22, 0, oid
, -1));
781 vector
<string
> snap_names
;
782 vector
<cls::rbd::SnapshotNamespace
> snap_namespaces
;
783 vector
<uint64_t> snap_sizes
;
785 vector
<ParentInfo
> parents
;
786 vector
<uint8_t> protection_status
;
787 vector
<utime_t
> snap_timestamps
;
789 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
790 ASSERT_EQ(0u, snapc
.snaps
.size());
791 ASSERT_EQ(0u, snapc
.seq
);
792 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
793 &snap_sizes
, &parents
, &protection_status
));
794 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
795 ASSERT_EQ(0u, snap_names
.size());
796 ASSERT_EQ(0u, snap_namespaces
.size());
797 ASSERT_EQ(0u, snap_sizes
.size());
798 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
799 ASSERT_EQ(0u, snap_timestamps
.size());
801 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 0, "snap1"));
802 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
803 ASSERT_EQ(1u, snapc
.snaps
.size());
804 ASSERT_EQ(0u, snapc
.snaps
[0]);
805 ASSERT_EQ(0u, snapc
.seq
);
806 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
807 &snap_sizes
, &parents
, &protection_status
));
808 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
809 ASSERT_EQ(1u, snap_names
.size());
810 ASSERT_EQ("snap1", snap_names
[0]);
811 ASSERT_EQ(1u, snap_namespaces
.size());
812 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
813 ASSERT_EQ(10u, snap_sizes
[0]);
814 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
815 ASSERT_EQ(1u, snap_timestamps
.size());
817 // snap with same id and name
818 ASSERT_EQ(-EEXIST
, snapshot_add(&ioctx
, oid
, 0, "snap1"));
819 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
820 ASSERT_EQ(1u, snapc
.snaps
.size());
821 ASSERT_EQ(0u, snapc
.snaps
[0]);
822 ASSERT_EQ(0u, snapc
.seq
);
823 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
824 &snap_sizes
, &parents
, &protection_status
));
825 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
826 ASSERT_EQ(1u, snap_names
.size());
827 ASSERT_EQ("snap1", snap_names
[0]);
828 ASSERT_EQ(1u, snap_namespaces
.size());
829 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
830 ASSERT_EQ(10u, snap_sizes
[0]);
831 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
832 ASSERT_EQ(1u, snap_timestamps
.size());
835 // snap with same id, different name
836 ASSERT_EQ(-EEXIST
, snapshot_add(&ioctx
, oid
, 0, "snap2"));
837 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
838 ASSERT_EQ(1u, snapc
.snaps
.size());
839 ASSERT_EQ(0u, snapc
.snaps
[0]);
840 ASSERT_EQ(0u, snapc
.seq
);
841 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
842 &snap_sizes
, &parents
, &protection_status
));
843 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
844 ASSERT_EQ(1u, snap_names
.size());
845 ASSERT_EQ("snap1", snap_names
[0]);
846 ASSERT_EQ(1u, snap_namespaces
.size());
847 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
848 ASSERT_EQ(10u, snap_sizes
[0]);
849 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
850 ASSERT_EQ(1u, snap_timestamps
.size());
852 // snap with different id, same name
853 ASSERT_EQ(-EEXIST
, snapshot_add(&ioctx
, oid
, 1, "snap1"));
854 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
855 ASSERT_EQ(1u, snapc
.snaps
.size());
856 ASSERT_EQ(0u, snapc
.snaps
[0]);
857 ASSERT_EQ(0u, snapc
.seq
);
858 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
859 &snap_sizes
, &parents
, &protection_status
));
860 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
861 ASSERT_EQ(snap_names
.size(), 1u);
862 ASSERT_EQ(snap_names
[0], "snap1");
863 ASSERT_EQ(1u, snap_namespaces
.size());
864 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
865 ASSERT_EQ(snap_sizes
[0], 10u);
866 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
867 ASSERT_EQ(1u, snap_timestamps
.size());
869 // snap with different id, different name
870 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 1, "snap2"));
871 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
872 ASSERT_EQ(2u, snapc
.snaps
.size());
873 ASSERT_EQ(1u, snapc
.snaps
[0]);
874 ASSERT_EQ(0u, snapc
.snaps
[1]);
875 ASSERT_EQ(1u, snapc
.seq
);
876 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
877 &snap_sizes
, &parents
, &protection_status
));
878 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
879 ASSERT_EQ(2u, snap_names
.size());
880 ASSERT_EQ(2u, snap_namespaces
.size());
881 ASSERT_EQ("snap2", snap_names
[0]);
882 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
883 ASSERT_EQ(10u, snap_sizes
[0]);
884 ASSERT_EQ("snap1", snap_names
[1]);
885 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[1]);
886 ASSERT_EQ(10u, snap_sizes
[1]);
887 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
888 ASSERT_EQ(2u, snap_timestamps
.size());
890 ASSERT_EQ(0, snapshot_rename(&ioctx
, oid
, 0, "snap1-rename"));
891 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
892 &snap_sizes
, &parents
, &protection_status
));
893 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
894 ASSERT_EQ(2u, snap_names
.size());
895 ASSERT_EQ(2u, snap_namespaces
.size());
896 ASSERT_EQ("snap2", snap_names
[0]);
897 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
898 ASSERT_EQ(10u, snap_sizes
[0]);
899 ASSERT_EQ("snap1-rename", snap_names
[1]);
900 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[1]);
901 ASSERT_EQ(10u, snap_sizes
[1]);
902 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
903 ASSERT_EQ(2u, snap_timestamps
.size());
905 ASSERT_EQ(0, snapshot_remove(&ioctx
, oid
, 0));
906 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
907 ASSERT_EQ(1u, snapc
.snaps
.size());
908 ASSERT_EQ(1u, snapc
.snaps
[0]);
909 ASSERT_EQ(1u, snapc
.seq
);
910 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
911 &snap_sizes
, &parents
, &protection_status
));
912 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
913 ASSERT_EQ(1u, snap_names
.size());
914 ASSERT_EQ(1u, snap_namespaces
.size());
915 ASSERT_EQ("snap2", snap_names
[0]);
916 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
917 ASSERT_EQ(10u, snap_sizes
[0]);
918 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
919 ASSERT_EQ(1u, snap_timestamps
.size());
923 ASSERT_EQ(0, set_size(&ioctx
, oid
, 0));
924 ASSERT_EQ(0, get_size(&ioctx
, oid
, CEPH_NOSNAP
, &size
, &order
));
926 ASSERT_EQ(22u, order
);
928 uint64_t large_snap_id
= 1ull << 63;
929 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, large_snap_id
, "snap3"));
930 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
931 ASSERT_EQ(2u, snapc
.snaps
.size());
932 ASSERT_EQ(large_snap_id
, snapc
.snaps
[0]);
933 ASSERT_EQ(1u, snapc
.snaps
[1]);
934 ASSERT_EQ(large_snap_id
, snapc
.seq
);
935 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
936 &snap_sizes
, &parents
, &protection_status
));
937 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
938 ASSERT_EQ(2u, snap_names
.size());
939 ASSERT_EQ(2u, snap_namespaces
.size());
940 ASSERT_EQ("snap3", snap_names
[0]);
941 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
942 ASSERT_EQ(0u, snap_sizes
[0]);
943 ASSERT_EQ("snap2", snap_names
[1]);
944 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[1]);
945 ASSERT_EQ(10u, snap_sizes
[1]);
946 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
947 ASSERT_EQ(2u, snap_timestamps
.size());
949 ASSERT_EQ(0, get_size(&ioctx
, oid
, large_snap_id
, &size
, &order
));
951 ASSERT_EQ(22u, order
);
953 ASSERT_EQ(0, get_size(&ioctx
, oid
, 1, &size
, &order
));
954 ASSERT_EQ(10u, size
);
955 ASSERT_EQ(22u, order
);
957 ASSERT_EQ(0, snapshot_remove(&ioctx
, oid
, large_snap_id
));
958 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
959 ASSERT_EQ(1u, snapc
.snaps
.size());
960 ASSERT_EQ(1u, snapc
.snaps
[0]);
961 ASSERT_EQ(large_snap_id
, snapc
.seq
);
962 ASSERT_EQ(0, snapshot_list(&ioctx
, oid
, snapc
.snaps
, &snap_names
,
963 &snap_sizes
, &parents
, &protection_status
));
964 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
965 ASSERT_EQ(1u, snap_names
.size());
966 ASSERT_EQ(1u, snap_namespaces
.size());
967 ASSERT_EQ("snap2", snap_names
[0]);
968 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[0]);
969 ASSERT_EQ(10u, snap_sizes
[0]);
970 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
971 ASSERT_EQ(1u, snap_timestamps
.size());
973 ASSERT_EQ(-ENOENT
, snapshot_remove(&ioctx
, oid
, large_snap_id
));
974 ASSERT_EQ(0, snapshot_remove(&ioctx
, oid
, 1));
975 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
976 ASSERT_EQ(0u, snapc
.snaps
.size());
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(0u, snap_names
.size());
982 ASSERT_EQ(0u, snap_namespaces
.size());
983 ASSERT_EQ(0u, snap_sizes
.size());
984 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
985 ASSERT_EQ(0u, snap_timestamps
.size());
990 TEST_F(TestClsRbd
, snapshots_namespaces
)
992 cls::rbd::SnapshotNamespace groupSnapNamespace
= cls::rbd::GroupSnapshotNamespace(5, "1018643c9869", 3);
993 cls::rbd::SnapshotNamespace userSnapNamespace
= cls::rbd::UserSnapshotNamespace();
994 librados::IoCtx ioctx
;
995 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
997 string oid
= get_temp_image_name();
999 ASSERT_EQ(0, create_image(&ioctx
, oid
, 10, 22, 0, oid
, -1));
1001 vector
<string
> snap_names
;
1002 vector
<cls::rbd::SnapshotNamespace
> snap_namespaces
;
1005 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
1006 ASSERT_EQ(0u, snapc
.snaps
.size());
1007 ASSERT_EQ(0u, snapc
.seq
);
1008 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
1009 ASSERT_EQ(0u, snap_namespaces
.size());
1011 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 0, "snap1"));
1013 librados::ObjectWriteOperation op
;
1014 ::librbd::cls_client::snapshot_add(&op
, 1, "snap1", groupSnapNamespace
);
1015 int r
= ioctx
.operate(oid
, &op
);
1018 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
1019 ASSERT_EQ(2u, snapc
.snaps
.size());
1020 ASSERT_EQ(1u, snapc
.snaps
[0]);
1021 ASSERT_EQ(0u, snapc
.snaps
[1]);
1022 ASSERT_EQ(1u, snapc
.seq
);
1023 ASSERT_EQ(0, snapshot_namespace_list(&ioctx
, oid
, snapc
.snaps
, &snap_namespaces
));
1024 ASSERT_EQ(groupSnapNamespace
, snap_namespaces
[0]);
1025 ASSERT_EQ(userSnapNamespace
, snap_namespaces
[1]);
1030 TEST_F(TestClsRbd
, snapshots_timestamps
)
1032 librados::IoCtx ioctx
;
1033 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1035 string oid
= get_temp_image_name();
1037 ASSERT_EQ(0, create_image(&ioctx
, oid
, 10, 22, 0, oid
, -1));
1039 vector
<string
> snap_names
;
1040 vector
<utime_t
> snap_timestamps
;
1043 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
1044 ASSERT_EQ(0u, snapc
.snaps
.size());
1045 ASSERT_EQ(0u, snapc
.seq
);
1046 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
1047 ASSERT_EQ(0u, snap_timestamps
.size());
1049 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, 0, "snap1"));
1051 ASSERT_EQ(0, get_snapcontext(&ioctx
, oid
, &snapc
));
1052 ASSERT_EQ(1u, snapc
.snaps
.size());
1053 ASSERT_EQ(0, snapshot_timestamp_list(&ioctx
, oid
, snapc
.snaps
, &snap_timestamps
));
1054 ASSERT_LT(0U, snap_timestamps
[0].tv
.tv_sec
);
1059 TEST_F(TestClsRbd
, snapid_race
)
1061 librados::IoCtx ioctx
;
1062 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1065 buffer::ptr
bp(4096);
1069 string oid
= get_temp_image_name();
1070 ASSERT_EQ(0, ioctx
.write(oid
, bl
, 4096, 0));
1071 ASSERT_EQ(0, old_snapshot_add(&ioctx
, oid
, 1, "test1"));
1072 ASSERT_EQ(0, old_snapshot_add(&ioctx
, oid
, 3, "test3"));
1073 ASSERT_EQ(-ESTALE
, old_snapshot_add(&ioctx
, oid
, 2, "test2"));
1078 TEST_F(TestClsRbd
, stripingv2
)
1080 librados::IoCtx ioctx
;
1081 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1083 string oid
= get_temp_image_name();
1084 string oid2
= get_temp_image_name();
1085 ASSERT_EQ(0, create_image(&ioctx
, oid
, 10, 22, 0, oid
, -1));
1087 uint64_t su
= 65536, sc
= 12;
1088 ASSERT_EQ(-ENOEXEC
, get_stripe_unit_count(&ioctx
, oid
, &su
, &sc
));
1089 ASSERT_EQ(-ENOEXEC
, set_stripe_unit_count(&ioctx
, oid
, su
, sc
));
1091 ASSERT_EQ(0, create_image(&ioctx
, oid2
, 10, 22, RBD_FEATURE_STRIPINGV2
,
1093 ASSERT_EQ(0, get_stripe_unit_count(&ioctx
, oid2
, &su
, &sc
));
1094 ASSERT_EQ(1ull << 22, su
);
1095 ASSERT_EQ(1ull, sc
);
1098 ASSERT_EQ(0, set_stripe_unit_count(&ioctx
, oid2
, su
, sc
));
1100 ASSERT_EQ(0, get_stripe_unit_count(&ioctx
, oid2
, &su
, &sc
));
1101 ASSERT_EQ(8192ull, su
);
1102 ASSERT_EQ(456ull, sc
);
1104 // su must not be larger than an object
1105 ASSERT_EQ(-EINVAL
, set_stripe_unit_count(&ioctx
, oid2
, 1 << 23, 1));
1106 // su must be a factor of object size
1107 ASSERT_EQ(-EINVAL
, set_stripe_unit_count(&ioctx
, oid2
, 511, 1));
1108 // su and sc must be non-zero
1109 ASSERT_EQ(-EINVAL
, set_stripe_unit_count(&ioctx
, oid2
, 0, 1));
1110 ASSERT_EQ(-EINVAL
, set_stripe_unit_count(&ioctx
, oid2
, 1, 0));
1111 ASSERT_EQ(-EINVAL
, set_stripe_unit_count(&ioctx
, oid2
, 0, 0));
1116 TEST_F(TestClsRbd
, get_mutable_metadata_features
)
1118 librados::IoCtx ioctx
;
1119 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1121 string oid
= get_temp_image_name();
1122 ASSERT_EQ(0, create_image(&ioctx
, oid
, 10, 22, RBD_FEATURE_EXCLUSIVE_LOCK
,
1125 uint64_t size
, features
, incompatible_features
;
1126 std::map
<rados::cls::lock::locker_id_t
,
1127 rados::cls::lock::locker_info_t
> lockers
;
1128 bool exclusive_lock
;
1129 std::string lock_tag
;
1130 ::SnapContext snapc
;
1133 ASSERT_EQ(0, get_mutable_metadata(&ioctx
, oid
, true, &size
, &features
,
1134 &incompatible_features
, &lockers
,
1135 &exclusive_lock
, &lock_tag
, &snapc
,
1137 ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK
), features
);
1138 ASSERT_EQ(0U, incompatible_features
);
1140 ASSERT_EQ(0, get_mutable_metadata(&ioctx
, oid
, false, &size
, &features
,
1141 &incompatible_features
, &lockers
,
1142 &exclusive_lock
, &lock_tag
, &snapc
,
1144 ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK
), features
);
1145 ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK
),
1146 incompatible_features
);
1151 TEST_F(TestClsRbd
, object_map_save
)
1153 librados::IoCtx ioctx
;
1154 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1156 string oid
= get_temp_image_name();
1157 BitVector
<2> ref_bit_vector
;
1158 ref_bit_vector
.resize(32);
1159 for (uint64_t i
= 0; i
< ref_bit_vector
.size(); ++i
) {
1160 ref_bit_vector
[i
] = 1;
1163 librados::ObjectWriteOperation op
;
1164 object_map_save(&op
, ref_bit_vector
);
1165 ASSERT_EQ(0, ioctx
.operate(oid
, &op
));
1167 BitVector
<2> osd_bit_vector
;
1168 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1169 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1172 TEST_F(TestClsRbd
, object_map_resize
)
1174 librados::IoCtx ioctx
;
1175 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1177 string oid
= get_temp_image_name();
1178 BitVector
<2> ref_bit_vector
;
1179 ref_bit_vector
.resize(32);
1180 for (uint64_t i
= 0; i
< ref_bit_vector
.size(); ++i
) {
1181 ref_bit_vector
[i
] = 1;
1184 librados::ObjectWriteOperation op1
;
1185 object_map_resize(&op1
, ref_bit_vector
.size(), 1);
1186 ASSERT_EQ(0, ioctx
.operate(oid
, &op1
));
1188 BitVector
<2> osd_bit_vector
;
1189 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1190 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1192 ref_bit_vector
.resize(64);
1193 for (uint64_t i
= 32; i
< ref_bit_vector
.size(); ++i
) {
1194 ref_bit_vector
[i
] = 2;
1197 librados::ObjectWriteOperation op2
;
1198 object_map_resize(&op2
, ref_bit_vector
.size(), 2);
1199 ASSERT_EQ(0, ioctx
.operate(oid
, &op2
));
1200 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1201 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1203 ref_bit_vector
.resize(32);
1205 librados::ObjectWriteOperation op3
;
1206 object_map_resize(&op3
, ref_bit_vector
.size(), 1);
1207 ASSERT_EQ(-ESTALE
, ioctx
.operate(oid
, &op3
));
1209 librados::ObjectWriteOperation op4
;
1210 object_map_resize(&op4
, ref_bit_vector
.size(), 2);
1211 ASSERT_EQ(0, ioctx
.operate(oid
, &op4
));
1213 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1214 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1219 TEST_F(TestClsRbd
, object_map_update
)
1221 librados::IoCtx ioctx
;
1222 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1224 string oid
= get_temp_image_name();
1225 BitVector
<2> ref_bit_vector
;
1226 ref_bit_vector
.resize(16);
1227 for (uint64_t i
= 0; i
< ref_bit_vector
.size(); ++i
) {
1228 ref_bit_vector
[i
] = 2;
1231 BitVector
<2> osd_bit_vector
;
1233 librados::ObjectWriteOperation op1
;
1234 object_map_resize(&op1
, ref_bit_vector
.size(), 2);
1235 ASSERT_EQ(0, ioctx
.operate(oid
, &op1
));
1236 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1237 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1239 ref_bit_vector
[7] = 1;
1240 ref_bit_vector
[8] = 1;
1242 librados::ObjectWriteOperation op2
;
1243 object_map_update(&op2
, 7, 9, 1, boost::optional
<uint8_t>());
1244 ASSERT_EQ(0, ioctx
.operate(oid
, &op2
));
1245 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1246 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1248 ref_bit_vector
[7] = 3;
1249 ref_bit_vector
[8] = 3;
1251 librados::ObjectWriteOperation op3
;
1252 object_map_update(&op3
, 6, 10, 3, 1);
1253 ASSERT_EQ(0, ioctx
.operate(oid
, &op3
));
1254 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1255 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1260 TEST_F(TestClsRbd
, object_map_load_enoent
)
1262 librados::IoCtx ioctx
;
1263 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1265 string oid
= get_temp_image_name();
1266 BitVector
<2> osd_bit_vector
;
1267 ASSERT_EQ(-ENOENT
, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1272 TEST_F(TestClsRbd
, object_map_snap_add
)
1274 librados::IoCtx ioctx
;
1275 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1277 string oid
= get_temp_image_name();
1278 BitVector
<2> ref_bit_vector
;
1279 ref_bit_vector
.resize(16);
1280 for (uint64_t i
= 0; i
< ref_bit_vector
.size(); ++i
) {
1282 ref_bit_vector
[i
] = OBJECT_NONEXISTENT
;
1284 ref_bit_vector
[i
] = OBJECT_EXISTS
;
1288 BitVector
<2> osd_bit_vector
;
1290 librados::ObjectWriteOperation op1
;
1291 object_map_resize(&op1
, ref_bit_vector
.size(), OBJECT_EXISTS
);
1292 ASSERT_EQ(0, ioctx
.operate(oid
, &op1
));
1294 librados::ObjectWriteOperation op2
;
1295 object_map_update(&op2
, 0, 4, OBJECT_NONEXISTENT
, boost::optional
<uint8_t>());
1296 ASSERT_EQ(0, ioctx
.operate(oid
, &op2
));
1298 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1299 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1301 librados::ObjectWriteOperation op3
;
1302 object_map_snap_add(&op3
);
1303 ASSERT_EQ(0, ioctx
.operate(oid
, &op3
));
1305 for (uint64_t i
= 0; i
< ref_bit_vector
.size(); ++i
) {
1306 if (ref_bit_vector
[i
] == OBJECT_EXISTS
) {
1307 ref_bit_vector
[i
] = OBJECT_EXISTS_CLEAN
;
1311 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1312 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1315 TEST_F(TestClsRbd
, object_map_snap_remove
)
1317 librados::IoCtx ioctx
;
1318 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1320 string oid
= get_temp_image_name();
1321 BitVector
<2> ref_bit_vector
;
1322 ref_bit_vector
.resize(16);
1323 for (uint64_t i
= 0; i
< ref_bit_vector
.size(); ++i
) {
1325 ref_bit_vector
[i
] = OBJECT_EXISTS_CLEAN
;
1327 ref_bit_vector
[i
] = OBJECT_EXISTS
;
1331 BitVector
<2> osd_bit_vector
;
1333 librados::ObjectWriteOperation op1
;
1334 object_map_resize(&op1
, ref_bit_vector
.size(), OBJECT_EXISTS
);
1335 ASSERT_EQ(0, ioctx
.operate(oid
, &op1
));
1337 librados::ObjectWriteOperation op2
;
1338 object_map_update(&op2
, 0, 4, OBJECT_EXISTS_CLEAN
, boost::optional
<uint8_t>());
1339 ASSERT_EQ(0, ioctx
.operate(oid
, &op2
));
1341 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1342 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1344 BitVector
<2> snap_bit_vector
;
1345 snap_bit_vector
.resize(4);
1346 for (uint64_t i
= 0; i
< snap_bit_vector
.size(); ++i
) {
1347 if (i
== 1 || i
== 2) {
1348 snap_bit_vector
[i
] = OBJECT_EXISTS
;
1350 snap_bit_vector
[i
] = OBJECT_NONEXISTENT
;
1354 librados::ObjectWriteOperation op3
;
1355 object_map_snap_remove(&op3
, snap_bit_vector
);
1356 ASSERT_EQ(0, ioctx
.operate(oid
, &op3
));
1358 ref_bit_vector
[1] = OBJECT_EXISTS
;
1359 ref_bit_vector
[2] = OBJECT_EXISTS
;
1360 ASSERT_EQ(0, object_map_load(&ioctx
, oid
, &osd_bit_vector
));
1361 ASSERT_EQ(ref_bit_vector
, osd_bit_vector
);
1364 TEST_F(TestClsRbd
, flags
)
1366 librados::IoCtx ioctx
;
1367 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1369 string oid
= get_temp_image_name();
1370 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, 0, oid
, -1));
1373 std::vector
<snapid_t
> snap_ids
;
1374 std::vector
<uint64_t> snap_flags
;
1375 ASSERT_EQ(0, get_flags(&ioctx
, oid
, &flags
, snap_ids
, &snap_flags
));
1376 ASSERT_EQ(0U, flags
);
1378 librados::ObjectWriteOperation op1
;
1379 set_flags(&op1
, CEPH_NOSNAP
, 3, 2);
1380 ASSERT_EQ(0, ioctx
.operate(oid
, &op1
));
1381 ASSERT_EQ(0, get_flags(&ioctx
, oid
, &flags
, snap_ids
, &snap_flags
));
1382 ASSERT_EQ(2U, flags
);
1384 uint64_t snap_id
= 10;
1385 snap_ids
.push_back(snap_id
);
1386 ASSERT_EQ(-ENOENT
, get_flags(&ioctx
, oid
, &flags
, snap_ids
, &snap_flags
));
1387 ASSERT_EQ(0, snapshot_add(&ioctx
, oid
, snap_id
, "snap"));
1389 librados::ObjectWriteOperation op2
;
1390 set_flags(&op2
, snap_id
, 31, 4);
1391 ASSERT_EQ(0, ioctx
.operate(oid
, &op2
));
1392 ASSERT_EQ(0, get_flags(&ioctx
, oid
, &flags
, snap_ids
, &snap_flags
));
1393 ASSERT_EQ(2U, flags
);
1394 ASSERT_EQ(snap_ids
.size(), snap_flags
.size());
1395 ASSERT_EQ(6U, snap_flags
[0]);
1400 TEST_F(TestClsRbd
, metadata
)
1402 librados::IoCtx ioctx
;
1403 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1405 string oid
= get_temp_image_name();
1406 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, 0, oid
, -1));
1408 map
<string
, bufferlist
> pairs
;
1410 ASSERT_EQ(0, metadata_list(&ioctx
, oid
, "", 0, &pairs
));
1411 ASSERT_TRUE(pairs
.empty());
1413 pairs
["key1"].append("value1");
1414 pairs
["key2"].append("value2");
1415 ASSERT_EQ(0, metadata_set(&ioctx
, oid
, pairs
));
1416 ASSERT_EQ(0, metadata_get(&ioctx
, oid
, "key1", &value
));
1417 ASSERT_EQ(0, strcmp("value1", value
.c_str()));
1419 ASSERT_EQ(0, metadata_list(&ioctx
, oid
, "", 0, &pairs
));
1420 ASSERT_EQ(2U, pairs
.size());
1421 ASSERT_EQ(0, strncmp("value1", pairs
["key1"].c_str(), 6));
1422 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
1425 ASSERT_EQ(0, metadata_remove(&ioctx
, oid
, "key1"));
1426 ASSERT_EQ(0, metadata_remove(&ioctx
, oid
, "key3"));
1427 ASSERT_TRUE(metadata_get(&ioctx
, oid
, "key1", &value
) < 0);
1428 ASSERT_EQ(0, metadata_list(&ioctx
, oid
, "", 0, &pairs
));
1429 ASSERT_EQ(1U, pairs
.size());
1430 ASSERT_EQ(0, strncmp("value2", pairs
["key2"].c_str(), 6));
1433 char key
[10], val
[20];
1434 for (int i
= 0; i
< 1024; i
++) {
1435 sprintf(key
, "key%d", i
);
1436 sprintf(val
, "value%d", i
);
1437 pairs
[key
].append(val
, strlen(val
));
1439 ASSERT_EQ(0, metadata_set(&ioctx
, oid
, pairs
));
1441 string last_read
= "";
1442 uint64_t max_read
= 48, r
;
1444 map
<string
, bufferlist
> data
;
1446 map
<string
, bufferlist
> cur
;
1447 metadata_list(&ioctx
, oid
, last_read
, max_read
, &cur
);
1449 for (map
<string
, bufferlist
>::iterator it
= cur
.begin();
1450 it
!= cur
.end(); ++it
)
1451 data
[it
->first
] = it
->second
;
1452 last_read
= cur
.rbegin()->first
;
1454 } while (r
== max_read
);
1455 ASSERT_EQ(size
, 1024U);
1456 for (map
<string
, bufferlist
>::iterator it
= data
.begin();
1457 it
!= data
.end(); ++it
) {
1458 ASSERT_TRUE(it
->second
.contents_equal(pairs
[it
->first
]));
1464 TEST_F(TestClsRbd
, set_features
)
1466 librados::IoCtx ioctx
;
1467 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1469 string oid
= get_temp_image_name();
1470 uint64_t base_features
= RBD_FEATURE_LAYERING
| RBD_FEATURE_DEEP_FLATTEN
;
1471 ASSERT_EQ(0, create_image(&ioctx
, oid
, 0, 22, base_features
, oid
, -1));
1473 uint64_t features
= RBD_FEATURES_MUTABLE
;
1474 uint64_t mask
= RBD_FEATURES_MUTABLE
;
1475 ASSERT_EQ(0, set_features(&ioctx
, oid
, features
, mask
));
1477 uint64_t actual_features
;
1478 ASSERT_EQ(0, get_features(&ioctx
, oid
, CEPH_NOSNAP
, &actual_features
));
1480 uint64_t expected_features
= RBD_FEATURES_MUTABLE
| base_features
;
1481 ASSERT_EQ(expected_features
, actual_features
);
1484 mask
= RBD_FEATURE_OBJECT_MAP
;
1485 ASSERT_EQ(0, set_features(&ioctx
, oid
, features
, mask
));
1487 ASSERT_EQ(0, get_features(&ioctx
, oid
, CEPH_NOSNAP
, &actual_features
));
1489 expected_features
= (RBD_FEATURES_MUTABLE
| base_features
) &
1490 ~RBD_FEATURE_OBJECT_MAP
;
1491 ASSERT_EQ(expected_features
, actual_features
);
1493 ASSERT_EQ(0, set_features(&ioctx
, oid
, 0, RBD_FEATURE_DEEP_FLATTEN
));
1494 ASSERT_EQ(-EINVAL
, set_features(&ioctx
, oid
, RBD_FEATURE_DEEP_FLATTEN
,
1495 RBD_FEATURE_DEEP_FLATTEN
));
1497 ASSERT_EQ(-EINVAL
, set_features(&ioctx
, oid
, 0, RBD_FEATURE_LAYERING
));
1500 TEST_F(TestClsRbd
, mirror
) {
1501 librados::IoCtx ioctx
;
1502 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1503 ioctx
.remove(RBD_MIRRORING
);
1505 std::vector
<cls::rbd::MirrorPeer
> peers
;
1506 ASSERT_EQ(-ENOENT
, mirror_peer_list(&ioctx
, &peers
));
1509 ASSERT_EQ(-ENOENT
, mirror_uuid_get(&ioctx
, &uuid
));
1510 ASSERT_EQ(-EINVAL
, mirror_peer_add(&ioctx
, "uuid1", "cluster1", "client"));
1512 cls::rbd::MirrorMode mirror_mode
;
1513 ASSERT_EQ(0, mirror_mode_get(&ioctx
, &mirror_mode
));
1514 ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED
, mirror_mode
);
1516 ASSERT_EQ(-EINVAL
, mirror_mode_set(&ioctx
, cls::rbd::MIRROR_MODE_IMAGE
));
1517 ASSERT_EQ(-EINVAL
, mirror_uuid_set(&ioctx
, ""));
1518 ASSERT_EQ(0, mirror_uuid_set(&ioctx
, "mirror-uuid"));
1519 ASSERT_EQ(0, mirror_uuid_get(&ioctx
, &uuid
));
1520 ASSERT_EQ("mirror-uuid", uuid
);
1522 ASSERT_EQ(0, mirror_mode_set(&ioctx
, cls::rbd::MIRROR_MODE_IMAGE
));
1523 ASSERT_EQ(0, mirror_mode_get(&ioctx
, &mirror_mode
));
1524 ASSERT_EQ(cls::rbd::MIRROR_MODE_IMAGE
, mirror_mode
);
1526 ASSERT_EQ(-EINVAL
, mirror_uuid_set(&ioctx
, "new-mirror-uuid"));
1528 ASSERT_EQ(0, mirror_mode_set(&ioctx
, cls::rbd::MIRROR_MODE_POOL
));
1529 ASSERT_EQ(0, mirror_mode_get(&ioctx
, &mirror_mode
));
1530 ASSERT_EQ(cls::rbd::MIRROR_MODE_POOL
, mirror_mode
);
1532 ASSERT_EQ(-EINVAL
, mirror_peer_add(&ioctx
, "mirror-uuid", "cluster1", "client"));
1533 ASSERT_EQ(0, mirror_peer_add(&ioctx
, "uuid1", "cluster1", "client"));
1534 ASSERT_EQ(0, mirror_peer_add(&ioctx
, "uuid2", "cluster2", "admin"));
1535 ASSERT_EQ(-ESTALE
, mirror_peer_add(&ioctx
, "uuid2", "cluster3", "foo"));
1536 ASSERT_EQ(-EEXIST
, mirror_peer_add(&ioctx
, "uuid3", "cluster1", "foo"));
1537 ASSERT_EQ(0, mirror_peer_add(&ioctx
, "uuid3", "cluster3", "admin", 123));
1538 ASSERT_EQ(-EEXIST
, mirror_peer_add(&ioctx
, "uuid4", "cluster3", "admin"));
1539 ASSERT_EQ(-EEXIST
, mirror_peer_add(&ioctx
, "uuid4", "cluster3", "admin", 123));
1540 ASSERT_EQ(0, mirror_peer_add(&ioctx
, "uuid4", "cluster3", "admin", 234));
1542 ASSERT_EQ(0, mirror_peer_list(&ioctx
, &peers
));
1543 std::vector
<cls::rbd::MirrorPeer
> expected_peers
= {
1544 {"uuid1", "cluster1", "client", -1},
1545 {"uuid2", "cluster2", "admin", -1},
1546 {"uuid3", "cluster3", "admin", 123},
1547 {"uuid4", "cluster3", "admin", 234}};
1548 ASSERT_EQ(expected_peers
, peers
);
1550 ASSERT_EQ(0, mirror_peer_remove(&ioctx
, "uuid5"));
1551 ASSERT_EQ(0, mirror_peer_remove(&ioctx
, "uuid4"));
1552 ASSERT_EQ(0, mirror_peer_remove(&ioctx
, "uuid2"));
1554 ASSERT_EQ(-ENOENT
, mirror_peer_set_client(&ioctx
, "uuid4", "new client"));
1555 ASSERT_EQ(0, mirror_peer_set_client(&ioctx
, "uuid1", "new client"));
1557 ASSERT_EQ(-ENOENT
, mirror_peer_set_cluster(&ioctx
, "uuid4", "new cluster"));
1558 ASSERT_EQ(0, mirror_peer_set_cluster(&ioctx
, "uuid3", "new cluster"));
1560 ASSERT_EQ(0, mirror_peer_list(&ioctx
, &peers
));
1562 {"uuid1", "cluster1", "new client", -1},
1563 {"uuid3", "new cluster", "admin", 123}};
1564 ASSERT_EQ(expected_peers
, peers
);
1565 ASSERT_EQ(-EBUSY
, mirror_mode_set(&ioctx
, cls::rbd::MIRROR_MODE_DISABLED
));
1567 ASSERT_EQ(0, mirror_peer_remove(&ioctx
, "uuid3"));
1568 ASSERT_EQ(0, mirror_peer_remove(&ioctx
, "uuid1"));
1569 ASSERT_EQ(0, mirror_peer_list(&ioctx
, &peers
));
1570 expected_peers
= {};
1571 ASSERT_EQ(expected_peers
, peers
);
1573 ASSERT_EQ(0, mirror_mode_set(&ioctx
, cls::rbd::MIRROR_MODE_DISABLED
));
1574 ASSERT_EQ(0, mirror_mode_get(&ioctx
, &mirror_mode
));
1575 ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED
, mirror_mode
);
1576 ASSERT_EQ(-ENOENT
, mirror_uuid_get(&ioctx
, &uuid
));
1579 TEST_F(TestClsRbd
, mirror_image
) {
1580 librados::IoCtx ioctx
;
1581 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1582 ioctx
.remove(RBD_MIRRORING
);
1584 std::map
<std::string
, std::string
> mirror_image_ids
;
1585 ASSERT_EQ(-ENOENT
, mirror_image_list(&ioctx
, "", 0, &mirror_image_ids
));
1587 cls::rbd::MirrorImage
image1("uuid1", cls::rbd::MIRROR_IMAGE_STATE_ENABLED
);
1588 cls::rbd::MirrorImage
image2("uuid2", cls::rbd::MIRROR_IMAGE_STATE_DISABLING
);
1589 cls::rbd::MirrorImage
image3("uuid3", cls::rbd::MIRROR_IMAGE_STATE_ENABLED
);
1591 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id1", image1
));
1592 ASSERT_EQ(-ENOENT
, mirror_image_set(&ioctx
, "image_id2", image2
));
1593 image2
.state
= cls::rbd::MIRROR_IMAGE_STATE_ENABLED
;
1594 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id2", image2
));
1595 image2
.state
= cls::rbd::MIRROR_IMAGE_STATE_DISABLING
;
1596 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id2", image2
));
1597 ASSERT_EQ(-EINVAL
, mirror_image_set(&ioctx
, "image_id1", image2
));
1598 ASSERT_EQ(-EEXIST
, mirror_image_set(&ioctx
, "image_id3", image2
));
1599 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id3", image3
));
1601 std::string image_id
;
1602 ASSERT_EQ(0, mirror_image_get_image_id(&ioctx
, "uuid2", &image_id
));
1603 ASSERT_EQ("image_id2", image_id
);
1605 cls::rbd::MirrorImage read_image
;
1606 ASSERT_EQ(0, mirror_image_get(&ioctx
, "image_id1", &read_image
));
1607 ASSERT_EQ(read_image
, image1
);
1608 ASSERT_EQ(0, mirror_image_get(&ioctx
, "image_id2", &read_image
));
1609 ASSERT_EQ(read_image
, image2
);
1610 ASSERT_EQ(0, mirror_image_get(&ioctx
, "image_id3", &read_image
));
1611 ASSERT_EQ(read_image
, image3
);
1613 ASSERT_EQ(0, mirror_image_list(&ioctx
, "", 1, &mirror_image_ids
));
1614 std::map
<std::string
, std::string
> expected_mirror_image_ids
= {
1615 {"image_id1", "uuid1"}};
1616 ASSERT_EQ(expected_mirror_image_ids
, mirror_image_ids
);
1618 ASSERT_EQ(0, mirror_image_list(&ioctx
, "image_id1", 2, &mirror_image_ids
));
1619 expected_mirror_image_ids
= {{"image_id2", "uuid2"}, {"image_id3", "uuid3"}};
1620 ASSERT_EQ(expected_mirror_image_ids
, mirror_image_ids
);
1622 ASSERT_EQ(0, mirror_image_remove(&ioctx
, "image_id2"));
1623 ASSERT_EQ(-ENOENT
, mirror_image_get_image_id(&ioctx
, "uuid2", &image_id
));
1624 ASSERT_EQ(-EBUSY
, mirror_image_remove(&ioctx
, "image_id1"));
1626 ASSERT_EQ(0, mirror_image_list(&ioctx
, "", 3, &mirror_image_ids
));
1627 expected_mirror_image_ids
= {{"image_id1", "uuid1"}, {"image_id3", "uuid3"}};
1628 ASSERT_EQ(expected_mirror_image_ids
, mirror_image_ids
);
1630 image1
.state
= cls::rbd::MIRROR_IMAGE_STATE_DISABLING
;
1631 image3
.state
= cls::rbd::MIRROR_IMAGE_STATE_DISABLING
;
1632 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id1", image1
));
1633 ASSERT_EQ(0, mirror_image_get(&ioctx
, "image_id1", &read_image
));
1634 ASSERT_EQ(read_image
, image1
);
1635 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id3", image3
));
1636 ASSERT_EQ(0, mirror_image_remove(&ioctx
, "image_id1"));
1637 ASSERT_EQ(0, mirror_image_remove(&ioctx
, "image_id3"));
1639 ASSERT_EQ(0, mirror_image_list(&ioctx
, "", 3, &mirror_image_ids
));
1640 expected_mirror_image_ids
= {};
1641 ASSERT_EQ(expected_mirror_image_ids
, mirror_image_ids
);
1644 TEST_F(TestClsRbd
, mirror_image_status
) {
1645 struct WatchCtx
: public librados::WatchCtx2
{
1646 librados::IoCtx
*m_ioctx
;
1648 WatchCtx(librados::IoCtx
*ioctx
) : m_ioctx(ioctx
) {}
1649 void handle_notify(uint64_t notify_id
, uint64_t cookie
,
1650 uint64_t notifier_id
, bufferlist
& bl_
) override
{
1652 m_ioctx
->notify_ack(RBD_MIRRORING
, notify_id
, cookie
, bl
);
1654 void handle_error(uint64_t cookie
, int err
) override
{}
1657 map
<std::string
, cls::rbd::MirrorImage
> images
;
1658 map
<std::string
, cls::rbd::MirrorImageStatus
> statuses
;
1659 std::map
<cls::rbd::MirrorImageStatusState
, int> states
;
1660 cls::rbd::MirrorImageStatus read_status
;
1661 uint64_t watch_handle
;
1662 librados::IoCtx ioctx
;
1664 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1665 ioctx
.remove(RBD_MIRRORING
);
1667 // Test list fails on nonexistent RBD_MIRRORING object
1669 ASSERT_EQ(-ENOENT
, mirror_image_status_list(&ioctx
, "", 1024, &images
,
1674 cls::rbd::MirrorImage
image1("uuid1", cls::rbd::MIRROR_IMAGE_STATE_ENABLED
);
1675 cls::rbd::MirrorImage
image2("uuid2", cls::rbd::MIRROR_IMAGE_STATE_ENABLED
);
1676 cls::rbd::MirrorImage
image3("uuid3", cls::rbd::MIRROR_IMAGE_STATE_ENABLED
);
1678 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id1", image1
));
1679 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id2", image2
));
1680 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id3", image3
));
1682 cls::rbd::MirrorImageStatus
status1(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN
);
1683 cls::rbd::MirrorImageStatus
status2(cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING
);
1684 cls::rbd::MirrorImageStatus
status3(cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR
);
1686 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid1", status1
));
1689 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, "", 1024, &images
, &statuses
));
1690 ASSERT_EQ(3U, images
.size());
1691 ASSERT_EQ(1U, statuses
.size());
1693 // Test status is down due to RBD_MIRRORING is not watched
1696 ASSERT_EQ(statuses
["image_id1"], status1
);
1697 ASSERT_EQ(0, mirror_image_status_get(&ioctx
, "uuid1", &read_status
));
1698 ASSERT_EQ(read_status
, status1
);
1700 // Test status summary. All statuses are unknown due to down.
1702 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx
, &states
));
1703 ASSERT_EQ(1U, states
.size());
1704 ASSERT_EQ(3, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN
]);
1706 // Test remove_down removes stale statuses
1708 ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx
));
1709 ASSERT_EQ(-ENOENT
, mirror_image_status_get(&ioctx
, "uuid1", &read_status
));
1710 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, "", 1024, &images
, &statuses
));
1711 ASSERT_EQ(3U, images
.size());
1712 ASSERT_TRUE(statuses
.empty());
1713 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx
, &states
));
1714 ASSERT_EQ(1U, states
.size());
1715 ASSERT_EQ(3, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN
]);
1717 // Test statuses are not down after watcher is started
1719 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid1", status1
));
1721 WatchCtx
watch_ctx(&ioctx
);
1722 ASSERT_EQ(0, ioctx
.watch2(RBD_MIRRORING
, &watch_handle
, &watch_ctx
));
1724 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid2", status2
));
1725 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid3", status3
));
1727 ASSERT_EQ(0, mirror_image_status_get(&ioctx
, "uuid1", &read_status
));
1729 ASSERT_EQ(read_status
, status1
);
1730 ASSERT_EQ(0, mirror_image_status_get(&ioctx
, "uuid2", &read_status
));
1732 ASSERT_EQ(read_status
, status2
);
1733 ASSERT_EQ(0, mirror_image_status_get(&ioctx
, "uuid3", &read_status
));
1735 ASSERT_EQ(read_status
, status3
);
1739 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, "", 1024, &images
, &statuses
));
1740 ASSERT_EQ(3U, images
.size());
1741 ASSERT_EQ(3U, statuses
.size());
1742 ASSERT_EQ(statuses
["image_id1"], status1
);
1743 ASSERT_EQ(statuses
["image_id2"], status2
);
1744 ASSERT_EQ(statuses
["image_id3"], status3
);
1746 ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx
));
1747 ASSERT_EQ(0, mirror_image_status_get(&ioctx
, "uuid1", &read_status
));
1748 ASSERT_EQ(read_status
, status1
);
1751 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, "", 1024, &images
, &statuses
));
1752 ASSERT_EQ(3U, images
.size());
1753 ASSERT_EQ(3U, statuses
.size());
1754 ASSERT_EQ(statuses
["image_id1"], status1
);
1755 ASSERT_EQ(statuses
["image_id2"], status2
);
1756 ASSERT_EQ(statuses
["image_id3"], status3
);
1759 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx
, &states
));
1760 ASSERT_EQ(3U, states
.size());
1761 ASSERT_EQ(1, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN
]);
1762 ASSERT_EQ(1, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING
]);
1763 ASSERT_EQ(1, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR
]);
1767 status1
.state
= status3
.state
= cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING
;
1768 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid1", status1
));
1769 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid3", status3
));
1770 ASSERT_EQ(0, mirror_image_status_get(&ioctx
, "uuid3", &read_status
));
1771 ASSERT_EQ(read_status
, status3
);
1774 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx
, &states
));
1775 ASSERT_EQ(1U, states
.size());
1776 ASSERT_EQ(3, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING
]);
1780 ASSERT_EQ(0, mirror_image_status_remove(&ioctx
, "uuid3"));
1781 ASSERT_EQ(-ENOENT
, mirror_image_status_get(&ioctx
, "uuid3", &read_status
));
1784 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, "", 1024, &images
, &statuses
));
1785 ASSERT_EQ(3U, images
.size());
1786 ASSERT_EQ(2U, statuses
.size());
1787 ASSERT_EQ(statuses
["image_id1"], status1
);
1788 ASSERT_EQ(statuses
["image_id2"], status2
);
1791 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx
, &states
));
1792 ASSERT_EQ(2U, states
.size());
1793 ASSERT_EQ(1, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN
]);
1794 ASSERT_EQ(2, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING
]);
1796 // Test statuses are down after removing watcher
1798 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid1", status1
));
1799 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid2", status2
));
1800 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, "uuid3", status3
));
1804 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, "", 1024, &images
, &statuses
));
1805 ASSERT_EQ(3U, images
.size());
1806 ASSERT_EQ(3U, statuses
.size());
1807 ASSERT_EQ(statuses
["image_id1"], status1
);
1808 ASSERT_EQ(statuses
["image_id2"], status2
);
1809 ASSERT_EQ(statuses
["image_id3"], status3
);
1811 ioctx
.unwatch2(watch_handle
);
1813 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, "", 1024, &images
, &statuses
));
1814 ASSERT_EQ(3U, images
.size());
1815 ASSERT_EQ(3U, statuses
.size());
1817 ASSERT_EQ(statuses
["image_id1"], status1
);
1819 ASSERT_EQ(statuses
["image_id2"], status2
);
1821 ASSERT_EQ(statuses
["image_id3"], status3
);
1823 ASSERT_EQ(0, mirror_image_status_get(&ioctx
, "uuid1", &read_status
));
1824 ASSERT_EQ(read_status
, status1
);
1827 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx
, &states
));
1828 ASSERT_EQ(1U, states
.size());
1829 ASSERT_EQ(3, states
[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN
]);
1831 ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx
));
1832 ASSERT_EQ(-ENOENT
, mirror_image_status_get(&ioctx
, "uuid1", &read_status
));
1836 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, "", 1024, &images
, &statuses
));
1837 ASSERT_EQ(3U, images
.size());
1838 ASSERT_TRUE(statuses
.empty());
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
]);
1847 image1
.state
= cls::rbd::MIRROR_IMAGE_STATE_DISABLING
;
1848 image2
.state
= cls::rbd::MIRROR_IMAGE_STATE_DISABLING
;
1849 image3
.state
= cls::rbd::MIRROR_IMAGE_STATE_DISABLING
;
1851 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id1", image1
));
1852 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id2", image2
));
1853 ASSERT_EQ(0, mirror_image_set(&ioctx
, "image_id3", image3
));
1855 ASSERT_EQ(0, mirror_image_remove(&ioctx
, "image_id1"));
1856 ASSERT_EQ(0, mirror_image_remove(&ioctx
, "image_id2"));
1857 ASSERT_EQ(0, mirror_image_remove(&ioctx
, "image_id3"));
1860 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx
, &states
));
1861 ASSERT_EQ(0U, states
.size());
1863 // Test status list with large number of images
1866 ASSERT_EQ(0U, N
% 2);
1868 for (size_t i
= 0; i
< N
; i
++) {
1869 std::string id
= "id" + stringify(i
);
1870 std::string uuid
= "uuid" + stringify(i
);
1871 cls::rbd::MirrorImage
image(uuid
, cls::rbd::MIRROR_IMAGE_STATE_ENABLED
);
1872 cls::rbd::MirrorImageStatus
status(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN
);
1873 ASSERT_EQ(0, mirror_image_set(&ioctx
, id
, image
));
1874 ASSERT_EQ(0, mirror_image_status_set(&ioctx
, uuid
, status
));
1877 std::string last_read
= "";
1880 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, last_read
, N
* 2, &images
,
1882 ASSERT_EQ(N
, images
.size());
1883 ASSERT_EQ(N
, statuses
.size());
1887 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, last_read
, N
/ 2, &images
,
1889 ASSERT_EQ(N
/ 2, images
.size());
1890 ASSERT_EQ(N
/ 2, statuses
.size());
1892 last_read
= images
.rbegin()->first
;
1895 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, last_read
, N
/ 2, &images
,
1897 ASSERT_EQ(N
/ 2, images
.size());
1898 ASSERT_EQ(N
/ 2, statuses
.size());
1900 last_read
= images
.rbegin()->first
;
1903 ASSERT_EQ(0, mirror_image_status_list(&ioctx
, last_read
, N
/ 2, &images
,
1905 ASSERT_EQ(0U, images
.size());
1906 ASSERT_EQ(0U, statuses
.size());
1909 TEST_F(TestClsRbd
, mirror_instances
) {
1910 librados::IoCtx ioctx
;
1911 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1912 ioctx
.remove(RBD_MIRROR_LEADER
);
1914 std::vector
<std::string
> instance_ids
;
1915 ASSERT_EQ(-ENOENT
, mirror_instances_list(&ioctx
, &instance_ids
));
1917 ASSERT_EQ(0, ioctx
.create(RBD_MIRROR_LEADER
, true));
1918 ASSERT_EQ(0, mirror_instances_list(&ioctx
, &instance_ids
));
1919 ASSERT_EQ(0U, instance_ids
.size());
1921 ASSERT_EQ(0, mirror_instances_add(&ioctx
, "instance_id1"));
1922 ASSERT_EQ(0, mirror_instances_list(&ioctx
, &instance_ids
));
1923 ASSERT_EQ(1U, instance_ids
.size());
1924 ASSERT_EQ(instance_ids
[0], "instance_id1");
1926 ASSERT_EQ(0, mirror_instances_add(&ioctx
, "instance_id1"));
1927 ASSERT_EQ(0, mirror_instances_add(&ioctx
, "instance_id2"));
1928 ASSERT_EQ(0, mirror_instances_list(&ioctx
, &instance_ids
));
1929 ASSERT_EQ(2U, instance_ids
.size());
1931 ASSERT_EQ(0, mirror_instances_remove(&ioctx
, "instance_id1"));
1932 ASSERT_EQ(0, mirror_instances_list(&ioctx
, &instance_ids
));
1933 ASSERT_EQ(1U, instance_ids
.size());
1934 ASSERT_EQ(instance_ids
[0], "instance_id2");
1936 ASSERT_EQ(0, mirror_instances_remove(&ioctx
, "instance_id2"));
1937 ASSERT_EQ(0, mirror_instances_list(&ioctx
, &instance_ids
));
1938 ASSERT_EQ(0U, instance_ids
.size());
1941 TEST_F(TestClsRbd
, group_create
) {
1942 librados::IoCtx ioctx
;
1943 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1945 string group_id
= "group_id";
1946 ASSERT_EQ(0, group_create(&ioctx
, group_id
));
1950 ASSERT_EQ(0, ioctx
.stat(group_id
, &psize
, &pmtime
));
1953 TEST_F(TestClsRbd
, group_dir_list
) {
1954 librados::IoCtx ioctx
;
1955 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1957 string group_id1
= "cgid1";
1958 string group_name1
= "cgname1";
1959 string group_id2
= "cgid2";
1960 string group_name2
= "cgname2";
1961 ASSERT_EQ(0, group_dir_add(&ioctx
, RBD_GROUP_DIRECTORY
, group_name1
, group_id1
));
1962 ASSERT_EQ(0, group_dir_add(&ioctx
, RBD_GROUP_DIRECTORY
, group_name2
, group_id2
));
1964 map
<string
, string
> cgs
;
1965 ASSERT_EQ(0, group_dir_list(&ioctx
, RBD_GROUP_DIRECTORY
, "", 10, &cgs
));
1967 ASSERT_EQ(2U, cgs
.size());
1969 auto it
= cgs
.begin();
1970 ASSERT_EQ(group_id1
, it
->second
);
1971 ASSERT_EQ(group_name1
, it
->first
);
1974 ASSERT_EQ(group_id2
, it
->second
);
1975 ASSERT_EQ(group_name2
, it
->first
);
1978 void add_group_to_dir(librados::IoCtx ioctx
, string group_id
, string group_name
) {
1979 ASSERT_EQ(0, group_dir_add(&ioctx
, RBD_GROUP_DIRECTORY
, group_name
, group_id
));
1982 ASSERT_EQ(0, ioctx
.omap_get_keys(RBD_GROUP_DIRECTORY
, "", 10, &keys
));
1983 ASSERT_EQ(2U, keys
.size());
1984 ASSERT_EQ("id_" + group_id
, *keys
.begin());
1985 ASSERT_EQ("name_" + group_name
, *keys
.rbegin());
1988 TEST_F(TestClsRbd
, group_dir_add
) {
1989 librados::IoCtx ioctx
;
1990 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
1991 ioctx
.remove(RBD_GROUP_DIRECTORY
);
1993 string group_id
= "cgid";
1994 string group_name
= "cgname";
1995 add_group_to_dir(ioctx
, group_id
, group_name
);
1998 TEST_F(TestClsRbd
, dir_add_already_existing
) {
1999 librados::IoCtx ioctx
;
2000 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2001 ioctx
.remove(RBD_GROUP_DIRECTORY
);
2003 string group_id
= "cgidexisting";
2004 string group_name
= "cgnameexisting";
2005 add_group_to_dir(ioctx
, group_id
, group_name
);
2007 ASSERT_EQ(-EEXIST
, group_dir_add(&ioctx
, RBD_GROUP_DIRECTORY
, group_name
, group_id
));
2010 TEST_F(TestClsRbd
, group_dir_remove
) {
2011 librados::IoCtx ioctx
;
2012 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2013 ioctx
.remove(RBD_GROUP_DIRECTORY
);
2015 string group_id
= "cgidtodel";
2016 string group_name
= "cgnametodel";
2017 add_group_to_dir(ioctx
, group_id
, group_name
);
2019 ASSERT_EQ(0, group_dir_remove(&ioctx
, RBD_GROUP_DIRECTORY
, group_name
, group_id
));
2022 ASSERT_EQ(0, ioctx
.omap_get_keys(RBD_GROUP_DIRECTORY
, "", 10, &keys
));
2023 ASSERT_EQ(0U, keys
.size());
2026 TEST_F(TestClsRbd
, group_dir_remove_missing
) {
2027 librados::IoCtx ioctx
;
2028 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2029 ioctx
.remove(RBD_GROUP_DIRECTORY
);
2031 string group_id
= "cgidtodelmissing";
2032 string group_name
= "cgnametodelmissing";
2033 // These two lines ensure that RBD_GROUP_DIRECTORY exists. It's important for the
2035 add_group_to_dir(ioctx
, group_id
, group_name
);
2037 ASSERT_EQ(0, group_dir_remove(&ioctx
, RBD_GROUP_DIRECTORY
, group_name
, group_id
));
2040 ASSERT_EQ(-ENOENT
, group_dir_remove(&ioctx
, RBD_GROUP_DIRECTORY
, group_name
, group_id
));
2043 ASSERT_EQ(0, ioctx
.omap_get_keys(RBD_GROUP_DIRECTORY
, "", 10, &keys
));
2044 ASSERT_EQ(0U, keys
.size());
2047 void test_image_add(librados::IoCtx
&ioctx
, const string
& group_id
,
2048 const string
& image_id
, int64_t pool_id
) {
2050 cls::rbd::GroupImageStatus
st(image_id
, pool_id
,
2051 cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE
);
2052 ASSERT_EQ(0, group_image_set(&ioctx
, group_id
, st
));
2055 ASSERT_EQ(0, ioctx
.omap_get_keys(group_id
, "", 10, &keys
));
2057 auto it
= keys
.begin();
2058 ASSERT_EQ(2U, keys
.size());
2060 string image_key
= cls::rbd::GroupImageSpec(image_id
, pool_id
).image_key();
2061 ASSERT_EQ(image_key
, *it
);
2063 ASSERT_EQ("snap_seq", *it
);
2066 TEST_F(TestClsRbd
, group_image_add
) {
2067 librados::IoCtx ioctx
;
2068 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2070 string group_id
= "group_id";
2071 ASSERT_EQ(0, group_create(&ioctx
, group_id
));
2073 int64_t pool_id
= ioctx
.get_id();
2074 string image_id
= "image_id";
2075 test_image_add(ioctx
, group_id
, image_id
, pool_id
);
2078 TEST_F(TestClsRbd
, group_image_remove
) {
2079 librados::IoCtx ioctx
;
2080 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2082 string group_id
= "group_id";
2083 ASSERT_EQ(0, group_create(&ioctx
, group_id
));
2085 int64_t pool_id
= ioctx
.get_id();
2086 string image_id
= "image_id";
2087 test_image_add(ioctx
, group_id
, image_id
, pool_id
);
2089 cls::rbd::GroupImageSpec
spec(image_id
, pool_id
);
2090 ASSERT_EQ(0, group_image_remove(&ioctx
, group_id
, spec
));
2092 ASSERT_EQ(0, ioctx
.omap_get_keys(group_id
, "", 10, &keys
));
2093 ASSERT_EQ(1U, keys
.size());
2094 ASSERT_EQ("snap_seq", *(keys
.begin()));
2097 TEST_F(TestClsRbd
, group_image_list
) {
2098 librados::IoCtx ioctx
;
2099 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2101 string group_id
= "group_id";
2102 ASSERT_EQ(0, group_create(&ioctx
, group_id
));
2104 int64_t pool_id
= ioctx
.get_id();
2105 string image_id
= "imageid"; // Image id shouldn't contain underscores
2106 test_image_add(ioctx
, group_id
, image_id
, pool_id
);
2108 vector
<cls::rbd::GroupImageStatus
> images
;
2109 cls::rbd::GroupImageSpec empty_image_spec
= cls::rbd::GroupImageSpec();
2110 ASSERT_EQ(0, group_image_list(&ioctx
, group_id
, empty_image_spec
, 1024,
2112 ASSERT_EQ(1U, images
.size());
2113 ASSERT_EQ(image_id
, images
[0].spec
.image_id
);
2114 ASSERT_EQ(pool_id
, images
[0].spec
.pool_id
);
2115 ASSERT_EQ(cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE
, images
[0].state
);
2117 cls::rbd::GroupImageStatus last_image
= *images
.rbegin();
2118 ASSERT_EQ(0, group_image_list(&ioctx
, group_id
, last_image
.spec
, 1024,
2120 ASSERT_EQ(0U, images
.size());
2123 TEST_F(TestClsRbd
, group_image_clean
) {
2124 librados::IoCtx ioctx
;
2125 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2127 string group_id
= "group_id1";
2128 ASSERT_EQ(0, group_create(&ioctx
, group_id
));
2130 int64_t pool_id
= ioctx
.get_id();
2131 string image_id
= "image_id";
2132 test_image_add(ioctx
, group_id
, image_id
, pool_id
);
2134 cls::rbd::GroupImageStatus
incomplete_st(image_id
, pool_id
,
2135 cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE
);
2137 ASSERT_EQ(0, group_image_set(&ioctx
, group_id
, incomplete_st
));
2138 // Set to dirty first in order to make sure that group_image_clean
2139 // actually does something.
2140 cls::rbd::GroupImageStatus
attached_st(image_id
, pool_id
,
2141 cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED
);
2142 ASSERT_EQ(0, group_image_set(&ioctx
, group_id
, attached_st
));
2144 string image_key
= cls::rbd::GroupImageSpec(image_id
, pool_id
).image_key();
2146 map
<string
, bufferlist
> vals
;
2147 ASSERT_EQ(0, ioctx
.omap_get_vals(group_id
, "", 10, &vals
));
2149 cls::rbd::GroupImageLinkState ref_state
;
2150 bufferlist::iterator it
= vals
[image_key
].begin();
2151 ::decode(ref_state
, it
);
2152 ASSERT_EQ(cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED
, ref_state
);
2155 TEST_F(TestClsRbd
, image_add_group
) {
2156 librados::IoCtx ioctx
;
2157 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2159 int64_t pool_id
= ioctx
.get_id();
2160 string image_id
= "imageid";
2162 ASSERT_EQ(0, create_image(&ioctx
, image_id
, 2<<20, 0,
2163 RBD_FEATURE_LAYERING
, image_id
, -1));
2165 string group_id
= "group_id";
2167 cls::rbd::GroupSpec
spec(group_id
, pool_id
);
2168 ASSERT_EQ(0, image_add_group(&ioctx
, image_id
, spec
));
2170 map
<string
, bufferlist
> vals
;
2171 ASSERT_EQ(0, ioctx
.omap_get_vals(image_id
, "", RBD_GROUP_REF
, 10, &vals
));
2173 cls::rbd::GroupSpec val_spec
;
2174 bufferlist::iterator it
= vals
[RBD_GROUP_REF
].begin();
2175 ::decode(val_spec
, it
);
2177 ASSERT_EQ(group_id
, val_spec
.group_id
);
2178 ASSERT_EQ(pool_id
, val_spec
.pool_id
);
2181 TEST_F(TestClsRbd
, image_remove_group
) {
2182 librados::IoCtx ioctx
;
2183 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2185 int64_t pool_id
= ioctx
.get_id();
2186 string image_id
= "image_id";
2188 ASSERT_EQ(0, create_image(&ioctx
, image_id
, 2<<20, 0,
2189 RBD_FEATURE_LAYERING
, image_id
, -1));
2191 string group_id
= "group_id";
2193 cls::rbd::GroupSpec
spec(group_id
, pool_id
);
2194 ASSERT_EQ(0, image_add_group(&ioctx
, image_id
, spec
));
2195 // Add reference in order to make sure that image_remove_group actually
2197 ASSERT_EQ(0, image_remove_group(&ioctx
, image_id
, spec
));
2199 map
<string
, bufferlist
> vals
;
2200 ASSERT_EQ(0, ioctx
.omap_get_vals(image_id
, "", RBD_GROUP_REF
, 10, &vals
));
2202 ASSERT_EQ(0U, vals
.size());
2205 TEST_F(TestClsRbd
, image_get_group
) {
2206 librados::IoCtx ioctx
;
2207 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2209 int64_t pool_id
= ioctx
.get_id();
2210 string image_id
= "imageidgroupspec";
2212 ASSERT_EQ(0, create_image(&ioctx
, image_id
, 2<<20, 0,
2213 RBD_FEATURE_LAYERING
, image_id
, -1));
2215 string group_id
= "group_id_get_group_spec";
2217 cls::rbd::GroupSpec
spec_add(group_id
, pool_id
);
2218 ASSERT_EQ(0, image_add_group(&ioctx
, image_id
, spec_add
));
2220 cls::rbd::GroupSpec spec
;
2221 ASSERT_EQ(0, image_get_group(&ioctx
, image_id
, &spec
));
2223 ASSERT_EQ(group_id
, spec
.group_id
);
2224 ASSERT_EQ(pool_id
, spec
.pool_id
);
2227 TEST_F(TestClsRbd
, trash_methods
)
2229 librados::IoCtx ioctx
;
2230 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), ioctx
));
2232 string id
= "123456789";
2233 string id2
= "123456780";
2235 std::map
<string
, cls::rbd::TrashImageSpec
> entries
;
2236 ASSERT_EQ(-ENOENT
, trash_list(&ioctx
, &entries
));
2238 utime_t now1
= ceph_clock_now();
2239 utime_t now1_delay
= now1
;
2241 cls::rbd::TrashImageSpec
trash_spec(cls::rbd::TRASH_IMAGE_SOURCE_USER
, "name",
2243 ASSERT_EQ(0, trash_add(&ioctx
, id
, trash_spec
));
2245 utime_t now2
= ceph_clock_now();
2246 utime_t now2_delay
= now2
;
2248 cls::rbd::TrashImageSpec
trash_spec2(cls::rbd::TRASH_IMAGE_SOURCE_MIRRORING
,
2249 "name2", now2
, now2_delay
);
2250 ASSERT_EQ(-EEXIST
, trash_add(&ioctx
, id
, trash_spec2
));
2252 ASSERT_EQ(0, trash_remove(&ioctx
, id
));
2253 ASSERT_EQ(-ENOENT
, trash_remove(&ioctx
, id
));
2255 ASSERT_EQ(0, trash_list(&ioctx
, &entries
));
2256 ASSERT_TRUE(entries
.empty());
2258 ASSERT_EQ(0, trash_add(&ioctx
, id
, trash_spec2
));
2259 ASSERT_EQ(0, trash_add(&ioctx
, id2
, trash_spec
));
2261 ASSERT_EQ(0, trash_list(&ioctx
, &entries
));
2263 for (auto& entry
: entries
) {
2264 if (entry
.first
== id
) {
2265 ASSERT_EQ(entry
.second
.source
, cls::rbd::TRASH_IMAGE_SOURCE_MIRRORING
);
2266 ASSERT_EQ(entry
.second
.name
, "name2");
2267 ASSERT_EQ(entry
.second
.deletion_time
, now2
);
2268 ASSERT_EQ(entry
.second
.deferment_end_time
, now2_delay
);
2269 } else if (entry
.first
== id2
) {
2270 ASSERT_EQ(entry
.second
.source
, cls::rbd::TRASH_IMAGE_SOURCE_USER
);
2271 ASSERT_EQ(entry
.second
.name
, "name");
2272 ASSERT_EQ(entry
.second
.deletion_time
, now1
);
2273 ASSERT_EQ(entry
.second
.deferment_end_time
, now1_delay
);
2277 cls::rbd::TrashImageSpec spec_res1
;
2278 ASSERT_EQ(0, trash_get(&ioctx
, id
, &spec_res1
));
2279 cls::rbd::TrashImageSpec spec_res2
;
2280 ASSERT_EQ(0, trash_get(&ioctx
, id2
, &spec_res2
));
2282 ASSERT_EQ(spec_res1
.name
, "name2");
2283 ASSERT_EQ(spec_res1
.deletion_time
, now2
);
2284 ASSERT_EQ(spec_res1
.deferment_end_time
, now2_delay
);
2286 ASSERT_EQ(spec_res2
.name
, "name");
2287 ASSERT_EQ(spec_res2
.deletion_time
, now1
);
2288 ASSERT_EQ(spec_res2
.deferment_end_time
, now1_delay
);