]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/cls_rbd/test_cls_rbd.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / test / cls_rbd / test_cls_rbd.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "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"
17
18 #include "gtest/gtest.h"
19 #include "test/librados/test.h"
20
21 #include <errno.h>
22 #include <string>
23 #include <vector>
24
25 using namespace std;
26 using namespace librbd::cls_client;
27 using ::librbd::ParentInfo;
28 using ::librbd::ParentSpec;
29
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);
35 }
36
37 static int snapshot_remove(librados::IoCtx *ioctx, const std::string &oid,
38 uint64_t snap_id) {
39 librados::ObjectWriteOperation op;
40 ::librbd::cls_client::snapshot_remove(&op, snap_id);
41 return ioctx->operate(oid, &op);
42 }
43
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);
49 }
50
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);
56 }
57
58 static char *random_buf(size_t len)
59 {
60 char *b = new char[len];
61 for (size_t i = 0; i < len; i++)
62 b[i] = (rand() % (128 - 32)) + 32;
63 return b;
64 }
65
66 class TestClsRbd : public ::testing::Test {
67 public:
68
69 static void SetUpTestCase() {
70 _pool_name = get_temp_pool_name();
71 ASSERT_EQ("", create_one_pool_pp(_pool_name, _rados));
72 }
73
74 static void TearDownTestCase() {
75 ASSERT_EQ(0, destroy_one_pool_pp(_pool_name, _rados));
76 }
77
78 std::string get_temp_image_name() {
79 ++_image_number;
80 return "image" + stringify(_image_number);
81 }
82
83 static std::string _pool_name;
84 static librados::Rados _rados;
85 static uint64_t _image_number;
86
87 };
88
89 std::string TestClsRbd::_pool_name;
90 librados::Rados TestClsRbd::_rados;
91 uint64_t TestClsRbd::_image_number = 0;
92
93 TEST_F(TestClsRbd, get_all_features)
94 {
95 librados::IoCtx ioctx;
96 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
97
98 string oid = get_temp_image_name();
99 ASSERT_EQ(0, ioctx.create(oid, false));
100
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);
104
105 ioctx.close();
106 }
107
108 TEST_F(TestClsRbd, copyup)
109 {
110 librados::IoCtx ioctx;
111 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
112
113 string oid = get_temp_image_name();
114 bufferlist inbl, outbl;
115
116 // copyup of 0-len nonexistent object should create new 0-len object
117 ioctx.remove(oid);
118 ASSERT_EQ(0, copyup(&ioctx, oid, inbl));
119 uint64_t size;
120 ASSERT_EQ(0, ioctx.stat(oid, &size, NULL));
121 ASSERT_EQ(0U, size);
122
123 // create some random data to write
124 size_t l = 4 << 20;
125 char *b = random_buf(l);
126 inbl.append(b, l);
127 delete [] b;
128 ASSERT_EQ(l, inbl.length());
129
130 // copyup to nonexistent object should create new object
131 ioctx.remove(oid);
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));
137
138 // now send different data, but with a preexisting object
139 bufferlist inbl2;
140 b = random_buf(l);
141 inbl2.append(b, l);
142 delete [] b;
143 ASSERT_EQ(l, inbl2.length());
144
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));
151
152 ASSERT_EQ(0, ioctx.remove(oid));
153 ioctx.close();
154 }
155
156 TEST_F(TestClsRbd, get_and_set_id)
157 {
158 librados::IoCtx ioctx;
159 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
160
161 string oid = get_temp_image_name();
162 string id;
163 string valid_id = "0123abcxyzZYXCBA";
164 string invalid_id = ".abc";
165 string empty_id;
166
167 ASSERT_EQ(-ENOENT, get_id(&ioctx, oid, &id));
168 ASSERT_EQ(-ENOENT, set_id(&ioctx, oid, valid_id));
169
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));
174
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);
180
181 ioctx.close();
182 }
183
184 TEST_F(TestClsRbd, add_remove_child)
185 {
186 librados::IoCtx ioctx;
187 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
188
189 string oid = get_temp_image_name();
190 ASSERT_EQ(0, ioctx.create(oid, true));
191
192 string snapname = "parent_snap";
193 snapid_t snapid(10);
194 string parent_image = "parent_id";
195 set<string>children;
196 ParentSpec pspec(ioctx.get_id(), parent_image, snapid);
197
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"));
201
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));
206
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"));
226
227 ioctx.close();
228 }
229
230 TEST_F(TestClsRbd, directory_methods)
231 {
232 librados::IoCtx ioctx;
233 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
234
235 string oid = get_temp_image_name();
236 string id, 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";
243 string empty;
244
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));
248
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));
252
253 map<string, string> images;
254 ASSERT_EQ(-ENOENT, dir_list(&ioctx, oid, "", 30, &images));
255
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));
260
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);
273
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);
288
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);
300
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));
311
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));
324
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());
335
336 ioctx.close();
337 }
338
339 TEST_F(TestClsRbd, create)
340 {
341 librados::IoCtx ioctx;
342 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
343
344 string oid = get_temp_image_name();
345 uint64_t size = 20ULL << 30;
346 uint64_t features = 0;
347 uint8_t order = 22;
348 string object_prefix = oid;
349
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));
355
356 ASSERT_EQ(-EINVAL, create_image(&ioctx, oid, size, order,
357 features, "", -1));
358 ASSERT_EQ(-ENOENT, ioctx.remove(oid));
359
360 ASSERT_EQ(0, create_image(&ioctx, oid, 0, order,
361 features, object_prefix, -1));
362 ASSERT_EQ(0, ioctx.remove(oid));
363
364 ASSERT_EQ(-ENOSYS, create_image(&ioctx, oid, size, order,
365 -1, object_prefix, -1));
366 ASSERT_EQ(-ENOENT, ioctx.remove(oid));
367
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,
374 123));
375
376 bufferlist inbl, outbl;
377 ASSERT_EQ(-EINVAL, ioctx.exec(oid, "rbd", "create", inbl, outbl));
378
379 ioctx.close();
380 }
381
382 TEST_F(TestClsRbd, get_features)
383 {
384 librados::IoCtx ioctx;
385 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
386
387 string oid = get_temp_image_name();
388
389 uint64_t features;
390 ASSERT_EQ(-ENOENT, get_features(&ioctx, oid, CEPH_NOSNAP, &features));
391
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);
395
396 int r = get_features(&ioctx, oid, 1, &features);
397 if (r == 0) {
398 ASSERT_EQ(0u, features);
399 } else {
400 // deprecated snapshot handling
401 ASSERT_EQ(-ENOENT, r);
402 }
403
404 ioctx.close();
405 }
406
407 TEST_F(TestClsRbd, get_object_prefix)
408 {
409 librados::IoCtx ioctx;
410 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
411
412 string oid = get_temp_image_name();
413
414 string object_prefix;
415 ASSERT_EQ(-ENOENT, get_object_prefix(&ioctx, oid, &object_prefix));
416
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);
420
421 ioctx.close();
422 }
423
424 TEST_F(TestClsRbd, get_data_pool)
425 {
426 librados::IoCtx ioctx;
427 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
428
429 string oid = get_temp_image_name();
430
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));
436
437 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, RBD_FEATURE_DATA_POOL, oid,
438 12));
439 ASSERT_EQ(0, get_data_pool(&ioctx, oid, &data_pool_id));
440 ASSERT_EQ(12, data_pool_id);
441 }
442
443 TEST_F(TestClsRbd, get_size)
444 {
445 librados::IoCtx ioctx;
446 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
447
448 string oid = get_temp_image_name();
449 uint64_t size;
450 uint8_t order;
451 ASSERT_EQ(-ENOENT, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
452
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));
455 ASSERT_EQ(0u, size);
456 ASSERT_EQ(22, order);
457 ASSERT_EQ(0, ioctx.remove(oid));
458
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);
462 ASSERT_EQ(0, order);
463
464 ASSERT_EQ(-ENOENT, get_size(&ioctx, oid, 1, &size, &order));
465
466 ioctx.close();
467 }
468
469 TEST_F(TestClsRbd, set_size)
470 {
471 librados::IoCtx ioctx;
472 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
473
474 string oid = get_temp_image_name();
475 ASSERT_EQ(-ENOENT, set_size(&ioctx, oid, 5));
476
477 uint64_t size;
478 uint8_t order;
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));
481 ASSERT_EQ(0u, size);
482 ASSERT_EQ(22, order);
483
484 ASSERT_EQ(0, set_size(&ioctx, oid, 0));
485 ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
486 ASSERT_EQ(0u, size);
487 ASSERT_EQ(22, order);
488
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);
493
494 ioctx.close();
495 }
496
497 TEST_F(TestClsRbd, protection_status)
498 {
499 librados::IoCtx ioctx;
500 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
501
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));
509
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,
521 2, &status));
522 ASSERT_EQ(-ENOENT, set_protection_status(&ioctx, oid,
523 2, status));
524
525 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 10, "snap1"));
526 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
527 10, &status));
528 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED, status);
529
530 ASSERT_EQ(0, set_protection_status(&ioctx, oid,
531 10, RBD_PROTECTION_STATUS_PROTECTED));
532 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
533 10, &status));
534 ASSERT_EQ(+RBD_PROTECTION_STATUS_PROTECTED, status);
535 ASSERT_EQ(-EBUSY, snapshot_remove(&ioctx, oid, 10));
536
537 ASSERT_EQ(0, set_protection_status(&ioctx, oid,
538 10, RBD_PROTECTION_STATUS_UNPROTECTING));
539 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
540 10, &status));
541 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTING, status);
542 ASSERT_EQ(-EBUSY, snapshot_remove(&ioctx, oid, 10));
543
544 ASSERT_EQ(-EINVAL, set_protection_status(&ioctx, oid,
545 10, RBD_PROTECTION_STATUS_LAST));
546 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
547 10, &status));
548 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTING, status);
549
550 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 20, "snap2"));
551 ASSERT_EQ(0, get_protection_status(&ioctx, oid,
552 20, &status));
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,
557 10, &status));
558 ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED, status);
559
560 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 10));
561 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 20));
562
563 ioctx.close();
564 }
565
566 TEST_F(TestClsRbd, snapshot_limits)
567 {
568 librados::IoCtx ioctx;
569 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
570
571 librados::ObjectWriteOperation op;
572 string oid = get_temp_image_name();
573 uint64_t limit;
574
575 ASSERT_EQ(-ENOENT, snapshot_get_limit(&ioctx, oid, &limit));
576
577 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, RBD_FEATURE_LAYERING, oid, -1));
578
579 snapshot_set_limit(&op, 2);
580
581 ASSERT_EQ(0, ioctx.operate(oid, &op));
582
583 ASSERT_EQ(0, snapshot_get_limit(&ioctx, oid, &limit));
584 ASSERT_EQ(2U, limit);
585
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"));
589
590 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 10));
591 ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 20));
592
593 ioctx.close();
594 }
595
596 TEST_F(TestClsRbd, parents)
597 {
598 librados::IoCtx ioctx;
599 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
600
601 string oid = get_temp_image_name();
602 ParentSpec pspec;
603 uint64_t size;
604
605 ASSERT_EQ(-ENOENT, get_parent(&ioctx, "doesnotexist", CEPH_NOSNAP, &pspec, &size));
606
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"));
618
619 // new image will work
620 ASSERT_EQ(0, create_image(&ioctx, oid, 33<<20, 22, RBD_FEATURE_LAYERING,
621 "foo.", -1));
622
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);
627
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));
632
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));
637
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));
642
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);
647
648 // snapshots
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);
656
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);
670
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);
685
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));
694
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));
702
703 // make sure resize adjust parent overlap
704 ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 10<<20));
705
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);
718
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);
736
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);
743
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);
750
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,
754 "foo.", -1));
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));
759
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);
766
767 ioctx.close();
768 }
769
770 TEST_F(TestClsRbd, snapshots)
771 {
772 cls::rbd::SnapshotNamespace userSnapNamespace = cls::rbd::UserSnapshotNamespace();
773 librados::IoCtx ioctx;
774 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
775
776 string oid = get_temp_image_name();
777 ASSERT_EQ(-ENOENT, snapshot_add(&ioctx, oid, 0, "snap1"));
778
779 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
780
781 vector<string> snap_names;
782 vector<cls::rbd::SnapshotNamespace> snap_namespaces;
783 vector<uint64_t> snap_sizes;
784 SnapContext snapc;
785 vector<ParentInfo> parents;
786 vector<uint8_t> protection_status;
787 vector<utime_t> snap_timestamps;
788
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());
800
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());
816
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());
833
834
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());
851
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());
868
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());
889
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());
904
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());
920
921 uint64_t size;
922 uint8_t order;
923 ASSERT_EQ(0, set_size(&ioctx, oid, 0));
924 ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
925 ASSERT_EQ(0u, size);
926 ASSERT_EQ(22u, order);
927
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());
948
949 ASSERT_EQ(0, get_size(&ioctx, oid, large_snap_id, &size, &order));
950 ASSERT_EQ(0u, size);
951 ASSERT_EQ(22u, order);
952
953 ASSERT_EQ(0, get_size(&ioctx, oid, 1, &size, &order));
954 ASSERT_EQ(10u, size);
955 ASSERT_EQ(22u, order);
956
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());
972
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());
986
987 ioctx.close();
988 }
989
990 TEST_F(TestClsRbd, snapshots_namespaces)
991 {
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));
996
997 string oid = get_temp_image_name();
998
999 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
1000
1001 vector<string> snap_names;
1002 vector<cls::rbd::SnapshotNamespace> snap_namespaces;
1003 SnapContext snapc;
1004
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());
1010
1011 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
1012
1013 librados::ObjectWriteOperation op;
1014 ::librbd::cls_client::snapshot_add(&op, 1, "snap1", groupSnapNamespace);
1015 int r = ioctx.operate(oid, &op);
1016 ASSERT_EQ(0, r);
1017
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]);
1026
1027 ioctx.close();
1028 }
1029
1030 TEST_F(TestClsRbd, snapshots_timestamps)
1031 {
1032 librados::IoCtx ioctx;
1033 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1034
1035 string oid = get_temp_image_name();
1036
1037 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
1038
1039 vector<string> snap_names;
1040 vector<utime_t> snap_timestamps;
1041 SnapContext snapc;
1042
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());
1048
1049 ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
1050
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);
1055 ioctx.close();
1056 }
1057
1058
1059 TEST_F(TestClsRbd, snapid_race)
1060 {
1061 librados::IoCtx ioctx;
1062 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1063
1064 buffer::list bl;
1065 buffer::ptr bp(4096);
1066 bp.zero();
1067 bl.append(bp);
1068
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"));
1074
1075 ioctx.close();
1076 }
1077
1078 TEST_F(TestClsRbd, stripingv2)
1079 {
1080 librados::IoCtx ioctx;
1081 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1082
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));
1086
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));
1090
1091 ASSERT_EQ(0, create_image(&ioctx, oid2, 10, 22, RBD_FEATURE_STRIPINGV2,
1092 oid2, -1));
1093 ASSERT_EQ(0, get_stripe_unit_count(&ioctx, oid2, &su, &sc));
1094 ASSERT_EQ(1ull << 22, su);
1095 ASSERT_EQ(1ull, sc);
1096 su = 8192;
1097 sc = 456;
1098 ASSERT_EQ(0, set_stripe_unit_count(&ioctx, oid2, su, sc));
1099 su = sc = 0;
1100 ASSERT_EQ(0, get_stripe_unit_count(&ioctx, oid2, &su, &sc));
1101 ASSERT_EQ(8192ull, su);
1102 ASSERT_EQ(456ull, sc);
1103
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));
1112
1113 ioctx.close();
1114 }
1115
1116 TEST_F(TestClsRbd, get_mutable_metadata_features)
1117 {
1118 librados::IoCtx ioctx;
1119 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1120
1121 string oid = get_temp_image_name();
1122 ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, RBD_FEATURE_EXCLUSIVE_LOCK,
1123 oid, -1));
1124
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;
1131 ParentInfo parent;
1132
1133 ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, true, &size, &features,
1134 &incompatible_features, &lockers,
1135 &exclusive_lock, &lock_tag, &snapc,
1136 &parent));
1137 ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK), features);
1138 ASSERT_EQ(0U, incompatible_features);
1139
1140 ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, false, &size, &features,
1141 &incompatible_features, &lockers,
1142 &exclusive_lock, &lock_tag, &snapc,
1143 &parent));
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);
1147
1148 ioctx.close();
1149 }
1150
1151 TEST_F(TestClsRbd, object_map_save)
1152 {
1153 librados::IoCtx ioctx;
1154 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1155
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;
1161 }
1162
1163 librados::ObjectWriteOperation op;
1164 object_map_save(&op, ref_bit_vector);
1165 ASSERT_EQ(0, ioctx.operate(oid, &op));
1166
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);
1170 }
1171
1172 TEST_F(TestClsRbd, object_map_resize)
1173 {
1174 librados::IoCtx ioctx;
1175 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1176
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;
1182 }
1183
1184 librados::ObjectWriteOperation op1;
1185 object_map_resize(&op1, ref_bit_vector.size(), 1);
1186 ASSERT_EQ(0, ioctx.operate(oid, &op1));
1187
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);
1191
1192 ref_bit_vector.resize(64);
1193 for (uint64_t i = 32; i < ref_bit_vector.size(); ++i) {
1194 ref_bit_vector[i] = 2;
1195 }
1196
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);
1202
1203 ref_bit_vector.resize(32);
1204
1205 librados::ObjectWriteOperation op3;
1206 object_map_resize(&op3, ref_bit_vector.size(), 1);
1207 ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op3));
1208
1209 librados::ObjectWriteOperation op4;
1210 object_map_resize(&op4, ref_bit_vector.size(), 2);
1211 ASSERT_EQ(0, ioctx.operate(oid, &op4));
1212
1213 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1214 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1215
1216 ioctx.close();
1217 }
1218
1219 TEST_F(TestClsRbd, object_map_update)
1220 {
1221 librados::IoCtx ioctx;
1222 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1223
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;
1229 }
1230
1231 BitVector<2> osd_bit_vector;
1232
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);
1238
1239 ref_bit_vector[7] = 1;
1240 ref_bit_vector[8] = 1;
1241
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);
1247
1248 ref_bit_vector[7] = 3;
1249 ref_bit_vector[8] = 3;
1250
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);
1256
1257 ioctx.close();
1258 }
1259
1260 TEST_F(TestClsRbd, object_map_load_enoent)
1261 {
1262 librados::IoCtx ioctx;
1263 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1264
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));
1268
1269 ioctx.close();
1270 }
1271
1272 TEST_F(TestClsRbd, object_map_snap_add)
1273 {
1274 librados::IoCtx ioctx;
1275 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1276
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) {
1281 if (i < 4) {
1282 ref_bit_vector[i] = OBJECT_NONEXISTENT;
1283 } else {
1284 ref_bit_vector[i] = OBJECT_EXISTS;
1285 }
1286 }
1287
1288 BitVector<2> osd_bit_vector;
1289
1290 librados::ObjectWriteOperation op1;
1291 object_map_resize(&op1, ref_bit_vector.size(), OBJECT_EXISTS);
1292 ASSERT_EQ(0, ioctx.operate(oid, &op1));
1293
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));
1297
1298 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1299 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1300
1301 librados::ObjectWriteOperation op3;
1302 object_map_snap_add(&op3);
1303 ASSERT_EQ(0, ioctx.operate(oid, &op3));
1304
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;
1308 }
1309 }
1310
1311 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1312 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1313 }
1314
1315 TEST_F(TestClsRbd, object_map_snap_remove)
1316 {
1317 librados::IoCtx ioctx;
1318 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1319
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) {
1324 if (i < 4) {
1325 ref_bit_vector[i] = OBJECT_EXISTS_CLEAN;
1326 } else {
1327 ref_bit_vector[i] = OBJECT_EXISTS;
1328 }
1329 }
1330
1331 BitVector<2> osd_bit_vector;
1332
1333 librados::ObjectWriteOperation op1;
1334 object_map_resize(&op1, ref_bit_vector.size(), OBJECT_EXISTS);
1335 ASSERT_EQ(0, ioctx.operate(oid, &op1));
1336
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));
1340
1341 ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1342 ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1343
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;
1349 } else {
1350 snap_bit_vector[i] = OBJECT_NONEXISTENT;
1351 }
1352 }
1353
1354 librados::ObjectWriteOperation op3;
1355 object_map_snap_remove(&op3, snap_bit_vector);
1356 ASSERT_EQ(0, ioctx.operate(oid, &op3));
1357
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);
1362 }
1363
1364 TEST_F(TestClsRbd, flags)
1365 {
1366 librados::IoCtx ioctx;
1367 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1368
1369 string oid = get_temp_image_name();
1370 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
1371
1372 uint64_t flags;
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);
1377
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);
1383
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"));
1388
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]);
1396
1397 ioctx.close();
1398 }
1399
1400 TEST_F(TestClsRbd, metadata)
1401 {
1402 librados::IoCtx ioctx;
1403 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1404
1405 string oid = get_temp_image_name();
1406 ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
1407
1408 map<string, bufferlist> pairs;
1409 string value;
1410 ASSERT_EQ(0, metadata_list(&ioctx, oid, "", 0, &pairs));
1411 ASSERT_TRUE(pairs.empty());
1412
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()));
1418 pairs.clear();
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));
1423
1424 pairs.clear();
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));
1431
1432 pairs.clear();
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));
1438 }
1439 ASSERT_EQ(0, metadata_set(&ioctx, oid, pairs));
1440
1441 string last_read = "";
1442 uint64_t max_read = 48, r;
1443 uint64_t size = 0;
1444 map<string, bufferlist> data;
1445 do {
1446 map<string, bufferlist> cur;
1447 metadata_list(&ioctx, oid, last_read, max_read, &cur);
1448 size += cur.size();
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;
1453 r = cur.size();
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]));
1459 }
1460
1461 ioctx.close();
1462 }
1463
1464 TEST_F(TestClsRbd, set_features)
1465 {
1466 librados::IoCtx ioctx;
1467 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1468
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));
1472
1473 uint64_t features = RBD_FEATURES_MUTABLE;
1474 uint64_t mask = RBD_FEATURES_MUTABLE;
1475 ASSERT_EQ(0, set_features(&ioctx, oid, features, mask));
1476
1477 uint64_t actual_features;
1478 ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &actual_features));
1479
1480 uint64_t expected_features = RBD_FEATURES_MUTABLE | base_features;
1481 ASSERT_EQ(expected_features, actual_features);
1482
1483 features = 0;
1484 mask = RBD_FEATURE_OBJECT_MAP;
1485 ASSERT_EQ(0, set_features(&ioctx, oid, features, mask));
1486
1487 ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &actual_features));
1488
1489 expected_features = (RBD_FEATURES_MUTABLE | base_features) &
1490 ~RBD_FEATURE_OBJECT_MAP;
1491 ASSERT_EQ(expected_features, actual_features);
1492
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));
1496
1497 ASSERT_EQ(-EINVAL, set_features(&ioctx, oid, 0, RBD_FEATURE_LAYERING));
1498 }
1499
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);
1504
1505 std::vector<cls::rbd::MirrorPeer> peers;
1506 ASSERT_EQ(-ENOENT, mirror_peer_list(&ioctx, &peers));
1507
1508 std::string uuid;
1509 ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid));
1510 ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client"));
1511
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);
1515
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);
1521
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);
1525
1526 ASSERT_EQ(-EINVAL, mirror_uuid_set(&ioctx, "new-mirror-uuid"));
1527
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);
1531
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));
1541
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);
1549
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"));
1553
1554 ASSERT_EQ(-ENOENT, mirror_peer_set_client(&ioctx, "uuid4", "new client"));
1555 ASSERT_EQ(0, mirror_peer_set_client(&ioctx, "uuid1", "new client"));
1556
1557 ASSERT_EQ(-ENOENT, mirror_peer_set_cluster(&ioctx, "uuid4", "new cluster"));
1558 ASSERT_EQ(0, mirror_peer_set_cluster(&ioctx, "uuid3", "new cluster"));
1559
1560 ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
1561 expected_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));
1566
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);
1572
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));
1577 }
1578
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);
1583
1584 std::map<std::string, std::string> mirror_image_ids;
1585 ASSERT_EQ(-ENOENT, mirror_image_list(&ioctx, "", 0, &mirror_image_ids));
1586
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);
1590
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));
1600
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);
1604
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);
1612
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);
1617
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);
1621
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"));
1625
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);
1629
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"));
1638
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);
1642 }
1643
1644 TEST_F(TestClsRbd, mirror_image_status) {
1645 struct WatchCtx : public librados::WatchCtx2 {
1646 librados::IoCtx *m_ioctx;
1647
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 {
1651 bufferlist bl;
1652 m_ioctx->notify_ack(RBD_MIRRORING, notify_id, cookie, bl);
1653 }
1654 void handle_error(uint64_t cookie, int err) override {}
1655 };
1656
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;
1663
1664 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1665 ioctx.remove(RBD_MIRRORING);
1666
1667 // Test list fails on nonexistent RBD_MIRRORING object
1668
1669 ASSERT_EQ(-ENOENT, mirror_image_status_list(&ioctx, "", 1024, &images,
1670 &statuses));
1671
1672 // Test status set
1673
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);
1677
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));
1681
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);
1685
1686 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1687 images.clear();
1688 statuses.clear();
1689 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1690 ASSERT_EQ(3U, images.size());
1691 ASSERT_EQ(1U, statuses.size());
1692
1693 // Test status is down due to RBD_MIRRORING is not watched
1694
1695 status1.up = false;
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);
1699
1700 // Test status summary. All statuses are unknown due to down.
1701 states.clear();
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]);
1705
1706 // Test remove_down removes stale statuses
1707
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]);
1716
1717 // Test statuses are not down after watcher is started
1718
1719 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1720
1721 WatchCtx watch_ctx(&ioctx);
1722 ASSERT_EQ(0, ioctx.watch2(RBD_MIRRORING, &watch_handle, &watch_ctx));
1723
1724 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid2", status2));
1725 ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid3", status3));
1726
1727 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1728 status1.up = true;
1729 ASSERT_EQ(read_status, status1);
1730 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid2", &read_status));
1731 status2.up = true;
1732 ASSERT_EQ(read_status, status2);
1733 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid3", &read_status));
1734 status3.up = true;
1735 ASSERT_EQ(read_status, status3);
1736
1737 images.clear();
1738 statuses.clear();
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);
1745
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);
1749 images.clear();
1750 statuses.clear();
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);
1757
1758 states.clear();
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]);
1764
1765 // Test update
1766
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);
1772
1773 states.clear();
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]);
1777
1778 // Test remove
1779
1780 ASSERT_EQ(0, mirror_image_status_remove(&ioctx, "uuid3"));
1781 ASSERT_EQ(-ENOENT, mirror_image_status_get(&ioctx, "uuid3", &read_status));
1782 images.clear();
1783 statuses.clear();
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);
1789
1790 states.clear();
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]);
1795
1796 // Test statuses are down after removing watcher
1797
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));
1801
1802 images.clear();
1803 statuses.clear();
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);
1810
1811 ioctx.unwatch2(watch_handle);
1812
1813 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1814 ASSERT_EQ(3U, images.size());
1815 ASSERT_EQ(3U, statuses.size());
1816 status1.up = false;
1817 ASSERT_EQ(statuses["image_id1"], status1);
1818 status2.up = false;
1819 ASSERT_EQ(statuses["image_id2"], status2);
1820 status3.up = false;
1821 ASSERT_EQ(statuses["image_id3"], status3);
1822
1823 ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1824 ASSERT_EQ(read_status, status1);
1825
1826 states.clear();
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]);
1830
1831 ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx));
1832 ASSERT_EQ(-ENOENT, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1833
1834 images.clear();
1835 statuses.clear();
1836 ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1837 ASSERT_EQ(3U, images.size());
1838 ASSERT_TRUE(statuses.empty());
1839
1840 states.clear();
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]);
1844
1845 // Remove images
1846
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;
1850
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));
1854
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"));
1858
1859 states.clear();
1860 ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1861 ASSERT_EQ(0U, states.size());
1862
1863 // Test status list with large number of images
1864
1865 size_t N = 1024;
1866 ASSERT_EQ(0U, N % 2);
1867
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));
1875 }
1876
1877 std::string last_read = "";
1878 images.clear();
1879 statuses.clear();
1880 ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N * 2, &images,
1881 &statuses));
1882 ASSERT_EQ(N, images.size());
1883 ASSERT_EQ(N, statuses.size());
1884
1885 images.clear();
1886 statuses.clear();
1887 ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1888 &statuses));
1889 ASSERT_EQ(N / 2, images.size());
1890 ASSERT_EQ(N / 2, statuses.size());
1891
1892 last_read = images.rbegin()->first;
1893 images.clear();
1894 statuses.clear();
1895 ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1896 &statuses));
1897 ASSERT_EQ(N / 2, images.size());
1898 ASSERT_EQ(N / 2, statuses.size());
1899
1900 last_read = images.rbegin()->first;
1901 images.clear();
1902 statuses.clear();
1903 ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1904 &statuses));
1905 ASSERT_EQ(0U, images.size());
1906 ASSERT_EQ(0U, statuses.size());
1907 }
1908
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);
1913
1914 std::vector<std::string> instance_ids;
1915 ASSERT_EQ(-ENOENT, mirror_instances_list(&ioctx, &instance_ids));
1916
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());
1920
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");
1925
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());
1930
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");
1935
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());
1939 }
1940
1941 TEST_F(TestClsRbd, group_create) {
1942 librados::IoCtx ioctx;
1943 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1944
1945 string group_id = "group_id";
1946 ASSERT_EQ(0, group_create(&ioctx, group_id));
1947
1948 uint64_t psize;
1949 time_t pmtime;
1950 ASSERT_EQ(0, ioctx.stat(group_id, &psize, &pmtime));
1951 }
1952
1953 TEST_F(TestClsRbd, group_dir_list) {
1954 librados::IoCtx ioctx;
1955 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1956
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));
1963
1964 map<string, string> cgs;
1965 ASSERT_EQ(0, group_dir_list(&ioctx, RBD_GROUP_DIRECTORY, "", 10, &cgs));
1966
1967 ASSERT_EQ(2U, cgs.size());
1968
1969 auto it = cgs.begin();
1970 ASSERT_EQ(group_id1, it->second);
1971 ASSERT_EQ(group_name1, it->first);
1972
1973 ++it;
1974 ASSERT_EQ(group_id2, it->second);
1975 ASSERT_EQ(group_name2, it->first);
1976 }
1977
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));
1980
1981 set<string> keys;
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());
1986 }
1987
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);
1992
1993 string group_id = "cgid";
1994 string group_name = "cgname";
1995 add_group_to_dir(ioctx, group_id, group_name);
1996 }
1997
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);
2002
2003 string group_id = "cgidexisting";
2004 string group_name = "cgnameexisting";
2005 add_group_to_dir(ioctx, group_id, group_name);
2006
2007 ASSERT_EQ(-EEXIST, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2008 }
2009
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);
2014
2015 string group_id = "cgidtodel";
2016 string group_name = "cgnametodel";
2017 add_group_to_dir(ioctx, group_id, group_name);
2018
2019 ASSERT_EQ(0, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2020
2021 set<string> keys;
2022 ASSERT_EQ(0, ioctx.omap_get_keys(RBD_GROUP_DIRECTORY, "", 10, &keys));
2023 ASSERT_EQ(0U, keys.size());
2024 }
2025
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);
2030
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
2034 // last two lines.
2035 add_group_to_dir(ioctx, group_id, group_name);
2036
2037 ASSERT_EQ(0, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2038
2039 // Removing missing
2040 ASSERT_EQ(-ENOENT, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2041
2042 set<string> keys;
2043 ASSERT_EQ(0, ioctx.omap_get_keys(RBD_GROUP_DIRECTORY, "", 10, &keys));
2044 ASSERT_EQ(0U, keys.size());
2045 }
2046
2047 void test_image_add(librados::IoCtx &ioctx, const string& group_id,
2048 const string& image_id, int64_t pool_id) {
2049
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));
2053
2054 set<string> keys;
2055 ASSERT_EQ(0, ioctx.omap_get_keys(group_id, "", 10, &keys));
2056
2057 auto it = keys.begin();
2058 ASSERT_EQ(2U, keys.size());
2059
2060 string image_key = cls::rbd::GroupImageSpec(image_id, pool_id).image_key();
2061 ASSERT_EQ(image_key, *it);
2062 ++it;
2063 ASSERT_EQ("snap_seq", *it);
2064 }
2065
2066 TEST_F(TestClsRbd, group_image_add) {
2067 librados::IoCtx ioctx;
2068 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2069
2070 string group_id = "group_id";
2071 ASSERT_EQ(0, group_create(&ioctx, group_id));
2072
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);
2076 }
2077
2078 TEST_F(TestClsRbd, group_image_remove) {
2079 librados::IoCtx ioctx;
2080 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2081
2082 string group_id = "group_id";
2083 ASSERT_EQ(0, group_create(&ioctx, group_id));
2084
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);
2088
2089 cls::rbd::GroupImageSpec spec(image_id, pool_id);
2090 ASSERT_EQ(0, group_image_remove(&ioctx, group_id, spec));
2091 set<string> keys;
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()));
2095 }
2096
2097 TEST_F(TestClsRbd, group_image_list) {
2098 librados::IoCtx ioctx;
2099 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2100
2101 string group_id = "group_id";
2102 ASSERT_EQ(0, group_create(&ioctx, group_id));
2103
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);
2107
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,
2111 &images));
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);
2116
2117 cls::rbd::GroupImageStatus last_image = *images.rbegin();
2118 ASSERT_EQ(0, group_image_list(&ioctx, group_id, last_image.spec, 1024,
2119 &images));
2120 ASSERT_EQ(0U, images.size());
2121 }
2122
2123 TEST_F(TestClsRbd, group_image_clean) {
2124 librados::IoCtx ioctx;
2125 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2126
2127 string group_id = "group_id1";
2128 ASSERT_EQ(0, group_create(&ioctx, group_id));
2129
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);
2133
2134 cls::rbd::GroupImageStatus incomplete_st(image_id, pool_id,
2135 cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE);
2136
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));
2143
2144 string image_key = cls::rbd::GroupImageSpec(image_id, pool_id).image_key();
2145
2146 map<string, bufferlist> vals;
2147 ASSERT_EQ(0, ioctx.omap_get_vals(group_id, "", 10, &vals));
2148
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);
2153 }
2154
2155 TEST_F(TestClsRbd, image_add_group) {
2156 librados::IoCtx ioctx;
2157 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2158
2159 int64_t pool_id = ioctx.get_id();
2160 string image_id = "imageid";
2161
2162 ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2163 RBD_FEATURE_LAYERING, image_id, -1));
2164
2165 string group_id = "group_id";
2166
2167 cls::rbd::GroupSpec spec(group_id, pool_id);
2168 ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec));
2169
2170 map<string, bufferlist> vals;
2171 ASSERT_EQ(0, ioctx.omap_get_vals(image_id, "", RBD_GROUP_REF, 10, &vals));
2172
2173 cls::rbd::GroupSpec val_spec;
2174 bufferlist::iterator it = vals[RBD_GROUP_REF].begin();
2175 ::decode(val_spec, it);
2176
2177 ASSERT_EQ(group_id, val_spec.group_id);
2178 ASSERT_EQ(pool_id, val_spec.pool_id);
2179 }
2180
2181 TEST_F(TestClsRbd, image_remove_group) {
2182 librados::IoCtx ioctx;
2183 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2184
2185 int64_t pool_id = ioctx.get_id();
2186 string image_id = "image_id";
2187
2188 ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2189 RBD_FEATURE_LAYERING, image_id, -1));
2190
2191 string group_id = "group_id";
2192
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
2196 // does something.
2197 ASSERT_EQ(0, image_remove_group(&ioctx, image_id, spec));
2198
2199 map<string, bufferlist> vals;
2200 ASSERT_EQ(0, ioctx.omap_get_vals(image_id, "", RBD_GROUP_REF, 10, &vals));
2201
2202 ASSERT_EQ(0U, vals.size());
2203 }
2204
2205 TEST_F(TestClsRbd, image_get_group) {
2206 librados::IoCtx ioctx;
2207 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2208
2209 int64_t pool_id = ioctx.get_id();
2210 string image_id = "imageidgroupspec";
2211
2212 ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2213 RBD_FEATURE_LAYERING, image_id, -1));
2214
2215 string group_id = "group_id_get_group_spec";
2216
2217 cls::rbd::GroupSpec spec_add(group_id, pool_id);
2218 ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec_add));
2219
2220 cls::rbd::GroupSpec spec;
2221 ASSERT_EQ(0, image_get_group(&ioctx, image_id, &spec));
2222
2223 ASSERT_EQ(group_id, spec.group_id);
2224 ASSERT_EQ(pool_id, spec.pool_id);
2225 }
2226
2227 TEST_F(TestClsRbd, trash_methods)
2228 {
2229 librados::IoCtx ioctx;
2230 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2231
2232 string id = "123456789";
2233 string id2 = "123456780";
2234
2235 std::map<string, cls::rbd::TrashImageSpec> entries;
2236 ASSERT_EQ(-ENOENT, trash_list(&ioctx, &entries));
2237
2238 utime_t now1 = ceph_clock_now();
2239 utime_t now1_delay = now1;
2240 now1_delay += 380;
2241 cls::rbd::TrashImageSpec trash_spec(cls::rbd::TRASH_IMAGE_SOURCE_USER, "name",
2242 now1, now1_delay);
2243 ASSERT_EQ(0, trash_add(&ioctx, id, trash_spec));
2244
2245 utime_t now2 = ceph_clock_now();
2246 utime_t now2_delay = now2;
2247 now2_delay += 480;
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));
2251
2252 ASSERT_EQ(0, trash_remove(&ioctx, id));
2253 ASSERT_EQ(-ENOENT, trash_remove(&ioctx, id));
2254
2255 ASSERT_EQ(0, trash_list(&ioctx, &entries));
2256 ASSERT_TRUE(entries.empty());
2257
2258 ASSERT_EQ(0, trash_add(&ioctx, id, trash_spec2));
2259 ASSERT_EQ(0, trash_add(&ioctx, id2, trash_spec));
2260
2261 ASSERT_EQ(0, trash_list(&ioctx, &entries));
2262
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);
2274 }
2275 }
2276
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));
2281
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);
2285
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);
2289
2290 ioctx.close();
2291 }
2292