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