1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 SUSE LINUX GmbH
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
14 #include "test/librbd/test_fixture.h"
15 #include "test/librbd/test_support.h"
16 #include "librbd/ExclusiveLock.h"
17 #include "librbd/ImageState.h"
18 #include "librbd/ImageWatcher.h"
19 #include "librbd/internal.h"
20 #include "librbd/ObjectMap.h"
21 #include "librbd/Operations.h"
22 #include "librbd/api/Image.h"
23 #include "librbd/api/Namespace.h"
24 #include "librbd/io/AioCompletion.h"
25 #include "librbd/io/ImageRequest.h"
26 #include "librbd/io/ImageRequestWQ.h"
27 #include "librbd/journal/Types.h"
28 #include "librbd/mirror/snapshot/GetImageStateRequest.h"
29 #include "librbd/mirror/snapshot/RemoveImageStateRequest.h"
30 #include "librbd/mirror/snapshot/SetImageStateRequest.h"
31 #include "librbd/mirror/snapshot/UnlinkPeerRequest.h"
32 #include "journal/Journaler.h"
33 #include "journal/Settings.h"
34 #include "common/Cond.h"
35 #include <boost/scope_exit.hpp>
36 #include <boost/assign/list_of.hpp>
40 void register_test_mirroring() {
45 static bool operator==(const mirror_peer_site_t
& lhs
,
46 const mirror_peer_site_t
& rhs
) {
47 return (lhs
.uuid
== rhs
.uuid
&&
48 lhs
.direction
== rhs
.direction
&&
49 lhs
.site_name
== rhs
.site_name
&&
50 lhs
.client_name
== rhs
.client_name
&&
51 lhs
.last_seen
== rhs
.last_seen
);
54 static std::ostream
& operator<<(std::ostream
& os
,
55 const mirror_peer_site_t
& rhs
) {
56 os
<< "uuid=" << rhs
.uuid
<< ", "
57 << "direction=" << rhs
.direction
<< ", "
58 << "site_name=" << rhs
.site_name
<< ", "
59 << "client_name=" << rhs
.client_name
<< ", "
60 << "last_seen=" << rhs
.last_seen
;
66 class TestMirroring
: public TestFixture
{
72 void TearDown() override
{
75 TestFixture::TearDown();
78 void SetUp() override
{
79 ASSERT_EQ(0, _rados
.ioctx_create(_pool_name
.c_str(), m_ioctx
));
82 std::string image_name
= "mirrorimg1";
84 int get_local_mirror_image_site_status(
85 const librbd::mirror_image_global_status_t
& status
,
86 librbd::mirror_image_site_status_t
* local_status
) {
87 auto it
= std::find_if(status
.site_statuses
.begin(),
88 status
.site_statuses
.end(),
89 [](auto& site_status
) {
90 return (site_status
.mirror_uuid
==
91 RBD_MIRROR_IMAGE_STATUS_LOCAL_MIRROR_UUID
);
93 if (it
== status
.site_statuses
.end()) {
101 void check_mirror_image_enable(
102 rbd_mirror_mode_t mirror_mode
, uint64_t features
, int expected_r
,
103 rbd_mirror_image_state_t mirror_state
,
104 rbd_mirror_image_mode_t mirror_image_mode
= RBD_MIRROR_IMAGE_MODE_JOURNAL
) {
106 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
109 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
, &order
));
111 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
113 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, mirror_mode
));
115 ASSERT_EQ(expected_r
, image
.mirror_image_enable2(mirror_image_mode
));
117 librbd::mirror_image_info_t mirror_image
;
118 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
, sizeof(mirror_image
)));
119 ASSERT_EQ(mirror_state
, mirror_image
.state
);
121 if (mirror_image
.state
== RBD_MIRROR_IMAGE_ENABLED
) {
122 librbd::mirror_image_mode_t mode
;
123 ASSERT_EQ(0, image
.mirror_image_get_mode(&mode
));
124 ASSERT_EQ(mirror_image_mode
, mode
);
127 librbd::mirror_image_global_status_t status
;
128 ASSERT_EQ(0, image
.mirror_image_get_global_status(&status
, sizeof(status
)));
129 librbd::mirror_image_site_status_t local_status
;
130 ASSERT_EQ(0, get_local_mirror_image_site_status(status
, &local_status
));
131 ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN
, local_status
.state
);
133 std::string instance_id
;
134 ASSERT_EQ(mirror_state
== RBD_MIRROR_IMAGE_ENABLED
? -ENOENT
: -EINVAL
,
135 image
.mirror_image_get_instance_id(&instance_id
));
137 ASSERT_EQ(0, image
.close());
138 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
139 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
142 void check_mirror_image_disable(rbd_mirror_mode_t mirror_mode
,
145 rbd_mirror_image_state_t mirror_state
) {
147 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_POOL
));
150 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
, &order
));
152 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
154 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, mirror_mode
));
156 ASSERT_EQ(expected_r
, image
.mirror_image_disable(false));
158 librbd::mirror_image_info_t mirror_image
;
159 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
, sizeof(mirror_image
)));
160 ASSERT_EQ(mirror_state
, mirror_image
.state
);
162 librbd::mirror_image_global_status_t status
;
163 ASSERT_EQ(0, image
.mirror_image_get_global_status(&status
, sizeof(status
)));
164 librbd::mirror_image_site_status_t local_status
;
165 ASSERT_EQ(0, get_local_mirror_image_site_status(status
, &local_status
));
166 ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN
, local_status
.state
);
168 std::string instance_id
;
169 ASSERT_EQ(mirror_state
== RBD_MIRROR_IMAGE_ENABLED
? -ENOENT
: -EINVAL
,
170 image
.mirror_image_get_instance_id(&instance_id
));
172 ASSERT_EQ(0, image
.close());
173 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
174 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
177 void check_mirroring_status(size_t *images_count
) {
178 std::map
<std::string
, librbd::mirror_image_global_status_t
> images
;
179 ASSERT_EQ(0, m_rbd
.mirror_image_global_status_list(m_ioctx
, "", 4096,
182 std::map
<librbd::mirror_image_status_state_t
, int> states
;
183 ASSERT_EQ(0, m_rbd
.mirror_image_status_summary(m_ioctx
, &states
));
184 size_t states_count
= 0;
185 for (auto &s
: states
) {
186 states_count
+= s
.second
;
188 ASSERT_EQ(images
.size(), states_count
);
190 *images_count
= images
.size();
192 std::map
<std::string
, std::string
> instance_ids
;
193 ASSERT_EQ(0, m_rbd
.mirror_image_instance_id_list(m_ioctx
, "", 4096,
195 ASSERT_TRUE(instance_ids
.empty());
198 void check_mirroring_on_create(uint64_t features
,
199 rbd_mirror_mode_t mirror_mode
,
200 rbd_mirror_image_state_t mirror_state
) {
202 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, mirror_mode
));
204 size_t mirror_images_count
= 0;
205 check_mirroring_status(&mirror_images_count
);
208 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
, &order
));
210 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
212 librbd::mirror_image_info_t mirror_image
;
213 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
, sizeof(mirror_image
)));
214 ASSERT_EQ(mirror_state
, mirror_image
.state
);
216 librbd::mirror_image_global_status_t status
;
217 ASSERT_EQ(0, image
.mirror_image_get_global_status(&status
, sizeof(status
)));
218 librbd::mirror_image_site_status_t local_status
;
219 ASSERT_EQ(0, get_local_mirror_image_site_status(status
, &local_status
));
220 ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN
, local_status
.state
);
222 size_t mirror_images_new_count
= 0;
223 check_mirroring_status(&mirror_images_new_count
);
224 if (mirror_mode
== RBD_MIRROR_MODE_POOL
&&
225 mirror_state
== RBD_MIRROR_IMAGE_ENABLED
) {
226 ASSERT_EQ(mirror_images_new_count
, mirror_images_count
+ 1);
228 ASSERT_EQ(mirror_images_new_count
, mirror_images_count
);
231 ASSERT_EQ(0, image
.close());
232 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
233 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
235 check_mirroring_status(&mirror_images_new_count
);
236 ASSERT_EQ(mirror_images_new_count
, mirror_images_count
);
239 void check_mirroring_on_update_features(
240 uint64_t init_features
, bool enable
, bool enable_mirroring
,
241 uint64_t features
, int expected_r
, rbd_mirror_mode_t mirror_mode
,
242 rbd_mirror_image_state_t mirror_state
,
243 rbd_mirror_image_mode_t mirror_image_mode
= RBD_MIRROR_IMAGE_MODE_JOURNAL
) {
245 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, mirror_mode
));
248 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, init_features
, &order
));
250 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
252 if (enable_mirroring
) {
253 ASSERT_EQ(0, image
.mirror_image_enable2(mirror_image_mode
));
256 ASSERT_EQ(expected_r
, image
.update_features(features
, enable
));
258 librbd::mirror_image_info_t mirror_image
;
259 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
, sizeof(mirror_image
)));
260 ASSERT_EQ(mirror_state
, mirror_image
.state
);
262 if (mirror_image
.state
== RBD_MIRROR_IMAGE_ENABLED
) {
263 librbd::mirror_image_mode_t mode
;
264 ASSERT_EQ(0, image
.mirror_image_get_mode(&mode
));
265 ASSERT_EQ(mirror_image_mode
, mode
);
268 librbd::mirror_image_global_status_t status
;
269 ASSERT_EQ(0, image
.mirror_image_get_global_status(&status
, sizeof(status
)));
270 librbd::mirror_image_site_status_t local_status
;
271 ASSERT_EQ(0, get_local_mirror_image_site_status(status
, &local_status
));
272 ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN
, local_status
.state
);
274 ASSERT_EQ(0, image
.close());
275 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
276 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
279 void setup_images_with_mirror_mode(rbd_mirror_mode_t mirror_mode
,
280 std::vector
<uint64_t>& features_vec
) {
282 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, mirror_mode
));
286 for (const auto& features
: features_vec
) {
287 std::stringstream
img_name("img_");
289 std::string img_name_str
= img_name
.str();
290 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, img_name_str
.c_str(), 2048, features
, &order
));
294 void check_mirroring_on_mirror_mode_set(rbd_mirror_mode_t mirror_mode
,
295 std::vector
<rbd_mirror_image_state_t
>& states_vec
) {
297 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, mirror_mode
));
299 std::vector
< std::tuple
<std::string
, rbd_mirror_image_state_t
> > images
;
301 for (const auto& mirror_state
: states_vec
) {
302 std::stringstream
img_name("img_");
304 std::string img_name_str
= img_name
.str();
306 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, img_name_str
.c_str()));
307 images
.push_back(std::make_tuple(img_name_str
, mirror_state
));
309 librbd::mirror_image_info_t mirror_image
;
310 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
, sizeof(mirror_image
)));
311 ASSERT_EQ(mirror_state
, mirror_image
.state
);
313 librbd::mirror_image_global_status_t status
;
314 ASSERT_EQ(0, image
.mirror_image_get_global_status(&status
,
316 librbd::mirror_image_site_status_t local_status
;
317 ASSERT_EQ(0, get_local_mirror_image_site_status(status
, &local_status
));
318 ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN
, local_status
.state
);
320 ASSERT_EQ(0, image
.close());
321 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, img_name_str
.c_str()));
325 void check_remove_image(rbd_mirror_mode_t mirror_mode
, uint64_t features
,
326 bool enable_mirroring
, bool demote
= false) {
328 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, mirror_mode
));
331 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
334 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
336 if (enable_mirroring
) {
337 ASSERT_EQ(0, image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL
));
341 ASSERT_EQ(0, image
.mirror_image_demote());
342 ASSERT_EQ(0, image
.mirror_image_disable(true));
346 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
347 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
350 void check_trash_move_restore(rbd_mirror_mode_t mirror_mode
,
351 bool enable_mirroring
) {
353 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, mirror_mode
));
356 uint64_t features
= RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
;
357 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
360 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
362 if (enable_mirroring
) {
363 ASSERT_EQ(0, image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL
));
366 std::string image_id
;
367 ASSERT_EQ(0, image
.get_id(&image_id
));
370 ASSERT_EQ(0, m_rbd
.trash_move(m_ioctx
, image_name
.c_str(), 100));
372 ASSERT_EQ(0, m_rbd
.open_by_id(m_ioctx
, image
, image_id
.c_str(), NULL
));
374 librbd::mirror_image_info_t mirror_image
;
375 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
, sizeof(mirror_image
)));
376 ASSERT_EQ(mirror_image
.state
, RBD_MIRROR_IMAGE_DISABLED
);
378 ASSERT_EQ(0, m_rbd
.trash_restore(m_ioctx
, image_id
.c_str(), ""));
380 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
, sizeof(mirror_image
)));
381 if (mirror_mode
== RBD_MIRROR_MODE_POOL
) {
382 ASSERT_EQ(mirror_image
.state
, RBD_MIRROR_IMAGE_ENABLED
);
384 ASSERT_EQ(mirror_image
.state
, RBD_MIRROR_IMAGE_DISABLED
);
388 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
389 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
392 void setup_mirror_peer(librados::IoCtx
&io_ctx
, librbd::Image
&image
) {
393 ASSERT_EQ(0, image
.snap_create("sync-point-snap"));
395 std::string image_id
;
396 ASSERT_EQ(0, get_image_id(image
, &image_id
));
398 librbd::journal::MirrorPeerClientMeta
peer_client_meta(
399 "remote-image-id", {{{}, "sync-point-snap", boost::none
}}, {});
400 librbd::journal::ClientData
client_data(peer_client_meta
);
402 journal::Journaler
journaler(io_ctx
, image_id
, "peer-client", {}, nullptr);
403 C_SaferCond init_ctx
;
404 journaler
.init(&init_ctx
);
405 ASSERT_EQ(-ENOENT
, init_ctx
.wait());
407 bufferlist client_data_bl
;
408 encode(client_data
, client_data_bl
);
409 ASSERT_EQ(0, journaler
.register_client(client_data_bl
));
411 C_SaferCond shut_down_ctx
;
412 journaler
.shut_down(&shut_down_ctx
);
413 ASSERT_EQ(0, shut_down_ctx
.wait());
418 TEST_F(TestMirroring
, EnableImageMirror_In_MirrorModeImage
) {
419 uint64_t features
= 0;
420 features
|= RBD_FEATURE_OBJECT_MAP
;
421 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
422 features
|= RBD_FEATURE_JOURNALING
;
423 check_mirror_image_enable(RBD_MIRROR_MODE_IMAGE
, features
, 0,
424 RBD_MIRROR_IMAGE_ENABLED
, RBD_MIRROR_IMAGE_MODE_JOURNAL
);
427 TEST_F(TestMirroring
, EnableImageMirror_In_MirrorModePool
) {
428 uint64_t features
= 0;
429 features
|= RBD_FEATURE_OBJECT_MAP
;
430 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
431 features
|= RBD_FEATURE_JOURNALING
;
432 check_mirror_image_enable(RBD_MIRROR_MODE_POOL
, features
, -EINVAL
,
433 RBD_MIRROR_IMAGE_ENABLED
, RBD_MIRROR_IMAGE_MODE_JOURNAL
);
436 TEST_F(TestMirroring
, EnableImageMirror_In_MirrorModeDisabled
) {
437 uint64_t features
= 0;
438 features
|= RBD_FEATURE_OBJECT_MAP
;
439 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
440 features
|= RBD_FEATURE_JOURNALING
;
441 check_mirror_image_enable(RBD_MIRROR_MODE_DISABLED
, features
, -EINVAL
,
442 RBD_MIRROR_IMAGE_DISABLED
);
445 TEST_F(TestMirroring
, DisableImageMirror_In_MirrorModeImage
) {
446 uint64_t features
= 0;
447 features
|= RBD_FEATURE_OBJECT_MAP
;
448 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
449 features
|= RBD_FEATURE_JOURNALING
;
450 check_mirror_image_disable(RBD_MIRROR_MODE_IMAGE
, features
, 0,
451 RBD_MIRROR_IMAGE_DISABLED
);
454 TEST_F(TestMirroring
, DisableImageMirror_In_MirrorModeImage_NoObjectMap
) {
455 uint64_t features
= 0;
456 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
457 features
|= RBD_FEATURE_JOURNALING
;
458 check_mirror_image_disable(RBD_MIRROR_MODE_IMAGE
, features
, 0,
459 RBD_MIRROR_IMAGE_DISABLED
);
462 TEST_F(TestMirroring
, DisableImageMirror_In_MirrorModePool
) {
463 uint64_t features
= 0;
464 features
|= RBD_FEATURE_OBJECT_MAP
;
465 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
466 features
|= RBD_FEATURE_JOURNALING
;
467 check_mirror_image_disable(RBD_MIRROR_MODE_POOL
, features
, -EINVAL
,
468 RBD_MIRROR_IMAGE_ENABLED
);
471 TEST_F(TestMirroring
, DisableImageMirror_In_MirrorModeDisabled
) {
472 uint64_t features
= 0;
473 features
|= RBD_FEATURE_OBJECT_MAP
;
474 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
475 features
|= RBD_FEATURE_JOURNALING
;
476 check_mirror_image_disable(RBD_MIRROR_MODE_DISABLED
, features
, -EINVAL
,
477 RBD_MIRROR_IMAGE_DISABLED
);
480 TEST_F(TestMirroring
, DisableImageMirrorWithPeer
) {
481 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
483 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_IMAGE
));
485 uint64_t features
= RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
;
487 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
491 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
492 ASSERT_EQ(0, image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_JOURNAL
));
494 setup_mirror_peer(m_ioctx
, image
);
496 ASSERT_EQ(0, image
.mirror_image_disable(false));
498 std::vector
<librbd::snap_info_t
> snaps
;
499 ASSERT_EQ(0, image
.snap_list(snaps
));
500 ASSERT_TRUE(snaps
.empty());
502 librbd::mirror_image_info_t mirror_image
;
503 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
,
504 sizeof(mirror_image
)));
505 ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED
, mirror_image
.state
);
507 librbd::mirror_image_global_status_t status
;
508 ASSERT_EQ(0, image
.mirror_image_get_global_status(&status
, sizeof(status
)));
509 librbd::mirror_image_site_status_t local_status
;
510 ASSERT_EQ(0, get_local_mirror_image_site_status(status
, &local_status
));
511 ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN
, local_status
.state
);
513 ASSERT_EQ(0, image
.close());
514 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
515 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
518 TEST_F(TestMirroring
, DisableJournalingWithPeer
) {
519 REQUIRE_FEATURE(RBD_FEATURE_JOURNALING
);
521 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_POOL
));
523 uint64_t features
= RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
;
525 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
529 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
531 setup_mirror_peer(m_ioctx
, image
);
533 ASSERT_EQ(0, image
.update_features(RBD_FEATURE_JOURNALING
, false));
535 std::vector
<librbd::snap_info_t
> snaps
;
536 ASSERT_EQ(0, image
.snap_list(snaps
));
537 ASSERT_TRUE(snaps
.empty());
539 librbd::mirror_image_info_t mirror_image
;
540 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
,
541 sizeof(mirror_image
)));
542 ASSERT_EQ(RBD_MIRROR_IMAGE_DISABLED
, mirror_image
.state
);
544 librbd::mirror_image_global_status_t status
;
545 ASSERT_EQ(0, image
.mirror_image_get_global_status(&status
, sizeof(status
)));
546 librbd::mirror_image_site_status_t local_status
;
547 ASSERT_EQ(0, get_local_mirror_image_site_status(status
, &local_status
));
548 ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN
, local_status
.state
);
550 ASSERT_EQ(0, image
.close());
551 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
552 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
555 TEST_F(TestMirroring
, EnableImageMirror_In_MirrorModeDisabled_WithoutJournaling
) {
556 uint64_t features
= 0;
557 features
|= RBD_FEATURE_OBJECT_MAP
;
558 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
559 check_mirror_image_enable(RBD_MIRROR_MODE_DISABLED
, features
, -EINVAL
,
560 RBD_MIRROR_IMAGE_DISABLED
);
563 TEST_F(TestMirroring
, EnableImageMirror_In_MirrorModePool_WithoutJournaling
) {
564 uint64_t features
= 0;
565 features
|= RBD_FEATURE_OBJECT_MAP
;
566 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
567 check_mirror_image_enable(RBD_MIRROR_MODE_POOL
, features
, -EINVAL
,
568 RBD_MIRROR_IMAGE_DISABLED
);
571 TEST_F(TestMirroring
, EnableImageMirror_In_MirrorModeImage_WithoutJournaling
) {
572 uint64_t features
= 0;
573 features
|= RBD_FEATURE_OBJECT_MAP
;
574 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
575 check_mirror_image_enable(RBD_MIRROR_MODE_IMAGE
, features
, 0,
576 RBD_MIRROR_IMAGE_ENABLED
, RBD_MIRROR_IMAGE_MODE_SNAPSHOT
);
579 TEST_F(TestMirroring
, EnableImageMirror_In_MirrorModeImage_WithoutExclusiveLock
) {
580 uint64_t features
= 0;
581 check_mirror_image_enable(RBD_MIRROR_MODE_IMAGE
, features
, 0,
582 RBD_MIRROR_IMAGE_ENABLED
, RBD_MIRROR_IMAGE_MODE_SNAPSHOT
);
585 TEST_F(TestMirroring
, CreateImage_In_MirrorModeDisabled
) {
586 uint64_t features
= 0;
587 features
|= RBD_FEATURE_OBJECT_MAP
;
588 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
589 features
|= RBD_FEATURE_JOURNALING
;
590 check_mirroring_on_create(features
, RBD_MIRROR_MODE_DISABLED
,
591 RBD_MIRROR_IMAGE_DISABLED
);
594 TEST_F(TestMirroring
, CreateImage_In_MirrorModeImage
) {
595 uint64_t features
= 0;
596 features
|= RBD_FEATURE_OBJECT_MAP
;
597 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
598 features
|= RBD_FEATURE_JOURNALING
;
599 check_mirroring_on_create(features
, RBD_MIRROR_MODE_IMAGE
,
600 RBD_MIRROR_IMAGE_DISABLED
);
603 TEST_F(TestMirroring
, CreateImage_In_MirrorModePool
) {
604 uint64_t features
= 0;
605 features
|= RBD_FEATURE_OBJECT_MAP
;
606 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
607 features
|= RBD_FEATURE_JOURNALING
;
608 check_mirroring_on_create(features
, RBD_MIRROR_MODE_POOL
,
609 RBD_MIRROR_IMAGE_ENABLED
);
612 TEST_F(TestMirroring
, CreateImage_In_MirrorModePool_WithoutJournaling
) {
613 uint64_t features
= 0;
614 features
|= RBD_FEATURE_OBJECT_MAP
;
615 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
616 check_mirroring_on_create(features
, RBD_MIRROR_MODE_POOL
,
617 RBD_MIRROR_IMAGE_DISABLED
);
620 TEST_F(TestMirroring
, CreateImage_In_MirrorModeImage_WithoutJournaling
) {
621 uint64_t features
= 0;
622 features
|= RBD_FEATURE_OBJECT_MAP
;
623 features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
624 check_mirroring_on_create(features
, RBD_MIRROR_MODE_IMAGE
,
625 RBD_MIRROR_IMAGE_DISABLED
);
628 TEST_F(TestMirroring
, EnableJournaling_In_MirrorModeDisabled
) {
629 uint64_t init_features
= 0;
630 init_features
|= RBD_FEATURE_OBJECT_MAP
;
631 init_features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
632 uint64_t features
= RBD_FEATURE_JOURNALING
;
633 check_mirroring_on_update_features(init_features
, true, false, features
, 0,
634 RBD_MIRROR_MODE_DISABLED
, RBD_MIRROR_IMAGE_DISABLED
);
637 TEST_F(TestMirroring
, EnableJournaling_In_MirrorModeImage
) {
638 uint64_t init_features
= 0;
639 init_features
|= RBD_FEATURE_OBJECT_MAP
;
640 init_features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
641 uint64_t features
= RBD_FEATURE_JOURNALING
;
642 check_mirroring_on_update_features(init_features
, true, false, features
, 0,
643 RBD_MIRROR_MODE_IMAGE
, RBD_MIRROR_IMAGE_DISABLED
);
646 TEST_F(TestMirroring
, EnableJournaling_In_MirrorModeImage_SnapshotMirroringEnabled
) {
647 uint64_t init_features
= 0;
648 init_features
|= RBD_FEATURE_OBJECT_MAP
;
649 init_features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
650 uint64_t features
= RBD_FEATURE_JOURNALING
;
651 check_mirroring_on_update_features(init_features
, true, true, features
,
652 0, RBD_MIRROR_MODE_IMAGE
, RBD_MIRROR_IMAGE_ENABLED
,
653 RBD_MIRROR_IMAGE_MODE_SNAPSHOT
);
656 TEST_F(TestMirroring
, EnableJournaling_In_MirrorModePool
) {
657 uint64_t init_features
= 0;
658 init_features
|= RBD_FEATURE_OBJECT_MAP
;
659 init_features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
660 uint64_t features
= RBD_FEATURE_JOURNALING
;
661 check_mirroring_on_update_features(init_features
, true, false, features
, 0,
662 RBD_MIRROR_MODE_POOL
, RBD_MIRROR_IMAGE_ENABLED
,
663 RBD_MIRROR_IMAGE_MODE_JOURNAL
);
666 TEST_F(TestMirroring
, DisableJournaling_In_MirrorModePool
) {
667 uint64_t init_features
= 0;
668 init_features
|= RBD_FEATURE_OBJECT_MAP
;
669 init_features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
670 init_features
|= RBD_FEATURE_JOURNALING
;
671 uint64_t features
= RBD_FEATURE_JOURNALING
;
672 check_mirroring_on_update_features(init_features
, false, false, features
, 0,
673 RBD_MIRROR_MODE_POOL
, RBD_MIRROR_IMAGE_DISABLED
);
676 TEST_F(TestMirroring
, DisableJournaling_In_MirrorModeImage
) {
677 uint64_t init_features
= 0;
678 init_features
|= RBD_FEATURE_OBJECT_MAP
;
679 init_features
|= RBD_FEATURE_EXCLUSIVE_LOCK
;
680 init_features
|= RBD_FEATURE_JOURNALING
;
681 uint64_t features
= RBD_FEATURE_JOURNALING
;
682 check_mirroring_on_update_features(init_features
, false, true, features
,
683 -EINVAL
, RBD_MIRROR_MODE_IMAGE
, RBD_MIRROR_IMAGE_ENABLED
,
684 RBD_MIRROR_IMAGE_MODE_JOURNAL
);
687 TEST_F(TestMirroring
, MirrorModeSet_DisabledMode_To_PoolMode
) {
688 std::vector
<uint64_t> features_vec
;
689 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
);
690 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
);
692 setup_images_with_mirror_mode(RBD_MIRROR_MODE_DISABLED
, features_vec
);
694 std::vector
<rbd_mirror_image_state_t
> states_vec
;
695 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
696 states_vec
.push_back(RBD_MIRROR_IMAGE_ENABLED
);
697 check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_POOL
, states_vec
);
700 TEST_F(TestMirroring
, MirrorModeSet_PoolMode_To_DisabledMode
) {
701 std::vector
<uint64_t> features_vec
;
702 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
);
703 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
);
705 setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL
, features_vec
);
707 std::vector
<rbd_mirror_image_state_t
> states_vec
;
708 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
709 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
710 check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_DISABLED
, states_vec
);
713 TEST_F(TestMirroring
, MirrorModeSet_DisabledMode_To_ImageMode
) {
714 std::vector
<uint64_t> features_vec
;
715 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
);
716 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
);
718 setup_images_with_mirror_mode(RBD_MIRROR_MODE_DISABLED
, features_vec
);
720 std::vector
<rbd_mirror_image_state_t
> states_vec
;
721 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
722 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
723 check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_IMAGE
, states_vec
);
727 TEST_F(TestMirroring
, MirrorModeSet_PoolMode_To_ImageMode
) {
728 std::vector
<uint64_t> features_vec
;
729 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
);
730 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
);
732 setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL
, features_vec
);
734 std::vector
<rbd_mirror_image_state_t
> states_vec
;
735 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
736 states_vec
.push_back(RBD_MIRROR_IMAGE_ENABLED
);
737 check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_IMAGE
, states_vec
);
740 TEST_F(TestMirroring
, MirrorModeSet_ImageMode_To_PoolMode
) {
741 std::vector
<uint64_t> features_vec
;
742 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
);
743 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
);
745 setup_images_with_mirror_mode(RBD_MIRROR_MODE_IMAGE
, features_vec
);
747 std::vector
<rbd_mirror_image_state_t
> states_vec
;
748 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
749 states_vec
.push_back(RBD_MIRROR_IMAGE_ENABLED
);
750 check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_POOL
, states_vec
);
753 TEST_F(TestMirroring
, MirrorModeSet_ImageMode_To_DisabledMode
) {
754 std::vector
<uint64_t> features_vec
;
755 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
);
756 features_vec
.push_back(RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
);
758 setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL
, features_vec
);
760 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_IMAGE
));
761 ASSERT_EQ(-EINVAL
, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
762 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_POOL
));
764 std::vector
<rbd_mirror_image_state_t
> states_vec
;
765 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
766 states_vec
.push_back(RBD_MIRROR_IMAGE_DISABLED
);
767 check_mirroring_on_mirror_mode_set(RBD_MIRROR_MODE_DISABLED
, states_vec
);
770 TEST_F(TestMirroring
, RemoveImage_With_MirrorImageEnabled
) {
771 check_remove_image(RBD_MIRROR_MODE_IMAGE
,
772 RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
,
776 TEST_F(TestMirroring
, RemoveImage_With_MirrorImageDisabled
) {
777 check_remove_image(RBD_MIRROR_MODE_IMAGE
,
778 RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
,
782 TEST_F(TestMirroring
, RemoveImage_With_ImageWithoutJournal
) {
783 check_remove_image(RBD_MIRROR_MODE_IMAGE
,
784 RBD_FEATURE_EXCLUSIVE_LOCK
,
788 TEST_F(TestMirroring
, RemoveImage_With_MirrorImageDemoted
) {
789 check_remove_image(RBD_MIRROR_MODE_IMAGE
,
790 RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
,
794 TEST_F(TestMirroring
, TrashMoveRestore_PoolMode
) {
795 check_trash_move_restore(RBD_MIRROR_MODE_POOL
, false);
798 TEST_F(TestMirroring
, TrashMoveRestore_ImageMode_MirroringDisabled
) {
799 check_trash_move_restore(RBD_MIRROR_MODE_IMAGE
, false);
802 TEST_F(TestMirroring
, TrashMoveRestore_ImageMode_MirroringEnabled
) {
803 check_trash_move_restore(RBD_MIRROR_MODE_IMAGE
, true);
806 TEST_F(TestMirroring
, MirrorStatusList
) {
807 std::vector
<uint64_t>
808 features_vec(5, RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
);
809 setup_images_with_mirror_mode(RBD_MIRROR_MODE_POOL
, features_vec
);
811 std::string last_read
= "";
812 std::map
<std::string
, librbd::mirror_image_global_status_t
> images
;
813 ASSERT_EQ(0, m_rbd
.mirror_image_global_status_list(m_ioctx
, last_read
, 2,
815 ASSERT_EQ(2U, images
.size());
817 last_read
= images
.rbegin()->first
;
819 ASSERT_EQ(0, m_rbd
.mirror_image_global_status_list(m_ioctx
, last_read
, 2,
821 ASSERT_EQ(2U, images
.size());
823 last_read
= images
.rbegin()->first
;
825 ASSERT_EQ(0, m_rbd
.mirror_image_global_status_list(m_ioctx
, last_read
, 4096,
827 ASSERT_EQ(1U, images
.size());
829 last_read
= images
.rbegin()->first
;
831 ASSERT_EQ(0, m_rbd
.mirror_image_global_status_list(m_ioctx
, last_read
, 4096,
833 ASSERT_EQ(0U, images
.size());
836 TEST_F(TestMirroring
, RemoveBootstrapped
)
838 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_POOL
));
840 uint64_t features
= RBD_FEATURE_EXCLUSIVE_LOCK
| RBD_FEATURE_JOURNALING
;
842 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
845 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
847 librbd::NoOpProgressContext no_op
;
848 ASSERT_EQ(-EBUSY
, librbd::api::Image
<>::remove(m_ioctx
, image_name
, no_op
));
850 // simulate the image is open by rbd-mirror bootstrap
852 struct MirrorWatcher
: public librados::WatchCtx2
{
853 explicit MirrorWatcher(librados::IoCtx
&ioctx
) : m_ioctx(ioctx
) {
855 void handle_notify(uint64_t notify_id
, uint64_t cookie
,
856 uint64_t notifier_id
, bufferlist
& bl
) override
{
857 // received IMAGE_UPDATED notification from remove
859 m_ioctx
.notify_ack(RBD_MIRRORING
, notify_id
, cookie
, bl
);
861 void handle_error(uint64_t cookie
, int err
) override
{
863 librados::IoCtx
&m_ioctx
;
864 bool m_notified
= false;
866 ASSERT_EQ(0, m_ioctx
.create(RBD_MIRRORING
, false));
867 ASSERT_EQ(0, m_ioctx
.watch2(RBD_MIRRORING
, &handle
, &watcher
));
868 // now remove should succeed
869 ASSERT_EQ(0, librbd::api::Image
<>::remove(m_ioctx
, image_name
, no_op
));
870 ASSERT_EQ(0, m_ioctx
.unwatch2(handle
));
871 ASSERT_TRUE(watcher
.m_notified
);
872 ASSERT_EQ(0, image
.close());
875 TEST_F(TestMirroring
, AioPromoteDemote
) {
876 std::list
<std::string
> image_names
;
877 for (size_t idx
= 0; idx
< 10; ++idx
) {
878 image_names
.push_back(get_temp_image_name());
881 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_IMAGE
));
883 // create mirror images
885 std::list
<librbd::Image
> images
;
886 for (auto &image_name
: image_names
) {
887 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 2048,
888 RBD_FEATURE_EXCLUSIVE_LOCK
|
889 RBD_FEATURE_JOURNALING
,
892 images
.emplace_back();
893 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, images
.back(), image_name
.c_str()));
894 ASSERT_EQ(0, images
.back().mirror_image_enable2(
895 RBD_MIRROR_IMAGE_MODE_JOURNAL
));
899 std::list
<librbd::RBD::AioCompletion
*> aio_comps
;
900 for (auto &image
: images
) {
901 aio_comps
.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr));
902 ASSERT_EQ(0, image
.aio_mirror_image_demote(aio_comps
.back()));
904 for (auto aio_comp
: aio_comps
) {
905 ASSERT_EQ(0, aio_comp
->wait_for_complete());
906 ASSERT_EQ(1, aio_comp
->is_complete());
907 ASSERT_EQ(0, aio_comp
->get_return_value());
913 for (auto &image
: images
) {
914 librbd::mirror_image_info_t mirror_image
;
915 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
,
916 sizeof(mirror_image
)));
917 ASSERT_FALSE(mirror_image
.primary
);
920 // promote all images
921 for (auto &image
: images
) {
922 aio_comps
.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr));
923 ASSERT_EQ(0, image
.aio_mirror_image_promote(false, aio_comps
.back()));
925 for (auto aio_comp
: aio_comps
) {
926 ASSERT_EQ(0, aio_comp
->wait_for_complete());
927 ASSERT_EQ(1, aio_comp
->is_complete());
928 ASSERT_EQ(0, aio_comp
->get_return_value());
933 for (auto &image
: images
) {
934 librbd::mirror_image_info_t mirror_image
;
935 ASSERT_EQ(0, image
.mirror_image_get_info(&mirror_image
,
936 sizeof(mirror_image
)));
937 ASSERT_TRUE(mirror_image
.primary
);
941 TEST_F(TestMirroring
, AioGetInfo
) {
942 std::list
<std::string
> image_names
;
943 for (size_t idx
= 0; idx
< 10; ++idx
) {
944 image_names
.push_back(get_temp_image_name());
947 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_POOL
));
949 // create mirror images
951 std::list
<librbd::Image
> images
;
952 for (auto &image_name
: image_names
) {
953 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 2048,
954 RBD_FEATURE_EXCLUSIVE_LOCK
|
955 RBD_FEATURE_JOURNALING
,
958 images
.emplace_back();
959 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, images
.back(), image_name
.c_str()));
962 std::list
<librbd::RBD::AioCompletion
*> aio_comps
;
963 std::list
<librbd::mirror_image_info_t
> infos
;
964 for (auto &image
: images
) {
965 aio_comps
.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr));
966 infos
.emplace_back();
967 ASSERT_EQ(0, image
.aio_mirror_image_get_info(&infos
.back(),
968 sizeof(infos
.back()),
971 for (auto aio_comp
: aio_comps
) {
972 ASSERT_EQ(0, aio_comp
->wait_for_complete());
973 ASSERT_EQ(1, aio_comp
->is_complete());
974 ASSERT_EQ(0, aio_comp
->get_return_value());
979 for (auto &info
: infos
) {
980 ASSERT_NE("", info
.global_id
);
981 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED
, info
.state
);
982 ASSERT_TRUE(info
.primary
);
986 TEST_F(TestMirroring
, AioGetStatus
) {
987 std::list
<std::string
> image_names
;
988 for (size_t idx
= 0; idx
< 10; ++idx
) {
989 image_names
.push_back(get_temp_image_name());
992 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_POOL
));
994 // create mirror images
996 std::list
<librbd::Image
> images
;
997 for (auto &image_name
: image_names
) {
998 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 2048,
999 RBD_FEATURE_EXCLUSIVE_LOCK
|
1000 RBD_FEATURE_JOURNALING
,
1003 images
.emplace_back();
1004 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, images
.back(), image_name
.c_str()));
1007 std::list
<librbd::RBD::AioCompletion
*> aio_comps
;
1008 std::list
<librbd::mirror_image_global_status_t
> statuses
;
1009 for (auto &image
: images
) {
1010 aio_comps
.push_back(new librbd::RBD::AioCompletion(nullptr, nullptr));
1011 statuses
.emplace_back();
1012 ASSERT_EQ(0, image
.aio_mirror_image_get_global_status(
1013 &statuses
.back(), sizeof(statuses
.back()),
1016 for (auto aio_comp
: aio_comps
) {
1017 ASSERT_EQ(0, aio_comp
->wait_for_complete());
1018 ASSERT_EQ(1, aio_comp
->is_complete());
1019 ASSERT_EQ(0, aio_comp
->get_return_value());
1020 aio_comp
->release();
1024 for (auto &status
: statuses
) {
1025 ASSERT_NE("", status
.name
);
1026 ASSERT_NE("", status
.info
.global_id
);
1027 ASSERT_EQ(RBD_MIRROR_IMAGE_ENABLED
, status
.info
.state
);
1028 ASSERT_TRUE(status
.info
.primary
);
1030 librbd::mirror_image_site_status_t local_status
;
1031 ASSERT_EQ(0, get_local_mirror_image_site_status(status
, &local_status
));
1032 ASSERT_EQ(MIRROR_IMAGE_STATUS_STATE_UNKNOWN
, local_status
.state
);
1033 ASSERT_EQ("status not found", local_status
.description
);
1034 ASSERT_FALSE(local_status
.up
);
1035 ASSERT_EQ(0, local_status
.last_update
);
1039 TEST_F(TestMirroring
, SiteName
) {
1040 REQUIRE(!is_librados_test_stub(_rados
));
1042 const std::string
expected_site_name("us-east-1a");
1043 ASSERT_EQ(0, m_rbd
.mirror_site_name_set(_rados
, expected_site_name
));
1045 std::string site_name
;
1046 ASSERT_EQ(0, m_rbd
.mirror_site_name_get(_rados
, &site_name
));
1047 ASSERT_EQ(expected_site_name
, site_name
);
1049 ASSERT_EQ(0, m_rbd
.mirror_site_name_set(_rados
, ""));
1052 ASSERT_EQ(0, _rados
.cluster_fsid(&fsid
));
1053 ASSERT_EQ(0, m_rbd
.mirror_site_name_get(_rados
, &site_name
));
1054 ASSERT_EQ(fsid
, site_name
);
1057 TEST_F(TestMirroring
, Bootstrap
) {
1058 REQUIRE(!is_librados_test_stub(_rados
));
1060 std::string token_b64
;
1061 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
1062 ASSERT_EQ(-EINVAL
, m_rbd
.mirror_peer_bootstrap_create(m_ioctx
, &token_b64
));
1064 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_POOL
));
1065 ASSERT_EQ(0, m_rbd
.mirror_peer_bootstrap_create(m_ioctx
, &token_b64
));
1067 bufferlist token_b64_bl
;
1068 token_b64_bl
.append(token_b64
);
1070 bufferlist token_bl
;
1071 token_bl
.decode_base64(token_b64_bl
);
1073 // cannot import token into same cluster
1075 m_rbd
.mirror_peer_bootstrap_import(
1076 m_ioctx
, RBD_MIRROR_PEER_DIRECTION_RX
, token_b64
));
1079 TEST_F(TestMirroring
, PeerDirection
) {
1080 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_POOL
));
1083 ASSERT_EQ(-EINVAL
, m_rbd
.mirror_peer_site_add(
1084 m_ioctx
, &uuid
, RBD_MIRROR_PEER_DIRECTION_TX
, "siteA",
1086 ASSERT_EQ(0, m_rbd
.mirror_peer_site_add(m_ioctx
, &uuid
,
1087 RBD_MIRROR_PEER_DIRECTION_RX_TX
,
1088 "siteA", "client.admin"));
1090 std::vector
<librbd::mirror_peer_site_t
> peers
;
1091 ASSERT_EQ(0, m_rbd
.mirror_peer_site_list(m_ioctx
, &peers
));
1092 std::vector
<librbd::mirror_peer_site_t
> expected_peers
= {
1093 {uuid
, RBD_MIRROR_PEER_DIRECTION_RX_TX
, "siteA", "", "client.admin", 0}};
1094 ASSERT_EQ(expected_peers
, peers
);
1096 ASSERT_EQ(0, m_rbd
.mirror_peer_site_set_direction(
1097 m_ioctx
, uuid
, RBD_MIRROR_PEER_DIRECTION_RX
));
1098 ASSERT_EQ(0, m_rbd
.mirror_peer_site_list(m_ioctx
, &peers
));
1100 {uuid
, RBD_MIRROR_PEER_DIRECTION_RX
, "siteA", "", "client.admin", 0}};
1101 ASSERT_EQ(expected_peers
, peers
);
1103 ASSERT_EQ(0, m_rbd
.mirror_peer_site_remove(m_ioctx
, uuid
));
1106 TEST_F(TestMirroring
, Snapshot
)
1108 REQUIRE_FORMAT_V2();
1110 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
1113 ASSERT_TRUE(get_features(&features
));
1115 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
1118 librbd::Image image
;
1119 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
1121 ASSERT_EQ(0, image
.metadata_set(
1122 "conf_rbd_mirroring_max_mirroring_snapshots", "3"));
1126 ASSERT_EQ(-EINVAL
, image
.mirror_image_create_snapshot(&snap_id
));
1127 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_IMAGE
));
1128 ASSERT_EQ(-EINVAL
, image
.mirror_image_create_snapshot(&snap_id
));
1129 ASSERT_EQ(0, image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT
));
1130 librbd::mirror_image_mode_t mode
;
1131 ASSERT_EQ(0, image
.mirror_image_get_mode(&mode
));
1132 ASSERT_EQ(RBD_MIRROR_IMAGE_MODE_SNAPSHOT
, mode
);
1133 ASSERT_EQ(-EINVAL
, image
.mirror_image_create_snapshot(&snap_id
));
1134 std::string peer_uuid
;
1135 ASSERT_EQ(0, m_rbd
.mirror_peer_site_add(m_ioctx
, &peer_uuid
,
1136 RBD_MIRROR_PEER_DIRECTION_RX_TX
,
1137 "cluster", "client"));
1138 ASSERT_EQ(0, image
.mirror_image_create_snapshot(&snap_id
));
1139 vector
<librbd::snap_info_t
> snaps
;
1140 ASSERT_EQ(0, image
.snap_list(snaps
));
1141 ASSERT_EQ(2U, snaps
.size());
1142 ASSERT_EQ(snaps
[1].id
, snap_id
);
1144 ASSERT_EQ(0, image
.mirror_image_create_snapshot(&snap_id
));
1145 ASSERT_EQ(0, image
.mirror_image_create_snapshot(&snap_id
));
1147 ASSERT_EQ(0, image
.snap_list(snaps
));
1148 ASSERT_EQ(3U, snaps
.size());
1149 ASSERT_EQ(snaps
[2].id
, snap_id
);
1151 // automatic peer unlink on max_mirroring_snapshots reached
1152 ASSERT_EQ(0, image
.mirror_image_create_snapshot(&snap_id
));
1153 vector
<librbd::snap_info_t
> snaps1
;
1154 ASSERT_EQ(0, image
.snap_list(snaps1
));
1155 ASSERT_EQ(3U, snaps1
.size());
1156 ASSERT_EQ(snaps1
[0].id
, snaps
[0].id
);
1157 ASSERT_EQ(snaps1
[1].id
, snaps
[2].id
);
1158 ASSERT_EQ(snaps1
[2].id
, snap_id
);
1160 librbd::snap_namespace_type_t snap_ns_type
;
1161 ASSERT_EQ(0, image
.snap_get_namespace_type(snap_id
, &snap_ns_type
));
1162 ASSERT_EQ(RBD_SNAP_NAMESPACE_TYPE_MIRROR
, snap_ns_type
);
1163 librbd::snap_mirror_namespace_t mirror_snap
;
1164 ASSERT_EQ(0, image
.snap_get_mirror_namespace(snap_id
, &mirror_snap
,
1165 sizeof(mirror_snap
)));
1166 ASSERT_EQ(1U, mirror_snap
.mirror_peer_uuids
.size());
1167 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer_uuid
));
1169 for (auto &snap
: snaps1
) {
1170 ASSERT_EQ(0, image
.snap_remove_by_id(snap
.id
));
1173 ASSERT_EQ(0, image
.close());
1174 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
1175 ASSERT_EQ(0, m_rbd
.mirror_peer_site_remove(m_ioctx
, peer_uuid
));
1176 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
1179 TEST_F(TestMirroring
, SnapshotRemoveOnDisable
)
1181 REQUIRE_FORMAT_V2();
1183 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_IMAGE
));
1184 std::string peer_uuid
;
1185 ASSERT_EQ(0, m_rbd
.mirror_peer_site_add(m_ioctx
, &peer_uuid
,
1186 RBD_MIRROR_PEER_DIRECTION_RX_TX
,
1187 "cluster", "client"));
1190 ASSERT_TRUE(get_features(&features
));
1192 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
1194 librbd::Image image
;
1195 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
1196 ASSERT_EQ(0, image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT
));
1198 ASSERT_EQ(0, image
.mirror_image_create_snapshot(&snap_id
));
1200 vector
<librbd::snap_info_t
> snaps
;
1201 ASSERT_EQ(0, image
.snap_list(snaps
));
1202 ASSERT_EQ(2U, snaps
.size());
1203 ASSERT_EQ(snaps
[1].id
, snap_id
);
1205 ASSERT_EQ(0, image
.mirror_image_disable(false));
1208 ASSERT_EQ(0, image
.snap_list(snaps
));
1209 ASSERT_TRUE(snaps
.empty());
1211 ASSERT_EQ(0, image
.close());
1212 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
1213 ASSERT_EQ(0, m_rbd
.mirror_peer_site_remove(m_ioctx
, peer_uuid
));
1214 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
1217 TEST_F(TestMirroring
, SnapshotUnlinkPeer
)
1219 REQUIRE_FORMAT_V2();
1221 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_IMAGE
));
1222 std::string peer1_uuid
;
1223 ASSERT_EQ(0, m_rbd
.mirror_peer_site_add(m_ioctx
, &peer1_uuid
,
1224 RBD_MIRROR_PEER_DIRECTION_RX_TX
,
1225 "cluster1", "client"));
1226 std::string peer2_uuid
;
1227 ASSERT_EQ(0, m_rbd
.mirror_peer_site_add(m_ioctx
, &peer2_uuid
,
1228 RBD_MIRROR_PEER_DIRECTION_RX_TX
,
1229 "cluster2", "client"));
1230 std::string peer3_uuid
;
1231 ASSERT_EQ(0, m_rbd
.mirror_peer_site_add(m_ioctx
, &peer3_uuid
,
1232 RBD_MIRROR_PEER_DIRECTION_RX_TX
,
1233 "cluster3", "client"));
1235 ASSERT_TRUE(get_features(&features
));
1236 features
&= ~RBD_FEATURE_JOURNALING
;
1238 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
1240 librbd::Image image
;
1241 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
1242 ASSERT_EQ(0, image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT
));
1244 ASSERT_EQ(0, image
.mirror_image_create_snapshot(&snap_id
));
1246 ASSERT_EQ(0, image
.mirror_image_create_snapshot(&snap_id2
));
1247 librbd::snap_mirror_namespace_t mirror_snap
;
1248 ASSERT_EQ(0, image
.snap_get_mirror_namespace(snap_id
, &mirror_snap
,
1249 sizeof(mirror_snap
)));
1250 ASSERT_EQ(3U, mirror_snap
.mirror_peer_uuids
.size());
1251 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer1_uuid
));
1252 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer2_uuid
));
1253 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer3_uuid
));
1255 auto ictx
= new librbd::ImageCtx(image_name
, "", nullptr, m_ioctx
, false);
1256 ASSERT_EQ(0, ictx
->state
->open(0));
1257 BOOST_SCOPE_EXIT(&ictx
) {
1258 if (ictx
!= nullptr) {
1259 ictx
->state
->close();
1261 } BOOST_SCOPE_EXIT_END
;
1264 auto req
= librbd::mirror::snapshot::UnlinkPeerRequest
<>::create(
1265 ictx
, snap_id
, peer1_uuid
, &cond1
);
1267 ASSERT_EQ(0, cond1
.wait());
1269 ASSERT_EQ(0, image
.snap_get_mirror_namespace(snap_id
, &mirror_snap
,
1270 sizeof(mirror_snap
)));
1271 ASSERT_EQ(2U, mirror_snap
.mirror_peer_uuids
.size());
1272 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer2_uuid
));
1273 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer3_uuid
));
1275 ASSERT_EQ(0, librbd::api::Namespace
<>::create(m_ioctx
, "ns1"));
1276 librados::IoCtx ns_ioctx
;
1277 ns_ioctx
.dup(m_ioctx
);
1278 ns_ioctx
.set_namespace("ns1");
1279 ASSERT_EQ(0, m_rbd
.mirror_mode_set(ns_ioctx
, RBD_MIRROR_MODE_IMAGE
));
1280 ASSERT_EQ(0, m_rbd
.create2(ns_ioctx
, image_name
.c_str(), 4096, features
,
1283 librbd::Image ns_image
;
1284 ASSERT_EQ(0, m_rbd
.open(ns_ioctx
, ns_image
, image_name
.c_str()));
1285 ASSERT_EQ(0, ns_image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT
));
1286 uint64_t ns_snap_id
;
1287 ASSERT_EQ(0, ns_image
.mirror_image_create_snapshot(&ns_snap_id
));
1288 ASSERT_EQ(0, ns_image
.snap_get_mirror_namespace(ns_snap_id
, &mirror_snap
,
1289 sizeof(mirror_snap
)));
1290 ASSERT_EQ(3U, mirror_snap
.mirror_peer_uuids
.size());
1291 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer1_uuid
));
1292 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer2_uuid
));
1293 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer3_uuid
));
1295 ASSERT_EQ(0, m_rbd
.mirror_peer_site_remove(m_ioctx
, peer3_uuid
));
1297 ASSERT_EQ(0, image
.snap_get_mirror_namespace(snap_id
, &mirror_snap
,
1298 sizeof(mirror_snap
)));
1299 ASSERT_EQ(1U, mirror_snap
.mirror_peer_uuids
.size());
1300 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer2_uuid
));
1302 ASSERT_EQ(0, ns_image
.snap_get_mirror_namespace(ns_snap_id
, &mirror_snap
,
1303 sizeof(mirror_snap
)));
1304 ASSERT_EQ(2U, mirror_snap
.mirror_peer_uuids
.size());
1305 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer1_uuid
));
1306 ASSERT_EQ(1, mirror_snap
.mirror_peer_uuids
.count(peer2_uuid
));
1309 req
= librbd::mirror::snapshot::UnlinkPeerRequest
<>::create(
1310 ictx
, snap_id
, peer2_uuid
, &cond2
);
1312 ASSERT_EQ(0, cond2
.wait());
1314 ASSERT_EQ(-ENOENT
, image
.snap_get_mirror_namespace(snap_id
, &mirror_snap
,
1315 sizeof(mirror_snap
)));
1316 ictx
->state
->close();
1318 ASSERT_EQ(0, image
.close());
1319 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
1321 ASSERT_EQ(0, ns_image
.close());
1322 ASSERT_EQ(0, m_rbd
.remove(ns_ioctx
, image_name
.c_str()));
1323 ASSERT_EQ(0, librbd::api::Namespace
<>::remove(m_ioctx
, "ns1"));
1325 ASSERT_EQ(0, m_rbd
.mirror_peer_site_remove(m_ioctx
, peer1_uuid
));
1326 ASSERT_EQ(0, m_rbd
.mirror_peer_site_remove(m_ioctx
, peer2_uuid
));
1327 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));
1330 TEST_F(TestMirroring
, SnapshotImageState
)
1332 REQUIRE_FORMAT_V2();
1334 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_IMAGE
));
1337 ASSERT_TRUE(get_features(&features
));
1339 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
1342 librbd::Image image
;
1343 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
1344 ASSERT_EQ(0, image
.snap_create("snap"));
1345 ASSERT_EQ(0, image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT
));
1346 std::vector
<librbd::snap_info_t
> snaps
;
1347 ASSERT_EQ(0, image
.snap_list(snaps
));
1348 ASSERT_EQ(2U, snaps
.size());
1349 auto snap_id
= snaps
[1].id
;
1351 auto ictx
= new librbd::ImageCtx(image_name
, "", nullptr, m_ioctx
, false);
1352 ASSERT_EQ(0, ictx
->state
->open(0));
1353 BOOST_SCOPE_EXIT(&ictx
) {
1354 if (ictx
!= nullptr) {
1355 ictx
->state
->close();
1357 } BOOST_SCOPE_EXIT_END
;
1361 auto req
= librbd::mirror::snapshot::SetImageStateRequest
<>::create(
1362 ictx
, snap_id
, &cond
);
1364 ASSERT_EQ(0, cond
.wait());
1367 librbd::mirror::snapshot::ImageState image_state
;
1370 auto req
= librbd::mirror::snapshot::GetImageStateRequest
<>::create(
1371 ictx
, snap_id
, &image_state
, &cond
);
1373 ASSERT_EQ(0, cond
.wait());
1376 ASSERT_EQ(image_name
, image_state
.name
);
1377 ASSERT_EQ(0, image
.features(&features
));
1378 ASSERT_EQ(features
& ~RBD_FEATURES_IMPLICIT_ENABLE
, image_state
.features
);
1379 ASSERT_EQ(1U, image_state
.snapshots
.size());
1380 ASSERT_EQ("snap", image_state
.snapshots
.begin()->second
.name
);
1381 ASSERT_TRUE(image_state
.metadata
.empty());
1385 auto req
= librbd::mirror::snapshot::RemoveImageStateRequest
<>::create(
1386 ictx
, snap_id
, &cond
);
1388 ASSERT_EQ(0, cond
.wait());
1391 // test storing "large" image state in multiple objects
1393 ASSERT_EQ(0, ictx
->config
.set_val("rbd_default_order", "8"));
1395 for (int i
= 0; i
< 10; i
++) {
1396 ASSERT_EQ(0, image
.metadata_set(stringify(i
), std::string(1024, 'A' + i
)));
1401 auto req
= librbd::mirror::snapshot::SetImageStateRequest
<>::create(
1402 ictx
, snap_id
, &cond
);
1404 ASSERT_EQ(0, cond
.wait());
1409 auto req
= librbd::mirror::snapshot::GetImageStateRequest
<>::create(
1410 ictx
, snap_id
, &image_state
, &cond
);
1412 ASSERT_EQ(0, cond
.wait());
1415 ASSERT_EQ(image_name
, image_state
.name
);
1416 ASSERT_EQ(features
& ~RBD_FEATURES_IMPLICIT_ENABLE
, image_state
.features
);
1417 ASSERT_EQ(10U, image_state
.metadata
.size());
1418 for (int i
= 0; i
< 10; i
++) {
1419 auto &bl
= image_state
.metadata
[stringify(i
)];
1420 ASSERT_EQ(0, strncmp(std::string(1024, 'A' + i
).c_str(), bl
.c_str(),
1426 auto req
= librbd::mirror::snapshot::RemoveImageStateRequest
<>::create(
1427 ictx
, snap_id
, &cond
);
1429 ASSERT_EQ(0, cond
.wait());
1432 ASSERT_EQ(0, ictx
->state
->close());
1435 ASSERT_EQ(0, image
.snap_remove("snap"));
1436 ASSERT_EQ(0, image
.close());
1437 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
1440 TEST_F(TestMirroring
, SnapshotPromoteDemote
)
1442 REQUIRE_FORMAT_V2();
1444 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_IMAGE
));
1445 std::string peer_uuid
;
1446 ASSERT_EQ(0, m_rbd
.mirror_peer_site_add(m_ioctx
, &peer_uuid
,
1447 RBD_MIRROR_PEER_DIRECTION_RX_TX
,
1448 "cluster", "client"));
1451 ASSERT_TRUE(get_features(&features
));
1453 ASSERT_EQ(0, m_rbd
.create2(m_ioctx
, image_name
.c_str(), 4096, features
,
1456 librbd::Image image
;
1457 ASSERT_EQ(0, m_rbd
.open(m_ioctx
, image
, image_name
.c_str()));
1458 ASSERT_EQ(0, image
.mirror_image_enable2(RBD_MIRROR_IMAGE_MODE_SNAPSHOT
));
1459 librbd::mirror_image_mode_t mode
;
1460 ASSERT_EQ(0, image
.mirror_image_get_mode(&mode
));
1461 ASSERT_EQ(RBD_MIRROR_IMAGE_MODE_SNAPSHOT
, mode
);
1463 ASSERT_EQ(-EINVAL
, image
.mirror_image_promote(false));
1464 ASSERT_EQ(0, image
.mirror_image_demote());
1465 ASSERT_EQ(0, image
.mirror_image_promote(false));
1466 ASSERT_EQ(0, image
.mirror_image_demote());
1467 ASSERT_EQ(0, image
.mirror_image_promote(false));
1469 ASSERT_EQ(0, image
.close());
1470 ASSERT_EQ(0, m_rbd
.remove(m_ioctx
, image_name
.c_str()));
1471 ASSERT_EQ(0, m_rbd
.mirror_peer_site_remove(m_ioctx
, peer_uuid
));
1472 ASSERT_EQ(0, m_rbd
.mirror_mode_set(m_ioctx
, RBD_MIRROR_MODE_DISABLED
));