Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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(static_cast<uint64_t>(RBD_FEATURES_ALL),
104             static_cast<uint64_t>(all_features & RBD_FEATURES_ALL));
105
106   ioctx.close();
107 }
108
109 TEST_F(TestClsRbd, copyup)
110 {
111   librados::IoCtx ioctx;
112   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
113
114   string oid = get_temp_image_name();
115   bufferlist inbl, outbl;
116
117   // copyup of 0-len nonexistent object should create new 0-len object
118   ioctx.remove(oid);
119   ASSERT_EQ(0, copyup(&ioctx, oid, inbl));
120   uint64_t size;
121   ASSERT_EQ(0, ioctx.stat(oid, &size, NULL));
122   ASSERT_EQ(0U, size);
123
124   // create some random data to write
125   size_t l = 4 << 20;
126   char *b = random_buf(l);
127   inbl.append(b, l);
128   delete [] b;
129   ASSERT_EQ(l, inbl.length());
130
131   // copyup to nonexistent object should create new object
132   ioctx.remove(oid);
133   ASSERT_EQ(-ENOENT, ioctx.remove(oid));
134   ASSERT_EQ(0, copyup(&ioctx, oid, inbl));
135   // and its contents should match
136   ASSERT_EQ(l, (size_t)ioctx.read(oid, outbl, l, 0));
137   ASSERT_TRUE(outbl.contents_equal(inbl));
138
139   // now send different data, but with a preexisting object
140   bufferlist inbl2;
141   b = random_buf(l);
142   inbl2.append(b, l);
143   delete [] b;
144   ASSERT_EQ(l, inbl2.length());
145
146   // should still succeed
147   ASSERT_EQ(0, copyup(&ioctx, oid, inbl));
148   ASSERT_EQ(l, (size_t)ioctx.read(oid, outbl, l, 0));
149   // but contents should not have changed
150   ASSERT_FALSE(outbl.contents_equal(inbl2));
151   ASSERT_TRUE(outbl.contents_equal(inbl));
152
153   ASSERT_EQ(0, ioctx.remove(oid));
154   ioctx.close();
155 }
156
157 TEST_F(TestClsRbd, get_and_set_id)
158 {
159   librados::IoCtx ioctx;
160   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
161
162   string oid = get_temp_image_name();
163   string id;
164   string valid_id = "0123abcxyzZYXCBA";
165   string invalid_id = ".abc";
166   string empty_id;
167
168   ASSERT_EQ(-ENOENT, get_id(&ioctx, oid, &id));
169   ASSERT_EQ(-ENOENT, set_id(&ioctx, oid, valid_id));
170
171   ASSERT_EQ(0, ioctx.create(oid, true));
172   ASSERT_EQ(-EINVAL, set_id(&ioctx, oid, invalid_id));
173   ASSERT_EQ(-EINVAL, set_id(&ioctx, oid, empty_id));
174   ASSERT_EQ(-ENOENT, get_id(&ioctx, oid, &id));
175
176   ASSERT_EQ(0, set_id(&ioctx, oid, valid_id));
177   ASSERT_EQ(-EEXIST, set_id(&ioctx, oid, valid_id));
178   ASSERT_EQ(-EEXIST, set_id(&ioctx, oid, valid_id + valid_id));
179   ASSERT_EQ(0, get_id(&ioctx, oid, &id));
180   ASSERT_EQ(id, valid_id);
181
182   ioctx.close();
183 }
184
185 TEST_F(TestClsRbd, add_remove_child)
186 {
187   librados::IoCtx ioctx;
188   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
189
190   string oid = get_temp_image_name();
191   ASSERT_EQ(0, ioctx.create(oid, true));
192
193   string snapname = "parent_snap";
194   snapid_t snapid(10);
195   string parent_image = "parent_id";
196   set<string>children;
197   ParentSpec pspec(ioctx.get_id(), parent_image, snapid);
198
199   // nonexistent children cannot be listed or removed
200   ASSERT_EQ(-ENOENT, get_children(&ioctx, oid, pspec, children));
201   ASSERT_EQ(-ENOENT, remove_child(&ioctx, oid, pspec, "child1"));
202
203   // create the parent and snapshot
204   ASSERT_EQ(0, create_image(&ioctx, parent_image, 2<<20, 0,
205                             RBD_FEATURE_LAYERING, parent_image, -1));
206   ASSERT_EQ(0, snapshot_add(&ioctx, parent_image, snapid, snapname));
207
208   // add child to it, verify it showed up
209   ASSERT_EQ(0, add_child(&ioctx, oid, pspec, "child1"));
210   ASSERT_EQ(0, get_children(&ioctx, oid, pspec, children));
211   ASSERT_TRUE(children.find("child1") != children.end());
212   // add another child to it, verify it showed up
213   ASSERT_EQ(0, add_child(&ioctx, oid, pspec, "child2"));
214   ASSERT_EQ(0, get_children(&ioctx, oid, pspec, children));
215   ASSERT_TRUE(children.find("child2") != children.end());
216   // add child2 again, expect -EEXIST
217   ASSERT_EQ(-EEXIST, add_child(&ioctx, oid, pspec, "child2"));
218   // remove first, verify it's gone
219   ASSERT_EQ(0, remove_child(&ioctx, oid, pspec, "child1"));
220   ASSERT_EQ(0, get_children(&ioctx, oid, pspec, children));
221   ASSERT_FALSE(children.find("child1") != children.end());
222   // remove second, verify list empty
223   ASSERT_EQ(0, remove_child(&ioctx, oid, pspec, "child2"));
224   ASSERT_EQ(-ENOENT, get_children(&ioctx, oid, pspec, children));
225   // try to remove again, validate -ENOENT to that as well
226   ASSERT_EQ(-ENOENT, remove_child(&ioctx, oid, pspec, "child2"));
227
228   ioctx.close();
229 }
230
231 TEST_F(TestClsRbd, directory_methods)
232 {
233   librados::IoCtx ioctx;
234   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
235
236   string oid = get_temp_image_name();
237   string id, name;
238   string imgname = get_temp_image_name();
239   string imgname2 = get_temp_image_name();
240   string imgname3 = get_temp_image_name();
241   string valid_id = "0123abcxyzZYXCBA";
242   string valid_id2 = "5";
243   string invalid_id = ".abc";
244   string empty;
245
246   ASSERT_EQ(-ENOENT, dir_get_id(&ioctx, oid, imgname, &id));
247   ASSERT_EQ(-ENOENT, dir_get_name(&ioctx, oid, valid_id, &name));
248   ASSERT_EQ(-ENOENT, dir_remove_image(&ioctx, oid, imgname, valid_id));
249
250   ASSERT_EQ(-EINVAL, dir_add_image(&ioctx, oid, imgname, invalid_id));
251   ASSERT_EQ(-EINVAL, dir_add_image(&ioctx, oid, imgname, empty));
252   ASSERT_EQ(-EINVAL, dir_add_image(&ioctx, oid, empty, valid_id));
253
254   map<string, string> images;
255   ASSERT_EQ(-ENOENT, dir_list(&ioctx, oid, "", 30, &images));
256
257   ASSERT_EQ(0, ioctx.create(oid, true));
258   ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
259   ASSERT_EQ(0u, images.size());
260   ASSERT_EQ(0, ioctx.remove(oid));
261
262   ASSERT_EQ(0, dir_add_image(&ioctx, oid, imgname, valid_id));
263   ASSERT_EQ(-EEXIST, dir_add_image(&ioctx, oid, imgname, valid_id2));
264   ASSERT_EQ(-EBADF, dir_add_image(&ioctx, oid, imgname2, valid_id));
265   ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
266   ASSERT_EQ(1u, images.size());
267   ASSERT_EQ(valid_id, images[imgname]);
268   ASSERT_EQ(0, dir_list(&ioctx, oid, "", 0, &images));
269   ASSERT_EQ(0u, images.size());
270   ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id, &name));
271   ASSERT_EQ(imgname, name);
272   ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname, &id));
273   ASSERT_EQ(valid_id, id);
274
275   ASSERT_EQ(0, dir_add_image(&ioctx, oid, imgname2, valid_id2));
276   ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
277   ASSERT_EQ(2u, images.size());
278   ASSERT_EQ(valid_id, images[imgname]);
279   ASSERT_EQ(valid_id2, images[imgname2]);
280   ASSERT_EQ(0, dir_list(&ioctx, oid, imgname, 0, &images));
281   ASSERT_EQ(0u, images.size());
282   ASSERT_EQ(0, dir_list(&ioctx, oid, imgname, 2, &images));
283   ASSERT_EQ(1u, images.size());
284   ASSERT_EQ(valid_id2, images[imgname2]);
285   ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id2, &name));
286   ASSERT_EQ(imgname2, name);
287   ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname2, &id));
288   ASSERT_EQ(valid_id2, id);
289
290   librados::ObjectWriteOperation op1;
291   dir_rename_image(&op1, imgname, imgname2, valid_id2);
292   ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op1));
293   ASSERT_EQ(-ESTALE, dir_remove_image(&ioctx, oid, imgname, valid_id2));
294   librados::ObjectWriteOperation op2;
295   dir_rename_image(&op2, imgname, imgname2, valid_id);
296   ASSERT_EQ(-EEXIST, ioctx.operate(oid, &op2));
297   ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname, &id));
298   ASSERT_EQ(valid_id, id);
299   ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id2, &name));
300   ASSERT_EQ(imgname2, name);
301
302   librados::ObjectWriteOperation op3;
303   dir_rename_image(&op3, imgname, imgname3, valid_id);
304   ASSERT_EQ(0, ioctx.operate(oid, &op3));
305   ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname3, &id));
306   ASSERT_EQ(valid_id, id);
307   ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id, &name));
308   ASSERT_EQ(imgname3, name);
309   librados::ObjectWriteOperation op4;
310   dir_rename_image(&op4, imgname3, imgname, valid_id);
311   ASSERT_EQ(0, ioctx.operate(oid, &op4));
312
313   ASSERT_EQ(0, dir_remove_image(&ioctx, oid, imgname, valid_id));
314   ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
315   ASSERT_EQ(1u, images.size());
316   ASSERT_EQ(valid_id2, images[imgname2]);
317   ASSERT_EQ(0, dir_list(&ioctx, oid, imgname2, 30, &images));
318   ASSERT_EQ(0u, images.size());
319   ASSERT_EQ(0, dir_get_name(&ioctx, oid, valid_id2, &name));
320   ASSERT_EQ(imgname2, name);
321   ASSERT_EQ(0, dir_get_id(&ioctx, oid, imgname2, &id));
322   ASSERT_EQ(valid_id2, id);
323   ASSERT_EQ(-ENOENT, dir_get_name(&ioctx, oid, valid_id, &name));
324   ASSERT_EQ(-ENOENT, dir_get_id(&ioctx, oid, imgname, &id));
325
326   ASSERT_EQ(0, dir_add_image(&ioctx, oid, imgname, valid_id));
327   ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
328   ASSERT_EQ(2u, images.size());
329   ASSERT_EQ(valid_id, images[imgname]);
330   ASSERT_EQ(valid_id2, images[imgname2]);
331   ASSERT_EQ(0, dir_remove_image(&ioctx, oid, imgname, valid_id));
332   ASSERT_EQ(-ENOENT, dir_remove_image(&ioctx, oid, imgname, valid_id));
333   ASSERT_EQ(0, dir_remove_image(&ioctx, oid, imgname2, valid_id2));
334   ASSERT_EQ(0, dir_list(&ioctx, oid, "", 30, &images));
335   ASSERT_EQ(0u, images.size());
336
337   ioctx.close();
338 }
339
340 TEST_F(TestClsRbd, create)
341 {
342   librados::IoCtx ioctx;
343   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
344
345   string oid = get_temp_image_name();
346   uint64_t size = 20ULL << 30;
347   uint64_t features = 0;
348   uint8_t order = 22;
349   string object_prefix = oid;
350
351   ASSERT_EQ(0, create_image(&ioctx, oid, size, order,
352                             features, object_prefix, -1));
353   ASSERT_EQ(-EEXIST, create_image(&ioctx, oid, size, order,
354                                   features, object_prefix, -1));
355   ASSERT_EQ(0, ioctx.remove(oid));
356
357   ASSERT_EQ(-EINVAL, create_image(&ioctx, oid, size, order,
358                                   features, "", -1));
359   ASSERT_EQ(-ENOENT, ioctx.remove(oid));
360
361   ASSERT_EQ(0, create_image(&ioctx, oid, 0, order,
362                             features, object_prefix, -1));
363   ASSERT_EQ(0, ioctx.remove(oid));
364
365   ASSERT_EQ(-ENOSYS, create_image(&ioctx, oid, size, order,
366                                   -1, object_prefix, -1));
367   ASSERT_EQ(-ENOENT, ioctx.remove(oid));
368
369   ASSERT_EQ(0, create_image(&ioctx, oid, size, order, RBD_FEATURE_DATA_POOL,
370                             object_prefix, 123));
371   ASSERT_EQ(0, ioctx.remove(oid));
372   ASSERT_EQ(-EINVAL, create_image(&ioctx, oid, size, order,
373                                   RBD_FEATURE_DATA_POOL, object_prefix, -1));
374   ASSERT_EQ(-EINVAL, create_image(&ioctx, oid, size, order, 0, object_prefix,
375                                   123));
376
377   bufferlist inbl, outbl;
378   ASSERT_EQ(-EINVAL, ioctx.exec(oid, "rbd", "create", inbl, outbl));
379
380   ioctx.close();
381 }
382
383 TEST_F(TestClsRbd, get_features)
384 {
385   librados::IoCtx ioctx;
386   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
387
388   string oid = get_temp_image_name();
389
390   uint64_t features;
391   ASSERT_EQ(-ENOENT, get_features(&ioctx, oid, CEPH_NOSNAP, &features));
392
393   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
394   ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &features));
395   ASSERT_EQ(0u, features);
396
397   int r = get_features(&ioctx, oid, 1, &features);
398   if (r == 0) {
399     ASSERT_EQ(0u, features);
400   } else {
401     // deprecated snapshot handling
402     ASSERT_EQ(-ENOENT, r);
403   }
404
405   ioctx.close();
406 }
407
408 TEST_F(TestClsRbd, get_object_prefix)
409 {
410   librados::IoCtx ioctx;
411   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
412
413   string oid = get_temp_image_name();
414
415   string object_prefix;
416   ASSERT_EQ(-ENOENT, get_object_prefix(&ioctx, oid, &object_prefix));
417
418   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
419   ASSERT_EQ(0, get_object_prefix(&ioctx, oid, &object_prefix));
420   ASSERT_EQ(oid, object_prefix);
421
422   ioctx.close();
423 }
424
425 TEST_F(TestClsRbd, get_create_timestamp)
426 {
427   librados::IoCtx ioctx;
428   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
429
430   string oid = get_temp_image_name();
431   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
432
433   utime_t timestamp;
434   ASSERT_EQ(0, get_create_timestamp(&ioctx, oid, &timestamp));
435   ASSERT_LT(0U, timestamp.tv.tv_sec);
436
437   ioctx.close();
438 }
439
440 TEST_F(TestClsRbd, get_data_pool)
441 {
442   librados::IoCtx ioctx;
443   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
444
445   string oid = get_temp_image_name();
446
447   int64_t data_pool_id;
448   ASSERT_EQ(0, ioctx.create(oid, true));
449   ASSERT_EQ(0, get_data_pool(&ioctx, oid, &data_pool_id));
450   ASSERT_EQ(-1, data_pool_id);
451   ASSERT_EQ(0, ioctx.remove(oid));
452
453   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, RBD_FEATURE_DATA_POOL, oid,
454                             12));
455   ASSERT_EQ(0, get_data_pool(&ioctx, oid, &data_pool_id));
456   ASSERT_EQ(12, data_pool_id);
457 }
458
459 TEST_F(TestClsRbd, get_size)
460 {
461   librados::IoCtx ioctx;
462   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
463
464   string oid = get_temp_image_name();
465   uint64_t size;
466   uint8_t order;
467   ASSERT_EQ(-ENOENT, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
468
469   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
470   ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
471   ASSERT_EQ(0u, size);
472   ASSERT_EQ(22, order);
473   ASSERT_EQ(0, ioctx.remove(oid));
474
475   ASSERT_EQ(0, create_image(&ioctx, oid, 2 << 22, 0, 0, oid, -1));
476   ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
477   ASSERT_EQ(2u << 22, size);
478   ASSERT_EQ(0, order);
479
480   ASSERT_EQ(-ENOENT, get_size(&ioctx, oid, 1, &size, &order));
481
482   ioctx.close();
483 }
484
485 TEST_F(TestClsRbd, set_size)
486 {
487   librados::IoCtx ioctx;
488   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
489
490   string oid = get_temp_image_name();
491   ASSERT_EQ(-ENOENT, set_size(&ioctx, oid, 5));
492
493   uint64_t size;
494   uint8_t order;
495   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
496   ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
497   ASSERT_EQ(0u, size);
498   ASSERT_EQ(22, order);
499
500   ASSERT_EQ(0, set_size(&ioctx, oid, 0));
501   ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
502   ASSERT_EQ(0u, size);
503   ASSERT_EQ(22, order);
504
505   ASSERT_EQ(0, set_size(&ioctx, oid, 3 << 22));
506   ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
507   ASSERT_EQ(3u << 22, size);
508   ASSERT_EQ(22, order);
509
510   ioctx.close();
511 }
512
513 TEST_F(TestClsRbd, protection_status)
514 {
515   librados::IoCtx ioctx;
516   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
517
518   string oid = get_temp_image_name();
519   string oid2 = get_temp_image_name();
520   uint8_t status = RBD_PROTECTION_STATUS_UNPROTECTED;
521   ASSERT_EQ(-ENOENT, get_protection_status(&ioctx, oid,
522                                            CEPH_NOSNAP, &status));
523   ASSERT_EQ(-ENOENT, set_protection_status(&ioctx, oid,
524                                            CEPH_NOSNAP, status));
525
526   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, RBD_FEATURE_LAYERING, oid, -1));
527   ASSERT_EQ(0, create_image(&ioctx, oid2, 0, 22, 0, oid, -1));
528   ASSERT_EQ(-EINVAL, get_protection_status(&ioctx, oid2,
529                                            CEPH_NOSNAP, &status));
530   ASSERT_EQ(-ENOEXEC, set_protection_status(&ioctx, oid2,
531                                            CEPH_NOSNAP, status));
532   ASSERT_EQ(-EINVAL, get_protection_status(&ioctx, oid,
533                                            CEPH_NOSNAP, &status));
534   ASSERT_EQ(-EINVAL, set_protection_status(&ioctx, oid,
535                                            CEPH_NOSNAP, status));
536   ASSERT_EQ(-ENOENT, get_protection_status(&ioctx, oid,
537                                            2, &status));
538   ASSERT_EQ(-ENOENT, set_protection_status(&ioctx, oid,
539                                            2, status));
540
541   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 10, "snap1"));
542   ASSERT_EQ(0, get_protection_status(&ioctx, oid,
543                                      10, &status));
544   ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED, status);
545
546   ASSERT_EQ(0, set_protection_status(&ioctx, oid,
547                                      10, RBD_PROTECTION_STATUS_PROTECTED));
548   ASSERT_EQ(0, get_protection_status(&ioctx, oid,
549                                      10, &status));
550   ASSERT_EQ(+RBD_PROTECTION_STATUS_PROTECTED, status);
551   ASSERT_EQ(-EBUSY, snapshot_remove(&ioctx, oid, 10));
552
553   ASSERT_EQ(0, set_protection_status(&ioctx, oid,
554                                      10, RBD_PROTECTION_STATUS_UNPROTECTING));
555   ASSERT_EQ(0, get_protection_status(&ioctx, oid,
556                                      10, &status));
557   ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTING, status);
558   ASSERT_EQ(-EBUSY, snapshot_remove(&ioctx, oid, 10));
559
560   ASSERT_EQ(-EINVAL, set_protection_status(&ioctx, oid,
561                                            10, RBD_PROTECTION_STATUS_LAST));
562   ASSERT_EQ(0, get_protection_status(&ioctx, oid,
563                                      10, &status));
564   ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTING, status);
565
566   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 20, "snap2"));
567   ASSERT_EQ(0, get_protection_status(&ioctx, oid,
568                                      20, &status));
569   ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED, status);
570   ASSERT_EQ(0, set_protection_status(&ioctx, oid,
571                                      10, RBD_PROTECTION_STATUS_UNPROTECTED));
572   ASSERT_EQ(0, get_protection_status(&ioctx, oid,
573                                      10, &status));
574   ASSERT_EQ(+RBD_PROTECTION_STATUS_UNPROTECTED, status);
575
576   ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 10));
577   ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 20));
578
579   ioctx.close();
580 }
581
582 TEST_F(TestClsRbd, snapshot_limits)
583 {
584   librados::IoCtx ioctx;
585   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
586
587   librados::ObjectWriteOperation op;
588   string oid = get_temp_image_name();
589   uint64_t limit;
590
591   ASSERT_EQ(-ENOENT, snapshot_get_limit(&ioctx, oid, &limit));
592
593   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, RBD_FEATURE_LAYERING, oid, -1));
594
595   snapshot_set_limit(&op, 2);
596
597   ASSERT_EQ(0, ioctx.operate(oid, &op));
598
599   ASSERT_EQ(0, snapshot_get_limit(&ioctx, oid, &limit));
600   ASSERT_EQ(2U, limit);
601
602   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 10, "snap1"));
603   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 20, "snap2"));
604   ASSERT_EQ(-EDQUOT, snapshot_add(&ioctx, oid, 30, "snap3"));
605
606   ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 10));
607   ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 20));
608
609   ioctx.close();
610 }
611
612 TEST_F(TestClsRbd, parents)
613 {
614   librados::IoCtx ioctx;
615   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
616
617   string oid = get_temp_image_name();
618   ParentSpec pspec;
619   uint64_t size;
620
621   ASSERT_EQ(-ENOENT, get_parent(&ioctx, "doesnotexist", CEPH_NOSNAP, &pspec, &size));
622
623   // old image should fail
624   ASSERT_EQ(0, create_image(&ioctx, "old", 33<<20, 22, 0, "old_blk.", -1));
625   // get nonexistent parent: succeed, return (-1, "", CEPH_NOSNAP), overlap 0
626   ASSERT_EQ(0, get_parent(&ioctx, "old", CEPH_NOSNAP, &pspec, &size));
627   ASSERT_EQ(pspec.pool_id, -1);
628   ASSERT_STREQ("", pspec.image_id.c_str());
629   ASSERT_EQ(pspec.snap_id, CEPH_NOSNAP);
630   ASSERT_EQ(size, 0ULL);
631   pspec = ParentSpec(-1, "parent", 3);
632   ASSERT_EQ(-ENOEXEC, set_parent(&ioctx, "old", ParentSpec(-1, "parent", 3), 10<<20));
633   ASSERT_EQ(-ENOEXEC, remove_parent(&ioctx, "old"));
634
635   // new image will work
636   ASSERT_EQ(0, create_image(&ioctx, oid, 33<<20, 22, RBD_FEATURE_LAYERING,
637                             "foo.", -1));
638
639   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
640   ASSERT_EQ(-1, pspec.pool_id);
641   ASSERT_EQ(0, get_parent(&ioctx, oid, 123, &pspec, &size));
642   ASSERT_EQ(-1, pspec.pool_id);
643
644   ASSERT_EQ(-EINVAL, set_parent(&ioctx, oid, ParentSpec(-1, "parent", 3), 10<<20));
645   ASSERT_EQ(-EINVAL, set_parent(&ioctx, oid, ParentSpec(1, "", 3), 10<<20));
646   ASSERT_EQ(-EINVAL, set_parent(&ioctx, oid, ParentSpec(1, "parent", CEPH_NOSNAP), 10<<20));
647   ASSERT_EQ(-EINVAL, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 0));
648
649   pspec = ParentSpec(1, "parent", 3);
650   ASSERT_EQ(0, set_parent(&ioctx, oid, pspec, 10<<20));
651   ASSERT_EQ(-EEXIST, set_parent(&ioctx, oid, pspec, 10<<20));
652   ASSERT_EQ(-EEXIST, set_parent(&ioctx, oid, ParentSpec(2, "parent", 34), 10<<20));
653
654   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
655   ASSERT_EQ(pspec.pool_id, 1);
656   ASSERT_EQ(pspec.image_id, "parent");
657   ASSERT_EQ(pspec.snap_id, snapid_t(3));
658
659   ASSERT_EQ(0, remove_parent(&ioctx, oid));
660   ASSERT_EQ(-ENOENT, remove_parent(&ioctx, oid));
661   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
662   ASSERT_EQ(-1, pspec.pool_id);
663
664   // snapshots
665   ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 10<<20));
666   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 10, "snap1"));
667   ASSERT_EQ(0, get_parent(&ioctx, oid, 10, &pspec, &size));
668   ASSERT_EQ(pspec.pool_id, 1);
669   ASSERT_EQ(pspec.image_id, "parent");
670   ASSERT_EQ(pspec.snap_id, snapid_t(3));
671   ASSERT_EQ(size, 10ull<<20);
672
673   ASSERT_EQ(0, remove_parent(&ioctx, oid));
674   ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(4, "parent2", 6), 5<<20));
675   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 11, "snap2"));
676   ASSERT_EQ(0, get_parent(&ioctx, oid, 10, &pspec, &size));
677   ASSERT_EQ(pspec.pool_id, 1);
678   ASSERT_EQ(pspec.image_id, "parent");
679   ASSERT_EQ(pspec.snap_id, snapid_t(3));
680   ASSERT_EQ(size, 10ull<<20);
681   ASSERT_EQ(0, get_parent(&ioctx, oid, 11, &pspec, &size));
682   ASSERT_EQ(pspec.pool_id, 4);
683   ASSERT_EQ(pspec.image_id, "parent2");
684   ASSERT_EQ(pspec.snap_id, snapid_t(6));
685   ASSERT_EQ(size, 5ull<<20);
686
687   ASSERT_EQ(0, remove_parent(&ioctx, oid));
688   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 12, "snap3"));
689   ASSERT_EQ(0, get_parent(&ioctx, oid, 10, &pspec, &size));
690   ASSERT_EQ(pspec.pool_id, 1);
691   ASSERT_EQ(pspec.image_id, "parent");
692   ASSERT_EQ(pspec.snap_id, snapid_t(3));
693   ASSERT_EQ(size, 10ull<<20);
694   ASSERT_EQ(0, get_parent(&ioctx, oid, 11, &pspec, &size));
695   ASSERT_EQ(pspec.pool_id, 4);
696   ASSERT_EQ(pspec.image_id, "parent2");
697   ASSERT_EQ(pspec.snap_id, snapid_t(6));
698   ASSERT_EQ(size, 5ull<<20);
699   ASSERT_EQ(0, get_parent(&ioctx, oid, 12, &pspec, &size));
700   ASSERT_EQ(-1, pspec.pool_id);
701
702   // make sure set_parent takes min of our size and parent's size
703   ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 1<<20));
704   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
705   ASSERT_EQ(pspec.pool_id, 1);
706   ASSERT_EQ(pspec.image_id, "parent");
707   ASSERT_EQ(pspec.snap_id, snapid_t(3));
708   ASSERT_EQ(size, 1ull<<20);
709   ASSERT_EQ(0, remove_parent(&ioctx, oid));
710
711   ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 100<<20));
712   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
713   ASSERT_EQ(pspec.pool_id, 1);
714   ASSERT_EQ(pspec.image_id, "parent");
715   ASSERT_EQ(pspec.snap_id, snapid_t(3));
716   ASSERT_EQ(size, 33ull<<20);
717   ASSERT_EQ(0, remove_parent(&ioctx, oid));
718
719   // make sure resize adjust parent overlap
720   ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 10<<20));
721
722   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 14, "snap4"));
723   ASSERT_EQ(0, set_size(&ioctx, oid, 3 << 20));
724   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
725   ASSERT_EQ(pspec.pool_id, 1);
726   ASSERT_EQ(pspec.image_id, "parent");
727   ASSERT_EQ(pspec.snap_id, snapid_t(3));
728   ASSERT_EQ(size, 3ull<<20);
729   ASSERT_EQ(0, get_parent(&ioctx, oid, 14, &pspec, &size));
730   ASSERT_EQ(pspec.pool_id, 1);
731   ASSERT_EQ(pspec.image_id, "parent");
732   ASSERT_EQ(pspec.snap_id, snapid_t(3));
733   ASSERT_EQ(size, 10ull<<20);
734
735   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 15, "snap5"));
736   ASSERT_EQ(0, set_size(&ioctx, oid, 30 << 20));
737   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
738   ASSERT_EQ(pspec.pool_id, 1);
739   ASSERT_EQ(pspec.image_id, "parent");
740   ASSERT_EQ(pspec.snap_id, snapid_t(3));
741   ASSERT_EQ(size, 3ull<<20);
742   ASSERT_EQ(0, get_parent(&ioctx, oid, 14, &pspec, &size));
743   ASSERT_EQ(pspec.pool_id, 1);
744   ASSERT_EQ(pspec.image_id, "parent");
745   ASSERT_EQ(pspec.snap_id, snapid_t(3));
746   ASSERT_EQ(size, 10ull<<20);
747   ASSERT_EQ(0, get_parent(&ioctx, oid, 15, &pspec, &size));
748   ASSERT_EQ(pspec.pool_id, 1);
749   ASSERT_EQ(pspec.image_id, "parent");
750   ASSERT_EQ(pspec.snap_id, snapid_t(3));
751   ASSERT_EQ(size, 3ull<<20);
752
753   ASSERT_EQ(0, set_size(&ioctx, oid, 2 << 20));
754   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
755   ASSERT_EQ(pspec.pool_id, 1);
756   ASSERT_EQ(pspec.image_id, "parent");
757   ASSERT_EQ(pspec.snap_id, snapid_t(3));
758   ASSERT_EQ(size, 2ull<<20);
759
760   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 16, "snap6"));
761   ASSERT_EQ(0, get_parent(&ioctx, oid, 16, &pspec, &size));
762   ASSERT_EQ(pspec.pool_id, 1);
763   ASSERT_EQ(pspec.image_id, "parent");
764   ASSERT_EQ(pspec.snap_id, snapid_t(3));
765   ASSERT_EQ(size, 2ull<<20);
766
767   ASSERT_EQ(0, ioctx.remove(oid));
768   ASSERT_EQ(0, create_image(&ioctx, oid, 33<<20, 22,
769                             RBD_FEATURE_LAYERING | RBD_FEATURE_DEEP_FLATTEN,
770                             "foo.", -1));
771   ASSERT_EQ(0, set_parent(&ioctx, oid, ParentSpec(1, "parent", 3), 100<<20));
772   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 1, "snap1"));
773   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 2, "snap2"));
774   ASSERT_EQ(0, remove_parent(&ioctx, oid));
775
776   ASSERT_EQ(0, get_parent(&ioctx, oid, 1, &pspec, &size));
777   ASSERT_EQ(-1, pspec.pool_id);
778   ASSERT_EQ(0, get_parent(&ioctx, oid, 2, &pspec, &size));
779   ASSERT_EQ(-1, pspec.pool_id);
780   ASSERT_EQ(0, get_parent(&ioctx, oid, CEPH_NOSNAP, &pspec, &size));
781   ASSERT_EQ(-1, pspec.pool_id);
782
783   ioctx.close();
784 }
785
786 TEST_F(TestClsRbd, snapshots)
787 {
788   cls::rbd::SnapshotNamespace userSnapNamespace = cls::rbd::UserSnapshotNamespace();
789   librados::IoCtx ioctx;
790   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
791
792   string oid = get_temp_image_name();
793   ASSERT_EQ(-ENOENT, snapshot_add(&ioctx, oid, 0, "snap1"));
794
795   ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
796
797   vector<string> snap_names;
798   vector<cls::rbd::SnapshotNamespace> snap_namespaces;
799   vector<uint64_t> snap_sizes;
800   SnapContext snapc;
801   vector<ParentInfo> parents;
802   vector<uint8_t> protection_status;
803   vector<utime_t> snap_timestamps;
804
805   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
806   ASSERT_EQ(0u, snapc.snaps.size());
807   ASSERT_EQ(0u, snapc.seq);
808   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
809                              &snap_sizes, &parents, &protection_status));
810   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
811   ASSERT_EQ(0u, snap_names.size());
812   ASSERT_EQ(0u, snap_namespaces.size());
813   ASSERT_EQ(0u, snap_sizes.size());
814   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
815   ASSERT_EQ(0u, snap_timestamps.size());
816
817   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
818   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
819   ASSERT_EQ(1u, snapc.snaps.size());
820   ASSERT_EQ(0u, snapc.snaps[0]);
821   ASSERT_EQ(0u, snapc.seq);
822   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
823                              &snap_sizes, &parents, &protection_status));
824   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
825   ASSERT_EQ(1u, snap_names.size());
826   ASSERT_EQ("snap1", snap_names[0]);
827   ASSERT_EQ(1u, snap_namespaces.size());
828   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
829   ASSERT_EQ(10u, snap_sizes[0]);
830   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
831   ASSERT_EQ(1u, snap_timestamps.size());
832
833   // snap with same id and name
834   ASSERT_EQ(-EEXIST, snapshot_add(&ioctx, oid, 0, "snap1"));
835   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
836   ASSERT_EQ(1u, snapc.snaps.size());
837   ASSERT_EQ(0u, snapc.snaps[0]);
838   ASSERT_EQ(0u, snapc.seq);
839   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
840                              &snap_sizes, &parents, &protection_status));
841   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
842   ASSERT_EQ(1u, snap_names.size());
843   ASSERT_EQ("snap1", snap_names[0]);
844   ASSERT_EQ(1u, snap_namespaces.size());
845   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
846   ASSERT_EQ(10u, snap_sizes[0]);
847   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
848   ASSERT_EQ(1u, snap_timestamps.size());
849
850
851   // snap with same id, different name
852   ASSERT_EQ(-EEXIST, snapshot_add(&ioctx, oid, 0, "snap2"));
853   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
854   ASSERT_EQ(1u, snapc.snaps.size());
855   ASSERT_EQ(0u, snapc.snaps[0]);
856   ASSERT_EQ(0u, snapc.seq);
857   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
858                              &snap_sizes, &parents, &protection_status));
859   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
860   ASSERT_EQ(1u, snap_names.size());
861   ASSERT_EQ("snap1", snap_names[0]);
862   ASSERT_EQ(1u, snap_namespaces.size());
863   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
864   ASSERT_EQ(10u, snap_sizes[0]);
865   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
866   ASSERT_EQ(1u, snap_timestamps.size());
867
868   // snap with different id, same name
869   ASSERT_EQ(-EEXIST, snapshot_add(&ioctx, oid, 1, "snap1"));
870   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
871   ASSERT_EQ(1u, snapc.snaps.size());
872   ASSERT_EQ(0u, snapc.snaps[0]);
873   ASSERT_EQ(0u, snapc.seq);
874   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
875                              &snap_sizes, &parents, &protection_status));
876   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
877   ASSERT_EQ(snap_names.size(), 1u);
878   ASSERT_EQ(snap_names[0], "snap1");
879   ASSERT_EQ(1u, snap_namespaces.size());
880   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
881   ASSERT_EQ(snap_sizes[0], 10u);
882   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
883   ASSERT_EQ(1u, snap_timestamps.size());
884
885   // snap with different id, different name
886   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 1, "snap2"));
887   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
888   ASSERT_EQ(2u, snapc.snaps.size());
889   ASSERT_EQ(1u, snapc.snaps[0]);
890   ASSERT_EQ(0u, snapc.snaps[1]);
891   ASSERT_EQ(1u, snapc.seq);
892   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
893                              &snap_sizes, &parents, &protection_status));
894   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
895   ASSERT_EQ(2u, snap_names.size());
896   ASSERT_EQ(2u, snap_namespaces.size());
897   ASSERT_EQ("snap2", snap_names[0]);
898   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
899   ASSERT_EQ(10u, snap_sizes[0]);
900   ASSERT_EQ("snap1", snap_names[1]);
901   ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
902   ASSERT_EQ(10u, snap_sizes[1]);
903   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
904   ASSERT_EQ(2u, snap_timestamps.size());
905
906   ASSERT_EQ(0, snapshot_rename(&ioctx, oid, 0, "snap1-rename"));
907   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
908                              &snap_sizes, &parents, &protection_status));
909   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
910   ASSERT_EQ(2u, snap_names.size());
911   ASSERT_EQ(2u, snap_namespaces.size());
912   ASSERT_EQ("snap2", snap_names[0]);
913   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
914   ASSERT_EQ(10u, snap_sizes[0]);
915   ASSERT_EQ("snap1-rename", snap_names[1]);
916   ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
917   ASSERT_EQ(10u, snap_sizes[1]);
918   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
919   ASSERT_EQ(2u, snap_timestamps.size());
920
921   ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 0));
922   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
923   ASSERT_EQ(1u, snapc.snaps.size());
924   ASSERT_EQ(1u, snapc.snaps[0]);
925   ASSERT_EQ(1u, snapc.seq);
926   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
927                              &snap_sizes, &parents, &protection_status));
928   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
929   ASSERT_EQ(1u, snap_names.size());
930   ASSERT_EQ(1u, snap_namespaces.size());
931   ASSERT_EQ("snap2", snap_names[0]);
932   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
933   ASSERT_EQ(10u, snap_sizes[0]);
934   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
935   ASSERT_EQ(1u, snap_timestamps.size());
936
937   uint64_t size;
938   uint8_t order;
939   ASSERT_EQ(0, set_size(&ioctx, oid, 0));
940   ASSERT_EQ(0, get_size(&ioctx, oid, CEPH_NOSNAP, &size, &order));
941   ASSERT_EQ(0u, size);
942   ASSERT_EQ(22u, order);
943
944   uint64_t large_snap_id = 1ull << 63;
945   ASSERT_EQ(0, snapshot_add(&ioctx, oid, large_snap_id, "snap3"));
946   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
947   ASSERT_EQ(2u, snapc.snaps.size());
948   ASSERT_EQ(large_snap_id, snapc.snaps[0]);
949   ASSERT_EQ(1u, snapc.snaps[1]);
950   ASSERT_EQ(large_snap_id, snapc.seq);
951   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
952                              &snap_sizes, &parents, &protection_status));
953   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
954   ASSERT_EQ(2u, snap_names.size());
955   ASSERT_EQ(2u, snap_namespaces.size());
956   ASSERT_EQ("snap3", snap_names[0]);
957   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
958   ASSERT_EQ(0u, snap_sizes[0]);
959   ASSERT_EQ("snap2", snap_names[1]);
960   ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
961   ASSERT_EQ(10u, snap_sizes[1]);
962   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
963   ASSERT_EQ(2u, snap_timestamps.size());
964
965   ASSERT_EQ(0, get_size(&ioctx, oid, large_snap_id, &size, &order));
966   ASSERT_EQ(0u, size);
967   ASSERT_EQ(22u, order);
968
969   ASSERT_EQ(0, get_size(&ioctx, oid, 1, &size, &order));
970   ASSERT_EQ(10u, size);
971   ASSERT_EQ(22u, order);
972
973   ASSERT_EQ(0, snapshot_remove(&ioctx, oid, large_snap_id));
974   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
975   ASSERT_EQ(1u, snapc.snaps.size());
976   ASSERT_EQ(1u, snapc.snaps[0]);
977   ASSERT_EQ(large_snap_id, snapc.seq);
978   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
979                              &snap_sizes, &parents, &protection_status));
980   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
981   ASSERT_EQ(1u, snap_names.size());
982   ASSERT_EQ(1u, snap_namespaces.size());
983   ASSERT_EQ("snap2", snap_names[0]);
984   ASSERT_EQ(userSnapNamespace, snap_namespaces[0]);
985   ASSERT_EQ(10u, snap_sizes[0]);
986   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
987   ASSERT_EQ(1u, snap_timestamps.size());
988
989   ASSERT_EQ(-ENOENT, snapshot_remove(&ioctx, oid, large_snap_id));
990   ASSERT_EQ(0, snapshot_remove(&ioctx, oid, 1));
991   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
992   ASSERT_EQ(0u, snapc.snaps.size());
993   ASSERT_EQ(large_snap_id, snapc.seq);
994   ASSERT_EQ(0, snapshot_list(&ioctx, oid, snapc.snaps, &snap_names,
995                              &snap_sizes, &parents, &protection_status));
996   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
997   ASSERT_EQ(0u, snap_names.size());
998   ASSERT_EQ(0u, snap_namespaces.size());
999   ASSERT_EQ(0u, snap_sizes.size());
1000   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
1001   ASSERT_EQ(0u, snap_timestamps.size());
1002
1003   ioctx.close();
1004 }
1005
1006 TEST_F(TestClsRbd, snapshots_namespaces)
1007 {
1008   cls::rbd::SnapshotNamespace groupSnapNamespace = cls::rbd::GroupSnapshotNamespace(5, "1018643c9869", 3);
1009   cls::rbd::SnapshotNamespace userSnapNamespace = cls::rbd::UserSnapshotNamespace();
1010   librados::IoCtx ioctx;
1011   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1012
1013   string oid = get_temp_image_name();
1014
1015   ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
1016
1017   vector<cls::rbd::SnapshotNamespace> snap_namespaces;
1018   SnapContext snapc;
1019
1020   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
1021   ASSERT_EQ(0u, snapc.snaps.size());
1022   ASSERT_EQ(0u, snapc.seq);
1023   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
1024   ASSERT_EQ(0u, snap_namespaces.size());
1025
1026   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
1027
1028   librados::ObjectWriteOperation op;
1029   ::librbd::cls_client::snapshot_add(&op, 1, "snap1", groupSnapNamespace);
1030   int r = ioctx.operate(oid, &op);
1031   ASSERT_EQ(0, r);
1032
1033   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
1034   ASSERT_EQ(2u, snapc.snaps.size());
1035   ASSERT_EQ(1u, snapc.snaps[0]);
1036   ASSERT_EQ(0u, snapc.snaps[1]);
1037   ASSERT_EQ(1u, snapc.seq);
1038   ASSERT_EQ(0, snapshot_namespace_list(&ioctx, oid, snapc.snaps, &snap_namespaces));
1039   ASSERT_EQ(groupSnapNamespace, snap_namespaces[0]);
1040   ASSERT_EQ(userSnapNamespace, snap_namespaces[1]);
1041
1042   ioctx.close();
1043 }
1044
1045 TEST_F(TestClsRbd, snapshots_timestamps)
1046 {
1047   librados::IoCtx ioctx;
1048   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1049
1050   string oid = get_temp_image_name();
1051
1052   ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
1053
1054   vector<utime_t> snap_timestamps;
1055   SnapContext snapc;
1056
1057   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
1058   ASSERT_EQ(0u, snapc.snaps.size());
1059   ASSERT_EQ(0u, snapc.seq);
1060   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
1061   ASSERT_EQ(0u, snap_timestamps.size());
1062
1063   ASSERT_EQ(0, snapshot_add(&ioctx, oid, 0, "snap1"));
1064
1065   ASSERT_EQ(0, get_snapcontext(&ioctx, oid, &snapc));
1066   ASSERT_EQ(1u, snapc.snaps.size());
1067   ASSERT_EQ(0, snapshot_timestamp_list(&ioctx, oid, snapc.snaps, &snap_timestamps));
1068   ASSERT_LT(0U, snap_timestamps[0].tv.tv_sec);
1069   ioctx.close();
1070 }
1071
1072
1073 TEST_F(TestClsRbd, snapid_race)
1074 {
1075   librados::IoCtx ioctx;
1076   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1077
1078   buffer::list bl;
1079   buffer::ptr bp(4096);
1080   bp.zero();
1081   bl.append(bp);
1082
1083   string oid = get_temp_image_name();
1084   ASSERT_EQ(0, ioctx.write(oid, bl, 4096, 0));
1085   ASSERT_EQ(0, old_snapshot_add(&ioctx, oid, 1, "test1"));
1086   ASSERT_EQ(0, old_snapshot_add(&ioctx, oid, 3, "test3"));
1087   ASSERT_EQ(-ESTALE, old_snapshot_add(&ioctx, oid, 2, "test2"));
1088
1089   ioctx.close();
1090 }
1091
1092 TEST_F(TestClsRbd, stripingv2)
1093 {
1094   librados::IoCtx ioctx;
1095   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1096
1097   string oid = get_temp_image_name();
1098   string oid2 = get_temp_image_name();
1099   ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, 0, oid, -1));
1100
1101   uint64_t su = 65536, sc = 12;
1102   ASSERT_EQ(-ENOEXEC, get_stripe_unit_count(&ioctx, oid, &su, &sc));
1103   ASSERT_EQ(-ENOEXEC, set_stripe_unit_count(&ioctx, oid, su, sc));
1104
1105   ASSERT_EQ(0, create_image(&ioctx, oid2, 10, 22, RBD_FEATURE_STRIPINGV2,
1106                             oid2, -1));
1107   ASSERT_EQ(0, get_stripe_unit_count(&ioctx, oid2, &su, &sc));
1108   ASSERT_EQ(1ull << 22, su);
1109   ASSERT_EQ(1ull, sc);
1110   su = 8192;
1111   sc = 456;
1112   ASSERT_EQ(0, set_stripe_unit_count(&ioctx, oid2, su, sc));
1113   su = sc = 0;
1114   ASSERT_EQ(0, get_stripe_unit_count(&ioctx, oid2, &su, &sc));
1115   ASSERT_EQ(8192ull, su);
1116   ASSERT_EQ(456ull, sc);
1117
1118   // su must not be larger than an object
1119   ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 1 << 23, 1));
1120   // su must be a factor of object size
1121   ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 511, 1));
1122   // su and sc must be non-zero
1123   ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 0, 1));
1124   ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 1, 0));
1125   ASSERT_EQ(-EINVAL, set_stripe_unit_count(&ioctx, oid2, 0, 0));
1126
1127   ioctx.close();
1128 }
1129
1130 TEST_F(TestClsRbd, get_mutable_metadata_features)
1131 {
1132   librados::IoCtx ioctx;
1133   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1134
1135   string oid = get_temp_image_name();
1136   ASSERT_EQ(0, create_image(&ioctx, oid, 10, 22, RBD_FEATURE_EXCLUSIVE_LOCK,
1137                             oid, -1));
1138
1139   uint64_t size, features, incompatible_features;
1140   std::map<rados::cls::lock::locker_id_t,
1141            rados::cls::lock::locker_info_t> lockers;
1142   bool exclusive_lock;
1143   std::string lock_tag;
1144   ::SnapContext snapc;
1145   ParentInfo parent;
1146
1147   ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, true, &size, &features,
1148                                     &incompatible_features, &lockers,
1149                                     &exclusive_lock, &lock_tag, &snapc,
1150                                     &parent));
1151   ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK), features);
1152   ASSERT_EQ(0U, incompatible_features);
1153
1154   ASSERT_EQ(0, get_mutable_metadata(&ioctx, oid, false, &size, &features,
1155                                     &incompatible_features, &lockers,
1156                                     &exclusive_lock, &lock_tag, &snapc,
1157                                     &parent));
1158   ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK), features);
1159   ASSERT_EQ(static_cast<uint64_t>(RBD_FEATURE_EXCLUSIVE_LOCK),
1160             incompatible_features);
1161
1162   ioctx.close();
1163 }
1164
1165 TEST_F(TestClsRbd, object_map_save)
1166 {
1167   librados::IoCtx ioctx;
1168   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1169
1170   string oid = get_temp_image_name();
1171   BitVector<2> ref_bit_vector;
1172   ref_bit_vector.resize(32);
1173   for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1174     ref_bit_vector[i] = 1;
1175   }
1176
1177   librados::ObjectWriteOperation op;
1178   object_map_save(&op, ref_bit_vector);
1179   ASSERT_EQ(0, ioctx.operate(oid, &op));
1180
1181   BitVector<2> osd_bit_vector;
1182   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1183   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1184 }
1185
1186 TEST_F(TestClsRbd, object_map_resize)
1187 {
1188   librados::IoCtx ioctx;
1189   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1190
1191   string oid = get_temp_image_name();
1192   BitVector<2> ref_bit_vector;
1193   ref_bit_vector.resize(32);
1194   for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1195     ref_bit_vector[i] = 1;
1196   }
1197
1198   librados::ObjectWriteOperation op1;
1199   object_map_resize(&op1, ref_bit_vector.size(), 1);
1200   ASSERT_EQ(0, ioctx.operate(oid, &op1));
1201
1202   BitVector<2> osd_bit_vector;
1203   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1204   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1205
1206   ref_bit_vector.resize(64);
1207   for (uint64_t i = 32; i < ref_bit_vector.size(); ++i) {
1208     ref_bit_vector[i] = 2;
1209   }
1210
1211   librados::ObjectWriteOperation op2;
1212   object_map_resize(&op2, ref_bit_vector.size(), 2);
1213   ASSERT_EQ(0, ioctx.operate(oid, &op2));
1214   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1215   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1216
1217   ref_bit_vector.resize(32);
1218
1219   librados::ObjectWriteOperation op3;
1220   object_map_resize(&op3, ref_bit_vector.size(), 1);
1221   ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op3));
1222
1223   librados::ObjectWriteOperation op4;
1224   object_map_resize(&op4, ref_bit_vector.size(), 2);
1225   ASSERT_EQ(0, ioctx.operate(oid, &op4));
1226
1227   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1228   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1229
1230   ioctx.close();
1231 }
1232
1233 TEST_F(TestClsRbd, object_map_update)
1234 {
1235   librados::IoCtx ioctx;
1236   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1237
1238   string oid = get_temp_image_name();
1239   BitVector<2> ref_bit_vector;
1240   ref_bit_vector.resize(16);
1241   for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1242     ref_bit_vector[i] = 2;
1243   }
1244
1245   BitVector<2> osd_bit_vector;
1246
1247   librados::ObjectWriteOperation op1;
1248   object_map_resize(&op1, ref_bit_vector.size(), 2);
1249   ASSERT_EQ(0, ioctx.operate(oid, &op1));
1250   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1251   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1252
1253   ref_bit_vector[7] = 1;
1254   ref_bit_vector[8] = 1;
1255
1256   librados::ObjectWriteOperation op2;
1257   object_map_update(&op2, 7, 9, 1, boost::optional<uint8_t>());
1258   ASSERT_EQ(0, ioctx.operate(oid, &op2));
1259   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1260   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1261
1262   ref_bit_vector[7] = 3;
1263   ref_bit_vector[8] = 3;
1264
1265   librados::ObjectWriteOperation op3;
1266   object_map_update(&op3, 6, 10, 3, 1);
1267   ASSERT_EQ(0, ioctx.operate(oid, &op3));
1268   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1269   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1270
1271   ioctx.close();
1272 }
1273
1274 TEST_F(TestClsRbd, object_map_load_enoent)
1275 {
1276   librados::IoCtx ioctx;
1277   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1278
1279   string oid = get_temp_image_name();
1280   BitVector<2> osd_bit_vector;
1281   ASSERT_EQ(-ENOENT, object_map_load(&ioctx, oid, &osd_bit_vector));
1282
1283   ioctx.close();
1284 }
1285
1286 TEST_F(TestClsRbd, object_map_snap_add)
1287 {
1288   librados::IoCtx ioctx;
1289   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1290
1291   string oid = get_temp_image_name();
1292   BitVector<2> ref_bit_vector;
1293   ref_bit_vector.resize(16);
1294   for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1295     if (i < 4) {
1296       ref_bit_vector[i] = OBJECT_NONEXISTENT;
1297     } else {
1298       ref_bit_vector[i] = OBJECT_EXISTS;
1299     }
1300   }
1301
1302   BitVector<2> osd_bit_vector;
1303
1304   librados::ObjectWriteOperation op1;
1305   object_map_resize(&op1, ref_bit_vector.size(), OBJECT_EXISTS);
1306   ASSERT_EQ(0, ioctx.operate(oid, &op1));
1307
1308   librados::ObjectWriteOperation op2;
1309   object_map_update(&op2, 0, 4, OBJECT_NONEXISTENT, boost::optional<uint8_t>());
1310   ASSERT_EQ(0, ioctx.operate(oid, &op2));
1311
1312   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1313   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1314
1315   librados::ObjectWriteOperation op3;
1316   object_map_snap_add(&op3);
1317   ASSERT_EQ(0, ioctx.operate(oid, &op3));
1318
1319   for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1320     if (ref_bit_vector[i] == OBJECT_EXISTS) {
1321       ref_bit_vector[i] = OBJECT_EXISTS_CLEAN;
1322     }
1323   }
1324
1325   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1326   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1327 }
1328
1329 TEST_F(TestClsRbd, object_map_snap_remove)
1330 {
1331   librados::IoCtx ioctx;
1332   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1333
1334   string oid = get_temp_image_name();
1335   BitVector<2> ref_bit_vector;
1336   ref_bit_vector.resize(16);
1337   for (uint64_t i = 0; i < ref_bit_vector.size(); ++i) {
1338     if (i < 4) {
1339       ref_bit_vector[i] = OBJECT_EXISTS_CLEAN;
1340     } else {
1341       ref_bit_vector[i] = OBJECT_EXISTS;
1342     }
1343   }
1344
1345   BitVector<2> osd_bit_vector;
1346
1347   librados::ObjectWriteOperation op1;
1348   object_map_resize(&op1, ref_bit_vector.size(), OBJECT_EXISTS);
1349   ASSERT_EQ(0, ioctx.operate(oid, &op1));
1350
1351   librados::ObjectWriteOperation op2;
1352   object_map_update(&op2, 0, 4, OBJECT_EXISTS_CLEAN, boost::optional<uint8_t>());
1353   ASSERT_EQ(0, ioctx.operate(oid, &op2));
1354
1355   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1356   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1357
1358   BitVector<2> snap_bit_vector;
1359   snap_bit_vector.resize(4);
1360   for (uint64_t i = 0; i < snap_bit_vector.size(); ++i) {
1361     if (i == 1 || i == 2) {
1362       snap_bit_vector[i] = OBJECT_EXISTS;
1363     } else {
1364       snap_bit_vector[i] = OBJECT_NONEXISTENT;
1365     }
1366   }
1367
1368   librados::ObjectWriteOperation op3;
1369   object_map_snap_remove(&op3, snap_bit_vector);
1370   ASSERT_EQ(0, ioctx.operate(oid, &op3));
1371
1372   ref_bit_vector[1] = OBJECT_EXISTS;
1373   ref_bit_vector[2] = OBJECT_EXISTS;
1374   ASSERT_EQ(0, object_map_load(&ioctx, oid, &osd_bit_vector));
1375   ASSERT_EQ(ref_bit_vector, osd_bit_vector);
1376 }
1377
1378 TEST_F(TestClsRbd, flags)
1379 {
1380   librados::IoCtx ioctx;
1381   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1382
1383   string oid = get_temp_image_name();
1384   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
1385
1386   uint64_t flags;
1387   std::vector<snapid_t> snap_ids;
1388   std::vector<uint64_t> snap_flags;
1389   ASSERT_EQ(0, get_flags(&ioctx, oid, &flags, snap_ids, &snap_flags));
1390   ASSERT_EQ(0U, flags);
1391
1392   librados::ObjectWriteOperation op1;
1393   set_flags(&op1, CEPH_NOSNAP, 3, 2);
1394   ASSERT_EQ(0, ioctx.operate(oid, &op1));
1395   ASSERT_EQ(0, get_flags(&ioctx, oid, &flags, snap_ids, &snap_flags));
1396   ASSERT_EQ(2U, flags);
1397
1398   uint64_t snap_id = 10;
1399   snap_ids.push_back(snap_id);
1400   ASSERT_EQ(-ENOENT, get_flags(&ioctx, oid, &flags, snap_ids, &snap_flags));
1401   ASSERT_EQ(0, snapshot_add(&ioctx, oid, snap_id, "snap"));
1402
1403   librados::ObjectWriteOperation op2;
1404   set_flags(&op2, snap_id, 31, 4);
1405   ASSERT_EQ(0, ioctx.operate(oid, &op2));
1406   ASSERT_EQ(0, get_flags(&ioctx, oid, &flags, snap_ids, &snap_flags));
1407   ASSERT_EQ(2U, flags);
1408   ASSERT_EQ(snap_ids.size(), snap_flags.size());
1409   ASSERT_EQ(6U, snap_flags[0]);
1410
1411   ioctx.close();
1412 }
1413
1414 TEST_F(TestClsRbd, metadata)
1415 {
1416   librados::IoCtx ioctx;
1417   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1418
1419   string oid = get_temp_image_name();
1420   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, 0, oid, -1));
1421
1422   map<string, bufferlist> pairs;
1423   string value;
1424   ASSERT_EQ(0, metadata_list(&ioctx, oid, "", 0, &pairs));
1425   ASSERT_TRUE(pairs.empty());
1426
1427   pairs["key1"].append("value1");
1428   pairs["key2"].append("value2");
1429   ASSERT_EQ(0, metadata_set(&ioctx, oid, pairs));
1430   ASSERT_EQ(0, metadata_get(&ioctx, oid, "key1", &value));
1431   ASSERT_EQ(0, strcmp("value1", value.c_str()));
1432   pairs.clear();
1433   ASSERT_EQ(0, metadata_list(&ioctx, oid, "", 0, &pairs));
1434   ASSERT_EQ(2U, pairs.size());
1435   ASSERT_EQ(0, strncmp("value1", pairs["key1"].c_str(), 6));
1436   ASSERT_EQ(0, strncmp("value2", pairs["key2"].c_str(), 6));
1437
1438   pairs.clear();
1439   ASSERT_EQ(0, metadata_remove(&ioctx, oid, "key1"));
1440   ASSERT_EQ(0, metadata_remove(&ioctx, oid, "key3"));
1441   ASSERT_TRUE(metadata_get(&ioctx, oid, "key1", &value) < 0);
1442   ASSERT_EQ(0, metadata_list(&ioctx, oid, "", 0, &pairs));
1443   ASSERT_EQ(1U, pairs.size());
1444   ASSERT_EQ(0, strncmp("value2", pairs["key2"].c_str(), 6));
1445
1446   pairs.clear();
1447   char key[10], val[20];
1448   for (int i = 0; i < 1024; i++) {
1449     sprintf(key, "key%d", i);
1450     sprintf(val, "value%d", i);
1451     pairs[key].append(val, strlen(val));
1452   }
1453   ASSERT_EQ(0, metadata_set(&ioctx, oid, pairs));
1454
1455   string last_read = "";
1456   uint64_t max_read = 48, r;
1457   uint64_t size = 0;
1458   map<string, bufferlist> data;
1459   do {
1460     map<string, bufferlist> cur;
1461     metadata_list(&ioctx, oid, last_read, max_read, &cur);
1462     size += cur.size();
1463     for (map<string, bufferlist>::iterator it = cur.begin();
1464          it != cur.end(); ++it)
1465       data[it->first] = it->second;
1466     last_read = cur.rbegin()->first;
1467     r = cur.size();
1468   } while (r == max_read);
1469   ASSERT_EQ(size, 1024U);
1470   for (map<string, bufferlist>::iterator it = data.begin();
1471        it != data.end(); ++it) {
1472     ASSERT_TRUE(it->second.contents_equal(pairs[it->first]));
1473   }
1474
1475   ioctx.close();
1476 }
1477
1478 TEST_F(TestClsRbd, set_features)
1479 {
1480   librados::IoCtx ioctx;
1481   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1482
1483   string oid = get_temp_image_name();
1484   uint64_t base_features = RBD_FEATURE_LAYERING | RBD_FEATURE_DEEP_FLATTEN;
1485   ASSERT_EQ(0, create_image(&ioctx, oid, 0, 22, base_features, oid, -1));
1486
1487   uint64_t features = RBD_FEATURES_MUTABLE;
1488   uint64_t mask = RBD_FEATURES_MUTABLE;
1489   ASSERT_EQ(0, set_features(&ioctx, oid, features, mask));
1490
1491   uint64_t actual_features;
1492   ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &actual_features));
1493
1494   uint64_t expected_features = RBD_FEATURES_MUTABLE | base_features;
1495   ASSERT_EQ(expected_features, actual_features);
1496
1497   features = 0;
1498   mask = RBD_FEATURE_OBJECT_MAP;
1499   ASSERT_EQ(0, set_features(&ioctx, oid, features, mask));
1500
1501   ASSERT_EQ(0, get_features(&ioctx, oid, CEPH_NOSNAP, &actual_features));
1502
1503   expected_features = (RBD_FEATURES_MUTABLE | base_features) &
1504                       ~RBD_FEATURE_OBJECT_MAP;
1505   ASSERT_EQ(expected_features, actual_features);
1506
1507   ASSERT_EQ(0, set_features(&ioctx, oid, 0, RBD_FEATURE_DEEP_FLATTEN));
1508   ASSERT_EQ(-EINVAL, set_features(&ioctx, oid, RBD_FEATURE_DEEP_FLATTEN,
1509                                   RBD_FEATURE_DEEP_FLATTEN));
1510
1511   ASSERT_EQ(-EINVAL, set_features(&ioctx, oid, 0, RBD_FEATURE_LAYERING));
1512 }
1513
1514 TEST_F(TestClsRbd, mirror) {
1515   librados::IoCtx ioctx;
1516   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1517   ioctx.remove(RBD_MIRRORING);
1518
1519   std::vector<cls::rbd::MirrorPeer> peers;
1520   ASSERT_EQ(-ENOENT, mirror_peer_list(&ioctx, &peers));
1521
1522   std::string uuid;
1523   ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid));
1524   ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client"));
1525
1526   cls::rbd::MirrorMode mirror_mode;
1527   ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
1528   ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED, mirror_mode);
1529
1530   ASSERT_EQ(-EINVAL, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_IMAGE));
1531   ASSERT_EQ(-EINVAL, mirror_uuid_set(&ioctx, ""));
1532   ASSERT_EQ(0, mirror_uuid_set(&ioctx, "mirror-uuid"));
1533   ASSERT_EQ(0, mirror_uuid_get(&ioctx, &uuid));
1534   ASSERT_EQ("mirror-uuid", uuid);
1535
1536   ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_IMAGE));
1537   ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
1538   ASSERT_EQ(cls::rbd::MIRROR_MODE_IMAGE, mirror_mode);
1539
1540   ASSERT_EQ(-EINVAL, mirror_uuid_set(&ioctx, "new-mirror-uuid"));
1541
1542   ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_POOL));
1543   ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
1544   ASSERT_EQ(cls::rbd::MIRROR_MODE_POOL, mirror_mode);
1545
1546   ASSERT_EQ(-EINVAL, mirror_peer_add(&ioctx, "mirror-uuid", "cluster1", "client"));
1547   ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid1", "cluster1", "client"));
1548   ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid2", "cluster2", "admin"));
1549   ASSERT_EQ(-ESTALE, mirror_peer_add(&ioctx, "uuid2", "cluster3", "foo"));
1550   ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid3", "cluster1", "foo"));
1551   ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid3", "cluster3", "admin", 123));
1552   ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin"));
1553   ASSERT_EQ(-EEXIST, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin", 123));
1554   ASSERT_EQ(0, mirror_peer_add(&ioctx, "uuid4", "cluster3", "admin", 234));
1555
1556   ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
1557   std::vector<cls::rbd::MirrorPeer> expected_peers = {
1558     {"uuid1", "cluster1", "client", -1},
1559     {"uuid2", "cluster2", "admin", -1},
1560     {"uuid3", "cluster3", "admin", 123},
1561     {"uuid4", "cluster3", "admin", 234}};
1562   ASSERT_EQ(expected_peers, peers);
1563
1564   ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid5"));
1565   ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid4"));
1566   ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid2"));
1567
1568   ASSERT_EQ(-ENOENT, mirror_peer_set_client(&ioctx, "uuid4", "new client"));
1569   ASSERT_EQ(0, mirror_peer_set_client(&ioctx, "uuid1", "new client"));
1570
1571   ASSERT_EQ(-ENOENT, mirror_peer_set_cluster(&ioctx, "uuid4", "new cluster"));
1572   ASSERT_EQ(0, mirror_peer_set_cluster(&ioctx, "uuid3", "new cluster"));
1573
1574   ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
1575   expected_peers = {
1576     {"uuid1", "cluster1", "new client", -1},
1577     {"uuid3", "new cluster", "admin", 123}};
1578   ASSERT_EQ(expected_peers, peers);
1579   ASSERT_EQ(-EBUSY, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_DISABLED));
1580
1581   ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid3"));
1582   ASSERT_EQ(0, mirror_peer_remove(&ioctx, "uuid1"));
1583   ASSERT_EQ(0, mirror_peer_list(&ioctx, &peers));
1584   expected_peers = {};
1585   ASSERT_EQ(expected_peers, peers);
1586
1587   ASSERT_EQ(0, mirror_mode_set(&ioctx, cls::rbd::MIRROR_MODE_DISABLED));
1588   ASSERT_EQ(0, mirror_mode_get(&ioctx, &mirror_mode));
1589   ASSERT_EQ(cls::rbd::MIRROR_MODE_DISABLED, mirror_mode);
1590   ASSERT_EQ(-ENOENT, mirror_uuid_get(&ioctx, &uuid));
1591 }
1592
1593 TEST_F(TestClsRbd, mirror_image) {
1594   librados::IoCtx ioctx;
1595   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1596   ioctx.remove(RBD_MIRRORING);
1597
1598   std::map<std::string, std::string> mirror_image_ids;
1599   ASSERT_EQ(-ENOENT, mirror_image_list(&ioctx, "", 0, &mirror_image_ids));
1600
1601   cls::rbd::MirrorImage image1("uuid1", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1602   cls::rbd::MirrorImage image2("uuid2", cls::rbd::MIRROR_IMAGE_STATE_DISABLING);
1603   cls::rbd::MirrorImage image3("uuid3", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1604
1605   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id1", image1));
1606   ASSERT_EQ(-ENOENT, mirror_image_set(&ioctx, "image_id2", image2));
1607   image2.state = cls::rbd::MIRROR_IMAGE_STATE_ENABLED;
1608   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id2", image2));
1609   image2.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1610   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id2", image2));
1611   ASSERT_EQ(-EINVAL, mirror_image_set(&ioctx, "image_id1", image2));
1612   ASSERT_EQ(-EEXIST, mirror_image_set(&ioctx, "image_id3", image2));
1613   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id3", image3));
1614
1615   std::string image_id;
1616   ASSERT_EQ(0, mirror_image_get_image_id(&ioctx, "uuid2", &image_id));
1617   ASSERT_EQ("image_id2", image_id);
1618
1619   cls::rbd::MirrorImage read_image;
1620   ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id1", &read_image));
1621   ASSERT_EQ(read_image, image1);
1622   ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id2", &read_image));
1623   ASSERT_EQ(read_image, image2);
1624   ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id3", &read_image));
1625   ASSERT_EQ(read_image, image3);
1626
1627   ASSERT_EQ(0, mirror_image_list(&ioctx, "", 1, &mirror_image_ids));
1628   std::map<std::string, std::string> expected_mirror_image_ids = {
1629     {"image_id1", "uuid1"}};
1630   ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
1631
1632   ASSERT_EQ(0, mirror_image_list(&ioctx, "image_id1", 2, &mirror_image_ids));
1633   expected_mirror_image_ids = {{"image_id2", "uuid2"}, {"image_id3", "uuid3"}};
1634   ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
1635
1636   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id2"));
1637   ASSERT_EQ(-ENOENT, mirror_image_get_image_id(&ioctx, "uuid2", &image_id));
1638   ASSERT_EQ(-EBUSY, mirror_image_remove(&ioctx, "image_id1"));
1639
1640   ASSERT_EQ(0, mirror_image_list(&ioctx, "", 3, &mirror_image_ids));
1641   expected_mirror_image_ids = {{"image_id1", "uuid1"}, {"image_id3", "uuid3"}};
1642   ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
1643
1644   image1.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1645   image3.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1646   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id1", image1));
1647   ASSERT_EQ(0, mirror_image_get(&ioctx, "image_id1", &read_image));
1648   ASSERT_EQ(read_image, image1);
1649   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id3", image3));
1650   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id1"));
1651   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id3"));
1652
1653   ASSERT_EQ(0, mirror_image_list(&ioctx, "", 3, &mirror_image_ids));
1654   expected_mirror_image_ids = {};
1655   ASSERT_EQ(expected_mirror_image_ids, mirror_image_ids);
1656 }
1657
1658 TEST_F(TestClsRbd, mirror_image_status) {
1659   struct WatchCtx : public librados::WatchCtx2 {
1660     librados::IoCtx *m_ioctx;
1661
1662     WatchCtx(librados::IoCtx *ioctx) : m_ioctx(ioctx) {}
1663     void handle_notify(uint64_t notify_id, uint64_t cookie,
1664                              uint64_t notifier_id, bufferlist& bl_) override {
1665       bufferlist bl;
1666       m_ioctx->notify_ack(RBD_MIRRORING, notify_id, cookie, bl);
1667     }
1668     void handle_error(uint64_t cookie, int err) override {}
1669   };
1670
1671   map<std::string, cls::rbd::MirrorImage> images;
1672   map<std::string, cls::rbd::MirrorImageStatus> statuses;
1673   std::map<cls::rbd::MirrorImageStatusState, int> states;
1674   cls::rbd::MirrorImageStatus read_status;
1675   uint64_t watch_handle;
1676   librados::IoCtx ioctx;
1677
1678   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1679   ioctx.remove(RBD_MIRRORING);
1680
1681   // Test list fails on nonexistent RBD_MIRRORING object
1682
1683   ASSERT_EQ(-ENOENT, mirror_image_status_list(&ioctx, "", 1024, &images,
1684           &statuses));
1685
1686   // Test status set
1687
1688   cls::rbd::MirrorImage image1("uuid1", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1689   cls::rbd::MirrorImage image2("uuid2", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1690   cls::rbd::MirrorImage image3("uuid3", cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1691
1692   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id1", image1));
1693   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id2", image2));
1694   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id3", image3));
1695
1696   cls::rbd::MirrorImageStatus status1(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN);
1697   cls::rbd::MirrorImageStatus status2(cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING);
1698   cls::rbd::MirrorImageStatus status3(cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR);
1699
1700   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1701   images.clear();
1702   statuses.clear();
1703   ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1704   ASSERT_EQ(3U, images.size());
1705   ASSERT_EQ(1U, statuses.size());
1706
1707   // Test status is down due to RBD_MIRRORING is not watched
1708
1709   status1.up = false;
1710   ASSERT_EQ(statuses["image_id1"], status1);
1711   ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1712   ASSERT_EQ(read_status, status1);
1713
1714   // Test status summary. All statuses are unknown due to down.
1715   states.clear();
1716   ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1717   ASSERT_EQ(1U, states.size());
1718   ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1719
1720   // Test remove_down removes stale statuses
1721
1722   ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx));
1723   ASSERT_EQ(-ENOENT, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1724   ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1725   ASSERT_EQ(3U, images.size());
1726   ASSERT_TRUE(statuses.empty());
1727   ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1728   ASSERT_EQ(1U, states.size());
1729   ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1730
1731   // Test statuses are not down after watcher is started
1732
1733   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1734
1735   WatchCtx watch_ctx(&ioctx);
1736   ASSERT_EQ(0, ioctx.watch2(RBD_MIRRORING, &watch_handle, &watch_ctx));
1737
1738   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid2", status2));
1739   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid3", status3));
1740
1741   ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1742   status1.up = true;
1743   ASSERT_EQ(read_status, status1);
1744   ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid2", &read_status));
1745   status2.up = true;
1746   ASSERT_EQ(read_status, status2);
1747   ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid3", &read_status));
1748   status3.up = true;
1749   ASSERT_EQ(read_status, status3);
1750
1751   images.clear();
1752   statuses.clear();
1753   ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1754   ASSERT_EQ(3U, images.size());
1755   ASSERT_EQ(3U, statuses.size());
1756   ASSERT_EQ(statuses["image_id1"], status1);
1757   ASSERT_EQ(statuses["image_id2"], status2);
1758   ASSERT_EQ(statuses["image_id3"], status3);
1759
1760   ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx));
1761   ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1762   ASSERT_EQ(read_status, status1);
1763   images.clear();
1764   statuses.clear();
1765   ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1766   ASSERT_EQ(3U, images.size());
1767   ASSERT_EQ(3U, statuses.size());
1768   ASSERT_EQ(statuses["image_id1"], status1);
1769   ASSERT_EQ(statuses["image_id2"], status2);
1770   ASSERT_EQ(statuses["image_id3"], status3);
1771
1772   states.clear();
1773   ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1774   ASSERT_EQ(3U, states.size());
1775   ASSERT_EQ(1, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1776   ASSERT_EQ(1, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING]);
1777   ASSERT_EQ(1, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_ERROR]);
1778
1779   // Test update
1780
1781   status1.state = status3.state = cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING;
1782   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1783   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid3", status3));
1784   ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid3", &read_status));
1785   ASSERT_EQ(read_status, status3);
1786
1787   states.clear();
1788   ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1789   ASSERT_EQ(1U, states.size());
1790   ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING]);
1791
1792   // Test remove
1793
1794   ASSERT_EQ(0, mirror_image_status_remove(&ioctx, "uuid3"));
1795   ASSERT_EQ(-ENOENT, mirror_image_status_get(&ioctx, "uuid3", &read_status));
1796   images.clear();
1797   statuses.clear();
1798   ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1799   ASSERT_EQ(3U, images.size());
1800   ASSERT_EQ(2U, statuses.size());
1801   ASSERT_EQ(statuses["image_id1"], status1);
1802   ASSERT_EQ(statuses["image_id2"], status2);
1803
1804   states.clear();
1805   ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1806   ASSERT_EQ(2U, states.size());
1807   ASSERT_EQ(1, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1808   ASSERT_EQ(2, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_REPLAYING]);
1809
1810   // Test statuses are down after removing watcher
1811
1812   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid1", status1));
1813   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid2", status2));
1814   ASSERT_EQ(0, mirror_image_status_set(&ioctx, "uuid3", status3));
1815
1816   images.clear();
1817   statuses.clear();
1818   ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1819   ASSERT_EQ(3U, images.size());
1820   ASSERT_EQ(3U, statuses.size());
1821   ASSERT_EQ(statuses["image_id1"], status1);
1822   ASSERT_EQ(statuses["image_id2"], status2);
1823   ASSERT_EQ(statuses["image_id3"], status3);
1824
1825   ioctx.unwatch2(watch_handle);
1826
1827   ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1828   ASSERT_EQ(3U, images.size());
1829   ASSERT_EQ(3U, statuses.size());
1830   status1.up = false;
1831   ASSERT_EQ(statuses["image_id1"], status1);
1832   status2.up = false;
1833   ASSERT_EQ(statuses["image_id2"], status2);
1834   status3.up = false;
1835   ASSERT_EQ(statuses["image_id3"], status3);
1836
1837   ASSERT_EQ(0, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1838   ASSERT_EQ(read_status, status1);
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   ASSERT_EQ(0, mirror_image_status_remove_down(&ioctx));
1846   ASSERT_EQ(-ENOENT, mirror_image_status_get(&ioctx, "uuid1", &read_status));
1847
1848   images.clear();
1849   statuses.clear();
1850   ASSERT_EQ(0, mirror_image_status_list(&ioctx, "", 1024, &images, &statuses));
1851   ASSERT_EQ(3U, images.size());
1852   ASSERT_TRUE(statuses.empty());
1853
1854   states.clear();
1855   ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1856   ASSERT_EQ(1U, states.size());
1857   ASSERT_EQ(3, states[cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN]);
1858
1859   // Remove images
1860
1861   image1.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1862   image2.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1863   image3.state = cls::rbd::MIRROR_IMAGE_STATE_DISABLING;
1864
1865   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id1", image1));
1866   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id2", image2));
1867   ASSERT_EQ(0, mirror_image_set(&ioctx, "image_id3", image3));
1868
1869   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id1"));
1870   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id2"));
1871   ASSERT_EQ(0, mirror_image_remove(&ioctx, "image_id3"));
1872
1873   states.clear();
1874   ASSERT_EQ(0, mirror_image_status_get_summary(&ioctx, &states));
1875   ASSERT_EQ(0U, states.size());
1876
1877   // Test status list with large number of images
1878
1879   size_t N = 1024;
1880   ASSERT_EQ(0U, N % 2);
1881
1882   for (size_t i = 0; i < N; i++) {
1883     std::string id = "id" + stringify(i);
1884     std::string uuid = "uuid" + stringify(i);
1885     cls::rbd::MirrorImage image(uuid, cls::rbd::MIRROR_IMAGE_STATE_ENABLED);
1886     cls::rbd::MirrorImageStatus status(cls::rbd::MIRROR_IMAGE_STATUS_STATE_UNKNOWN);
1887     ASSERT_EQ(0, mirror_image_set(&ioctx, id, image));
1888     ASSERT_EQ(0, mirror_image_status_set(&ioctx, uuid, status));
1889   }
1890
1891   std::string last_read = "";
1892   images.clear();
1893   statuses.clear();
1894   ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N * 2, &images,
1895           &statuses));
1896   ASSERT_EQ(N, images.size());
1897   ASSERT_EQ(N, statuses.size());
1898
1899   images.clear();
1900   statuses.clear();
1901   ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1902           &statuses));
1903   ASSERT_EQ(N / 2, images.size());
1904   ASSERT_EQ(N / 2, statuses.size());
1905
1906   last_read = images.rbegin()->first;
1907   images.clear();
1908   statuses.clear();
1909   ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1910           &statuses));
1911   ASSERT_EQ(N / 2, images.size());
1912   ASSERT_EQ(N / 2, statuses.size());
1913
1914   last_read = images.rbegin()->first;
1915   images.clear();
1916   statuses.clear();
1917   ASSERT_EQ(0, mirror_image_status_list(&ioctx, last_read, N / 2, &images,
1918           &statuses));
1919   ASSERT_EQ(0U, images.size());
1920   ASSERT_EQ(0U, statuses.size());
1921 }
1922
1923 TEST_F(TestClsRbd, mirror_instances) {
1924   librados::IoCtx ioctx;
1925   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1926   ioctx.remove(RBD_MIRROR_LEADER);
1927
1928   std::vector<std::string> instance_ids;
1929   ASSERT_EQ(-ENOENT, mirror_instances_list(&ioctx, &instance_ids));
1930
1931   ASSERT_EQ(0, ioctx.create(RBD_MIRROR_LEADER, true));
1932   ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1933   ASSERT_EQ(0U, instance_ids.size());
1934
1935   ASSERT_EQ(0, mirror_instances_add(&ioctx, "instance_id1"));
1936   ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1937   ASSERT_EQ(1U, instance_ids.size());
1938   ASSERT_EQ(instance_ids[0], "instance_id1");
1939
1940   ASSERT_EQ(0, mirror_instances_add(&ioctx, "instance_id1"));
1941   ASSERT_EQ(0, mirror_instances_add(&ioctx, "instance_id2"));
1942   ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1943   ASSERT_EQ(2U, instance_ids.size());
1944
1945   ASSERT_EQ(0, mirror_instances_remove(&ioctx, "instance_id1"));
1946   ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1947   ASSERT_EQ(1U, instance_ids.size());
1948   ASSERT_EQ(instance_ids[0], "instance_id2");
1949
1950   ASSERT_EQ(0, mirror_instances_remove(&ioctx, "instance_id2"));
1951   ASSERT_EQ(0, mirror_instances_list(&ioctx, &instance_ids));
1952   ASSERT_EQ(0U, instance_ids.size());
1953 }
1954
1955 TEST_F(TestClsRbd, group_create) {
1956   librados::IoCtx ioctx;
1957   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1958
1959   string group_id = "group_id";
1960   ASSERT_EQ(0, group_create(&ioctx, group_id));
1961
1962   uint64_t psize;
1963   time_t pmtime;
1964   ASSERT_EQ(0, ioctx.stat(group_id, &psize, &pmtime));
1965 }
1966
1967 TEST_F(TestClsRbd, group_dir_list) {
1968   librados::IoCtx ioctx;
1969   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
1970
1971   string group_id1 = "cgid1";
1972   string group_name1 = "cgname1";
1973   string group_id2 = "cgid2";
1974   string group_name2 = "cgname2";
1975   ASSERT_EQ(0, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name1, group_id1));
1976   ASSERT_EQ(0, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name2, group_id2));
1977
1978   map<string, string> cgs;
1979   ASSERT_EQ(0, group_dir_list(&ioctx, RBD_GROUP_DIRECTORY, "", 10, &cgs));
1980
1981   ASSERT_EQ(2U, cgs.size());
1982
1983   auto it = cgs.begin();
1984   ASSERT_EQ(group_id1, it->second);
1985   ASSERT_EQ(group_name1, it->first);
1986
1987   ++it;
1988   ASSERT_EQ(group_id2, it->second);
1989   ASSERT_EQ(group_name2, it->first);
1990 }
1991
1992 void add_group_to_dir(librados::IoCtx ioctx, string group_id, string group_name) {
1993   ASSERT_EQ(0, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
1994
1995   set<string> keys;
1996   ASSERT_EQ(0, ioctx.omap_get_keys(RBD_GROUP_DIRECTORY, "", 10, &keys));
1997   ASSERT_EQ(2U, keys.size());
1998   ASSERT_EQ("id_" + group_id, *keys.begin());
1999   ASSERT_EQ("name_" + group_name, *keys.rbegin());
2000 }
2001
2002 TEST_F(TestClsRbd, group_dir_add) {
2003   librados::IoCtx ioctx;
2004   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2005   ioctx.remove(RBD_GROUP_DIRECTORY);
2006
2007   string group_id = "cgid";
2008   string group_name = "cgname";
2009   add_group_to_dir(ioctx, group_id, group_name);
2010 }
2011
2012 TEST_F(TestClsRbd, dir_add_already_existing) {
2013   librados::IoCtx ioctx;
2014   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2015   ioctx.remove(RBD_GROUP_DIRECTORY);
2016
2017   string group_id = "cgidexisting";
2018   string group_name = "cgnameexisting";
2019   add_group_to_dir(ioctx, group_id, group_name);
2020
2021   ASSERT_EQ(-EEXIST, group_dir_add(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2022 }
2023
2024 TEST_F(TestClsRbd, group_dir_remove) {
2025   librados::IoCtx ioctx;
2026   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2027   ioctx.remove(RBD_GROUP_DIRECTORY);
2028
2029   string group_id = "cgidtodel";
2030   string group_name = "cgnametodel";
2031   add_group_to_dir(ioctx, group_id, group_name);
2032
2033   ASSERT_EQ(0, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2034
2035   set<string> keys;
2036   ASSERT_EQ(0, ioctx.omap_get_keys(RBD_GROUP_DIRECTORY, "", 10, &keys));
2037   ASSERT_EQ(0U, keys.size());
2038 }
2039
2040 TEST_F(TestClsRbd, group_dir_remove_missing) {
2041   librados::IoCtx ioctx;
2042   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2043   ioctx.remove(RBD_GROUP_DIRECTORY);
2044
2045   string group_id = "cgidtodelmissing";
2046   string group_name = "cgnametodelmissing";
2047   // These two lines ensure that RBD_GROUP_DIRECTORY exists. It's important for the
2048   // last two lines.
2049   add_group_to_dir(ioctx, group_id, group_name);
2050
2051   ASSERT_EQ(0, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2052
2053   // Removing missing
2054   ASSERT_EQ(-ENOENT, group_dir_remove(&ioctx, RBD_GROUP_DIRECTORY, group_name, group_id));
2055
2056   set<string> keys;
2057   ASSERT_EQ(0, ioctx.omap_get_keys(RBD_GROUP_DIRECTORY, "", 10, &keys));
2058   ASSERT_EQ(0U, keys.size());
2059 }
2060
2061 void test_image_add(librados::IoCtx &ioctx, const string& group_id,
2062                     const string& image_id, int64_t pool_id) {
2063
2064   cls::rbd::GroupImageStatus st(image_id, pool_id,
2065                                cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE);
2066   ASSERT_EQ(0, group_image_set(&ioctx, group_id, st));
2067
2068   set<string> keys;
2069   ASSERT_EQ(0, ioctx.omap_get_keys(group_id, "", 10, &keys));
2070
2071   auto it = keys.begin();
2072   ASSERT_EQ(2U, keys.size());
2073
2074   string image_key = cls::rbd::GroupImageSpec(image_id, pool_id).image_key();
2075   ASSERT_EQ(image_key, *it);
2076   ++it;
2077   ASSERT_EQ("snap_seq", *it);
2078 }
2079
2080 TEST_F(TestClsRbd, group_image_add) {
2081   librados::IoCtx ioctx;
2082   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2083
2084   string group_id = "group_id";
2085   ASSERT_EQ(0, group_create(&ioctx, group_id));
2086
2087   int64_t pool_id = ioctx.get_id();
2088   string image_id = "image_id";
2089   test_image_add(ioctx, group_id, image_id, pool_id);
2090 }
2091
2092 TEST_F(TestClsRbd, group_image_remove) {
2093   librados::IoCtx ioctx;
2094   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2095
2096   string group_id = "group_id";
2097   ASSERT_EQ(0, group_create(&ioctx, group_id));
2098
2099   int64_t pool_id = ioctx.get_id();
2100   string image_id = "image_id";
2101   test_image_add(ioctx, group_id, image_id, pool_id);
2102
2103   cls::rbd::GroupImageSpec spec(image_id, pool_id);
2104   ASSERT_EQ(0, group_image_remove(&ioctx, group_id, spec));
2105   set<string> keys;
2106   ASSERT_EQ(0, ioctx.omap_get_keys(group_id, "", 10, &keys));
2107   ASSERT_EQ(1U, keys.size());
2108   ASSERT_EQ("snap_seq", *(keys.begin()));
2109 }
2110
2111 TEST_F(TestClsRbd, group_image_list) {
2112   librados::IoCtx ioctx;
2113   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2114
2115   string group_id = "group_id";
2116   ASSERT_EQ(0, group_create(&ioctx, group_id));
2117
2118   int64_t pool_id = ioctx.get_id();
2119   string image_id = "imageid"; // Image id shouldn't contain underscores
2120   test_image_add(ioctx, group_id, image_id, pool_id);
2121
2122   vector<cls::rbd::GroupImageStatus> images;
2123   cls::rbd::GroupImageSpec empty_image_spec = cls::rbd::GroupImageSpec();
2124   ASSERT_EQ(0, group_image_list(&ioctx, group_id, empty_image_spec, 1024,
2125                                 &images));
2126   ASSERT_EQ(1U, images.size());
2127   ASSERT_EQ(image_id, images[0].spec.image_id);
2128   ASSERT_EQ(pool_id, images[0].spec.pool_id);
2129   ASSERT_EQ(cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE, images[0].state);
2130
2131   cls::rbd::GroupImageStatus last_image = *images.rbegin();
2132   ASSERT_EQ(0, group_image_list(&ioctx, group_id, last_image.spec, 1024,
2133                                 &images));
2134   ASSERT_EQ(0U, images.size());
2135 }
2136
2137 TEST_F(TestClsRbd, group_image_clean) {
2138   librados::IoCtx ioctx;
2139   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2140
2141   string group_id = "group_id1";
2142   ASSERT_EQ(0, group_create(&ioctx, group_id));
2143
2144   int64_t pool_id = ioctx.get_id();
2145   string image_id = "image_id";
2146   test_image_add(ioctx, group_id, image_id, pool_id);
2147
2148   cls::rbd::GroupImageStatus incomplete_st(image_id, pool_id,
2149                                cls::rbd::GROUP_IMAGE_LINK_STATE_INCOMPLETE);
2150
2151   ASSERT_EQ(0, group_image_set(&ioctx, group_id, incomplete_st));
2152   // Set to dirty first in order to make sure that group_image_clean
2153   // actually does something.
2154   cls::rbd::GroupImageStatus attached_st(image_id, pool_id,
2155                                cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED);
2156   ASSERT_EQ(0, group_image_set(&ioctx, group_id, attached_st));
2157
2158   string image_key = cls::rbd::GroupImageSpec(image_id, pool_id).image_key();
2159
2160   map<string, bufferlist> vals;
2161   ASSERT_EQ(0, ioctx.omap_get_vals(group_id, "", 10, &vals));
2162
2163   cls::rbd::GroupImageLinkState ref_state;
2164   bufferlist::iterator it = vals[image_key].begin();
2165   ::decode(ref_state, it);
2166   ASSERT_EQ(cls::rbd::GROUP_IMAGE_LINK_STATE_ATTACHED, ref_state);
2167 }
2168
2169 TEST_F(TestClsRbd, image_add_group) {
2170   librados::IoCtx ioctx;
2171   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2172
2173   int64_t pool_id = ioctx.get_id();
2174   string image_id = "imageid";
2175
2176   ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2177                             RBD_FEATURE_LAYERING, image_id, -1));
2178
2179   string group_id = "group_id";
2180
2181   cls::rbd::GroupSpec spec(group_id, pool_id);
2182   ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec));
2183
2184   map<string, bufferlist> vals;
2185   ASSERT_EQ(0, ioctx.omap_get_vals(image_id, "", RBD_GROUP_REF, 10, &vals));
2186
2187   cls::rbd::GroupSpec val_spec;
2188   bufferlist::iterator it = vals[RBD_GROUP_REF].begin();
2189   ::decode(val_spec, it);
2190
2191   ASSERT_EQ(group_id, val_spec.group_id);
2192   ASSERT_EQ(pool_id, val_spec.pool_id);
2193 }
2194
2195 TEST_F(TestClsRbd, image_remove_group) {
2196   librados::IoCtx ioctx;
2197   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2198
2199   int64_t pool_id = ioctx.get_id();
2200   string image_id = "image_id";
2201
2202   ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2203                             RBD_FEATURE_LAYERING, image_id, -1));
2204
2205   string group_id = "group_id";
2206
2207   cls::rbd::GroupSpec spec(group_id, pool_id);
2208   ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec));
2209   // Add reference in order to make sure that image_remove_group actually
2210   // does something.
2211   ASSERT_EQ(0, image_remove_group(&ioctx, image_id, spec));
2212
2213   map<string, bufferlist> vals;
2214   ASSERT_EQ(0, ioctx.omap_get_vals(image_id, "", RBD_GROUP_REF, 10, &vals));
2215
2216   ASSERT_EQ(0U, vals.size());
2217 }
2218
2219 TEST_F(TestClsRbd, image_get_group) {
2220   librados::IoCtx ioctx;
2221   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2222
2223   int64_t pool_id = ioctx.get_id();
2224   string image_id = "imageidgroupspec";
2225
2226   ASSERT_EQ(0, create_image(&ioctx, image_id, 2<<20, 0,
2227                             RBD_FEATURE_LAYERING, image_id, -1));
2228
2229   string group_id = "group_id_get_group_spec";
2230
2231   cls::rbd::GroupSpec spec_add(group_id, pool_id);
2232   ASSERT_EQ(0, image_add_group(&ioctx, image_id, spec_add));
2233
2234   cls::rbd::GroupSpec spec;
2235   ASSERT_EQ(0, image_get_group(&ioctx, image_id, &spec));
2236
2237   ASSERT_EQ(group_id, spec.group_id);
2238   ASSERT_EQ(pool_id, spec.pool_id);
2239 }
2240
2241 TEST_F(TestClsRbd, trash_methods)
2242 {
2243   librados::IoCtx ioctx;
2244   ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
2245
2246   string id = "123456789";
2247   string id2 = "123456780";
2248
2249   std::map<string, cls::rbd::TrashImageSpec> entries;
2250   ASSERT_EQ(-ENOENT, trash_list(&ioctx, "", 1024, &entries));
2251
2252   utime_t now1 = ceph_clock_now();
2253   utime_t now1_delay = now1;
2254   now1_delay += 380;
2255   cls::rbd::TrashImageSpec trash_spec(cls::rbd::TRASH_IMAGE_SOURCE_USER, "name",
2256                                       now1, now1_delay);
2257   ASSERT_EQ(0, trash_add(&ioctx, id, trash_spec));
2258
2259   utime_t now2 = ceph_clock_now();
2260   utime_t now2_delay = now2;
2261   now2_delay += 480;
2262   cls::rbd::TrashImageSpec trash_spec2(cls::rbd::TRASH_IMAGE_SOURCE_MIRRORING,
2263                                        "name2", now2, now2_delay);
2264   ASSERT_EQ(-EEXIST, trash_add(&ioctx, id, trash_spec2));
2265
2266   ASSERT_EQ(0, trash_remove(&ioctx, id));
2267   ASSERT_EQ(-ENOENT, trash_remove(&ioctx, id));
2268
2269   ASSERT_EQ(0, trash_list(&ioctx, "", 1024, &entries));
2270   ASSERT_TRUE(entries.empty());
2271
2272   ASSERT_EQ(0, trash_add(&ioctx, id, trash_spec2));
2273   ASSERT_EQ(0, trash_add(&ioctx, id2, trash_spec));
2274
2275   ASSERT_EQ(0, trash_list(&ioctx, "", 1, &entries));
2276   ASSERT_TRUE(entries.find(id2) != entries.end());
2277   ASSERT_EQ(cls::rbd::TRASH_IMAGE_SOURCE_USER, entries[id2].source);
2278   ASSERT_EQ(std::string("name"), entries[id2].name);
2279   ASSERT_EQ(now1, entries[id2].deletion_time);
2280   ASSERT_EQ(now1_delay, entries[id2].deferment_end_time);
2281
2282   ASSERT_EQ(0, trash_list(&ioctx, id2, 1, &entries));
2283   ASSERT_TRUE(entries.find(id) != entries.end());
2284   ASSERT_EQ(cls::rbd::TRASH_IMAGE_SOURCE_MIRRORING, entries[id].source);
2285   ASSERT_EQ(std::string("name2"), entries[id].name);
2286   ASSERT_EQ(now2, entries[id].deletion_time);
2287   ASSERT_EQ(now2_delay, entries[id].deferment_end_time);
2288
2289   ASSERT_EQ(0, trash_list(&ioctx, id, 1, &entries));
2290   ASSERT_TRUE(entries.empty());
2291
2292   cls::rbd::TrashImageSpec spec_res1;
2293   ASSERT_EQ(0, trash_get(&ioctx, id, &spec_res1));
2294   cls::rbd::TrashImageSpec spec_res2;
2295   ASSERT_EQ(0, trash_get(&ioctx, id2, &spec_res2));
2296
2297   ASSERT_EQ(spec_res1.name, "name2");
2298   ASSERT_EQ(spec_res1.deletion_time, now2);
2299   ASSERT_EQ(spec_res1.deferment_end_time, now2_delay);
2300
2301   ASSERT_EQ(spec_res2.name, "name");
2302   ASSERT_EQ(spec_res2.deletion_time, now1);
2303   ASSERT_EQ(spec_res2.deferment_end_time, now1_delay);
2304
2305   ioctx.close();
2306 }
2307