1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/api/Config.h"
5 #include "librbd/api/Namespace.h"
6 #include "test/librbd/mock/MockImageCtx.h"
7 #include "test/librados_test_stub/MockTestMemCluster.h"
8 #include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
9 #include "test/librados_test_stub/MockTestMemRadosClient.h"
10 #include "test/rbd_mirror/test_mock_fixture.h"
11 #include "test/rbd_mirror/mock/MockContextWQ.h"
12 #include "test/rbd_mirror/mock/MockSafeTimer.h"
13 #include "tools/rbd_mirror/Throttler.h"
14 #include "tools/rbd_mirror/LeaderWatcher.h"
15 #include "tools/rbd_mirror/NamespaceReplayer.h"
16 #include "tools/rbd_mirror/PoolMetaCache.h"
17 #include "tools/rbd_mirror/PoolReplayer.h"
18 #include "tools/rbd_mirror/RemotePoolPoller.h"
19 #include "tools/rbd_mirror/ServiceDaemon.h"
20 #include "tools/rbd_mirror/Threads.h"
21 #include "common/Formatter.h"
27 struct MockTestImageCtx
: public MockImageCtx
{
28 MockTestImageCtx(librbd::ImageCtx
&image_ctx
)
29 : librbd::MockImageCtx(image_ctx
) {
33 } // anonymous namespace
38 class Config
<MockTestImageCtx
> {
40 static void apply_pool_overrides(librados::IoCtx
& io_ctx
,
41 ConfigProxy
* config_proxy
) {
46 class Namespace
<MockTestImageCtx
> {
48 static Namespace
* s_instance
;
50 static int list(librados::IoCtx
& io_ctx
, std::vector
<std::string
> *names
) {
52 return s_instance
->list(names
);
62 void add(const std::string
&name
) {
63 std::lock_guard locker
{m_lock
};
68 void remove(const std::string
&name
) {
69 std::lock_guard locker
{m_lock
};
75 std::lock_guard locker
{m_lock
};
81 ceph::mutex m_lock
= ceph::make_mutex("Namespace");
82 std::set
<std::string
> m_names
;
84 int list(std::vector
<std::string
> *names
) {
85 std::lock_guard locker
{m_lock
};
88 names
->insert(names
->begin(), m_names
.begin(), m_names
.end());
93 Namespace
<librbd::MockTestImageCtx
>* Namespace
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
103 struct Throttler
<librbd::MockTestImageCtx
> {
104 static Throttler
* s_instance
;
106 static Throttler
*create(
108 const std::string
&max_concurrent_ops_config_param_name
) {
113 ceph_assert(s_instance
== nullptr);
117 virtual ~Throttler() {
118 ceph_assert(s_instance
== this);
119 s_instance
= nullptr;
122 MOCK_METHOD1(print_status
, void(Formatter
*));
125 Throttler
<librbd::MockTestImageCtx
>* Throttler
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
128 struct NamespaceReplayer
<librbd::MockTestImageCtx
> {
129 static std::map
<std::string
, NamespaceReplayer
*> s_instances
;
131 static NamespaceReplayer
*create(
132 const std::string
&name
,
133 librados::IoCtx
&local_ioctx
,
134 librados::IoCtx
&remote_ioctx
,
135 const std::string
&local_mirror_uuid
,
136 const std::string
& local_mirror_peer_uuid
,
137 const RemotePoolMeta
& remote_pool_meta
,
138 Threads
<librbd::MockTestImageCtx
> *threads
,
139 Throttler
<librbd::MockTestImageCtx
> *image_sync_throttler
,
140 Throttler
<librbd::MockTestImageCtx
> *image_deletion_throttler
,
141 ServiceDaemon
<librbd::MockTestImageCtx
> *service_daemon
,
142 journal::CacheManagerHandler
*cache_manager_handler
,
143 PoolMetaCache
* pool_meta_cache
) {
144 ceph_assert(s_instances
.count(name
));
145 auto namespace_replayer
= s_instances
[name
];
146 s_instances
.erase(name
);
147 return namespace_replayer
;
150 MOCK_METHOD0(is_blocklisted
, bool());
151 MOCK_METHOD0(get_instance_id
, std::string());
153 MOCK_METHOD1(init
, void(Context
*));
154 MOCK_METHOD1(shut_down
, void(Context
*));
156 MOCK_METHOD1(handle_acquire_leader
, void(Context
*));
157 MOCK_METHOD1(handle_release_leader
, void(Context
*));
158 MOCK_METHOD1(handle_update_leader
, void(const std::string
&));
159 MOCK_METHOD1(handle_instances_added
, void(const std::vector
<std::string
> &));
160 MOCK_METHOD1(handle_instances_removed
, void(const std::vector
<std::string
> &));
162 MOCK_METHOD1(print_status
, void(Formatter
*));
163 MOCK_METHOD0(start
, void());
164 MOCK_METHOD0(stop
, void());
165 MOCK_METHOD0(restart
, void());
166 MOCK_METHOD0(flush
, void());
168 NamespaceReplayer(const std::string
&name
= "") {
169 ceph_assert(!s_instances
.count(name
));
170 s_instances
[name
] = this;
174 std::map
<std::string
, NamespaceReplayer
<librbd::MockTestImageCtx
> *> NamespaceReplayer
<librbd::MockTestImageCtx
>::s_instances
;
177 struct LeaderWatcher
<librbd::MockTestImageCtx
> {
178 static LeaderWatcher
* s_instance
;
179 leader_watcher::Listener
* listener
= nullptr;
181 static LeaderWatcher
*create(Threads
<librbd::MockTestImageCtx
> *threads
,
182 librados::IoCtx
&ioctx
,
183 leader_watcher::Listener
* listener
) {
184 ceph_assert(s_instance
!= nullptr);
185 s_instance
->listener
= listener
;
189 MOCK_METHOD0(is_blocklisted
, bool());
190 MOCK_METHOD0(is_leader
, bool());
191 MOCK_METHOD0(release_leader
, void());
193 MOCK_METHOD1(get_leader_instance_id
, bool(std::string
*));
194 MOCK_METHOD1(list_instances
, void(std::vector
<std::string
>*));
196 MOCK_METHOD0(init
, int());
197 MOCK_METHOD0(shut_down
, int());
205 LeaderWatcher
<librbd::MockTestImageCtx
>* LeaderWatcher
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
208 struct RemotePoolPoller
<librbd::MockTestImageCtx
> {
209 static RemotePoolPoller
* s_instance
;
211 remote_pool_poller::Listener
* listener
= nullptr;
213 static RemotePoolPoller
* create(
214 Threads
<librbd::MockTestImageCtx
>* threads
,
215 librados::IoCtx
& remote_io_ctx
,
216 const std::string
& local_site_name
,
217 const std::string
& local_mirror_uuid
,
218 remote_pool_poller::Listener
& listener
) {
219 ceph_assert(s_instance
!= nullptr);
220 s_instance
->listener
= &listener
;
224 MOCK_METHOD1(init
, void(Context
*));
225 MOCK_METHOD1(shut_down
, void(Context
*));
232 RemotePoolPoller
<librbd::MockTestImageCtx
>* RemotePoolPoller
<librbd::MockTestImageCtx
>::s_instance
= nullptr;
235 struct ServiceDaemon
<librbd::MockTestImageCtx
> {
236 MOCK_METHOD2(add_namespace
, void(int64_t, const std::string
&));
237 MOCK_METHOD2(remove_namespace
, void(int64_t, const std::string
&));
239 MOCK_METHOD3(add_or_update_attribute
,
240 void(int64_t, const std::string
&,
241 const service_daemon::AttributeValue
&));
242 MOCK_METHOD2(remove_attribute
,
243 void(int64_t, const std::string
&));
245 MOCK_METHOD4(add_or_update_callout
, uint64_t(int64_t, uint64_t,
246 service_daemon::CalloutLevel
,
247 const std::string
&));
248 MOCK_METHOD2(remove_callout
, void(int64_t, uint64_t));
252 struct Threads
<librbd::MockTestImageCtx
> {
253 MockSafeTimer
*timer
;
254 ceph::mutex
&timer_lock
;
255 ceph::condition_variable timer_cond
;
257 MockContextWQ
*work_queue
;
259 Threads(Threads
<librbd::ImageCtx
> *threads
)
260 : timer(new MockSafeTimer()),
261 timer_lock(threads
->timer_lock
),
262 work_queue(new MockContextWQ()) {
270 } // namespace mirror
273 // template definitions
274 #include "tools/rbd_mirror/PoolReplayer.cc"
280 using ::testing::AtLeast
;
281 using ::testing::DoAll
;
282 using ::testing::InSequence
;
283 using ::testing::Invoke
;
284 using ::testing::Return
;
285 using ::testing::StrEq
;
286 using ::testing::WithArg
;
288 class TestMockPoolReplayer
: public TestMockFixture
{
290 typedef librbd::api::Namespace
<librbd::MockTestImageCtx
> MockNamespace
;
291 typedef PoolReplayer
<librbd::MockTestImageCtx
> MockPoolReplayer
;
292 typedef Throttler
<librbd::MockTestImageCtx
> MockThrottler
;
293 typedef NamespaceReplayer
<librbd::MockTestImageCtx
> MockNamespaceReplayer
;
294 typedef RemotePoolPoller
<librbd::MockTestImageCtx
> MockRemotePoolPoller
;
295 typedef LeaderWatcher
<librbd::MockTestImageCtx
> MockLeaderWatcher
;
296 typedef ServiceDaemon
<librbd::MockTestImageCtx
> MockServiceDaemon
;
297 typedef Threads
<librbd::MockTestImageCtx
> MockThreads
;
299 void expect_work_queue(MockThreads
&mock_threads
) {
300 EXPECT_CALL(*mock_threads
.work_queue
, queue(_
, _
))
301 .WillRepeatedly(Invoke([this](Context
*ctx
, int r
) {
302 m_threads
->work_queue
->queue(ctx
, r
);
306 void expect_connect(librados::MockTestMemCluster
& mock_cluster
,
307 librados::MockTestMemRadosClient
* mock_rados_client
,
308 const std::string
& cluster_name
, CephContext
** cct_ref
) {
309 EXPECT_CALL(mock_cluster
, create_rados_client(_
))
310 .WillOnce(Invoke([cluster_name
, mock_rados_client
, cct_ref
](CephContext
* cct
) {
311 EXPECT_EQ(cluster_name
, cct
->_conf
->cluster
);
312 if (cct_ref
!= nullptr) {
316 return mock_rados_client
;
320 void expect_create_ioctx(librados::MockTestMemRadosClient
* mock_rados_client
,
321 librados::MockTestMemIoCtxImpl
* mock_io_ctx_impl
) {
322 EXPECT_CALL(*mock_rados_client
, create_ioctx(_
, _
))
323 .WillOnce(Invoke([mock_io_ctx_impl
](int64_t id
, const std::string
& name
) {
324 return mock_io_ctx_impl
;
328 void expect_mirror_uuid_get(librados::MockTestMemIoCtxImpl
*io_ctx_impl
,
329 const std::string
&uuid
, int r
) {
331 encode(uuid
, out_bl
);
333 EXPECT_CALL(*io_ctx_impl
,
334 exec(RBD_MIRRORING
, _
, StrEq("rbd"), StrEq("mirror_uuid_get"),
336 .WillOnce(DoAll(WithArg
<5>(Invoke([out_bl
](bufferlist
*bl
) {
342 void expect_mirror_mode_get(librados::MockTestMemIoCtxImpl
*io_ctx_impl
,
343 cls::rbd::MirrorMode mirror_mode
, int r
) {
345 encode(mirror_mode
, out_bl
);
347 EXPECT_CALL(*io_ctx_impl
,
348 exec(RBD_MIRRORING
, _
, StrEq("rbd"), StrEq("mirror_mode_get"),
350 .WillOnce(DoAll(WithArg
<5>(Invoke([out_bl
](bufferlist
*bl
) {
356 void expect_mirror_mode_get(librados::MockTestMemIoCtxImpl
*io_ctx_impl
) {
357 EXPECT_CALL(*io_ctx_impl
,
358 exec(RBD_MIRRORING
, _
, StrEq("rbd"), StrEq("mirror_mode_get"),
360 .WillRepeatedly(DoAll(WithArg
<5>(Invoke([](bufferlist
*bl
) {
361 encode(cls::rbd::MIRROR_MODE_POOL
, *bl
);
366 void expect_leader_watcher_init(MockLeaderWatcher
& mock_leader_watcher
,
368 EXPECT_CALL(mock_leader_watcher
, init())
369 .WillOnce(Return(r
));
372 void expect_leader_watcher_shut_down(MockLeaderWatcher
& mock_leader_watcher
) {
373 EXPECT_CALL(mock_leader_watcher
, shut_down());
376 void expect_leader_watcher_get_leader_instance_id(
377 MockLeaderWatcher
& mock_leader_watcher
) {
378 EXPECT_CALL(mock_leader_watcher
, get_leader_instance_id(_
))
379 .WillRepeatedly(Return(true));
382 void expect_leader_watcher_list_instances(
383 MockLeaderWatcher
& mock_leader_watcher
) {
384 EXPECT_CALL(mock_leader_watcher
, list_instances(_
))
388 void expect_remote_pool_poller_init(
389 MockRemotePoolPoller
& mock_remote_pool_poller
,
390 const RemotePoolMeta
& remote_pool_meta
, int r
) {
391 EXPECT_CALL(mock_remote_pool_poller
, init(_
))
393 [this, &mock_remote_pool_poller
, remote_pool_meta
, r
]
396 mock_remote_pool_poller
.listener
->handle_updated(
400 m_threads
->work_queue
->queue(ctx
, r
);
404 void expect_remote_pool_poller_shut_down(
405 MockRemotePoolPoller
& mock_remote_pool_poller
, int r
) {
406 EXPECT_CALL(mock_remote_pool_poller
, shut_down(_
))
408 [this, r
](Context
* ctx
) {
409 m_threads
->work_queue
->queue(ctx
, r
);
413 void expect_leader_watcher_is_blocklisted(
414 MockLeaderWatcher
&mock_leader_watcher
, bool blocklisted
) {
415 EXPECT_CALL(mock_leader_watcher
, is_blocklisted())
416 .WillRepeatedly(Return(blocklisted
));
419 void expect_namespace_replayer_is_blocklisted(
420 MockNamespaceReplayer
&mock_namespace_replayer
,
422 EXPECT_CALL(mock_namespace_replayer
, is_blocklisted())
423 .WillRepeatedly(Return(blocklisted
));
426 void expect_namespace_replayer_get_instance_id(
427 MockNamespaceReplayer
&mock_namespace_replayer
,
428 const std::string
&instance_id
) {
429 EXPECT_CALL(mock_namespace_replayer
, get_instance_id())
430 .WillOnce(Return(instance_id
));
433 void expect_namespace_replayer_init(
434 MockNamespaceReplayer
&mock_namespace_replayer
, int r
,
435 Context
*on_init
= nullptr) {
437 EXPECT_CALL(mock_namespace_replayer
, init(_
))
438 .WillOnce(Invoke([this, r
, on_init
](Context
* ctx
) {
439 m_threads
->work_queue
->queue(ctx
, r
);
440 if (on_init
!= nullptr) {
441 m_threads
->work_queue
->queue(on_init
, r
);
446 void expect_namespace_replayer_shut_down(
447 MockNamespaceReplayer
&mock_namespace_replayer
,
448 Context
*on_shut_down
= nullptr) {
449 EXPECT_CALL(mock_namespace_replayer
, shut_down(_
))
450 .WillOnce(Invoke([this, on_shut_down
](Context
* ctx
) {
451 m_threads
->work_queue
->queue(ctx
);
452 if (on_shut_down
!= nullptr) {
453 m_threads
->work_queue
->queue(on_shut_down
);
458 void expect_namespace_replayer_handle_acquire_leader(
459 MockNamespaceReplayer
&mock_namespace_replayer
, int r
,
460 Context
*on_acquire
= nullptr) {
461 EXPECT_CALL(mock_namespace_replayer
, handle_acquire_leader(_
))
462 .WillOnce(Invoke([this, r
, on_acquire
](Context
* ctx
) {
463 m_threads
->work_queue
->queue(ctx
, r
);
464 if (on_acquire
!= nullptr) {
465 m_threads
->work_queue
->queue(on_acquire
, r
);
470 void expect_namespace_replayer_handle_release_leader(
471 MockNamespaceReplayer
&mock_namespace_replayer
, int r
,
472 Context
*on_release
= nullptr) {
473 EXPECT_CALL(mock_namespace_replayer
, handle_release_leader(_
))
474 .WillOnce(Invoke([this, r
, on_release
](Context
* ctx
) {
475 m_threads
->work_queue
->queue(ctx
, r
);
476 if (on_release
!= nullptr) {
477 m_threads
->work_queue
->queue(on_release
, r
);
482 void expect_namespace_replayer_handle_update_leader(
483 MockNamespaceReplayer
&mock_namespace_replayer
,
484 const std::string
&leader_instance_id
,
485 Context
*on_update
= nullptr) {
486 EXPECT_CALL(mock_namespace_replayer
,
487 handle_update_leader(leader_instance_id
))
488 .WillOnce(Invoke([on_update
](const std::string
&) {
489 if (on_update
!= nullptr) {
490 on_update
->complete(0);
495 void expect_namespace_replayer_handle_instances_added(
496 MockNamespaceReplayer
&mock_namespace_replayer
) {
497 EXPECT_CALL(mock_namespace_replayer
, handle_instances_added(_
));
500 void expect_namespace_replayer_handle_instances_removed(
501 MockNamespaceReplayer
&mock_namespace_replayer
) {
502 EXPECT_CALL(mock_namespace_replayer
, handle_instances_removed(_
));
505 void expect_service_daemon_add_namespace(
506 MockServiceDaemon
&mock_service_daemon
,
507 const std::string
& namespace_name
) {
508 EXPECT_CALL(mock_service_daemon
,
509 add_namespace(m_local_io_ctx
.get_id(), namespace_name
));
512 void expect_service_daemon_remove_namespace(
513 MockServiceDaemon
&mock_service_daemon
,
514 const std::string
& namespace_name
) {
515 EXPECT_CALL(mock_service_daemon
,
516 remove_namespace(m_local_io_ctx
.get_id(), namespace_name
));
519 void expect_service_daemon_add_or_update_attribute(
520 MockServiceDaemon
&mock_service_daemon
, const std::string
& key
,
521 const service_daemon::AttributeValue
& value
) {
522 EXPECT_CALL(mock_service_daemon
, add_or_update_attribute(_
, key
, value
));
525 void expect_service_daemon_remove_attribute(
526 MockServiceDaemon
&mock_service_daemon
, const std::string
& key
) {
527 EXPECT_CALL(mock_service_daemon
, remove_attribute(_
, key
));
530 void expect_service_daemon_add_or_update_instance_id_attribute(
531 MockServiceDaemon
&mock_service_daemon
, const std::string
&instance_id
) {
532 expect_service_daemon_add_or_update_attribute(
533 mock_service_daemon
, "instance_id", {instance_id
});
536 PoolMetaCache m_pool_meta_cache
{g_ceph_context
};
539 TEST_F(TestMockPoolReplayer
, ConfigKeyOverride
) {
540 PeerSpec peer_spec
{"uuid", "cluster name", "client.name"};
541 peer_spec
.mon_host
= "123";
542 peer_spec
.key
= "234";
544 auto mock_default_namespace_replayer
= new MockNamespaceReplayer();
545 expect_namespace_replayer_is_blocklisted(*mock_default_namespace_replayer
,
548 MockThreads
mock_threads(m_threads
);
549 expect_work_queue(mock_threads
);
551 auto mock_leader_watcher
= new MockLeaderWatcher();
552 expect_leader_watcher_get_leader_instance_id(*mock_leader_watcher
);
553 expect_leader_watcher_is_blocklisted(*mock_leader_watcher
, false);
557 auto& mock_cluster
= get_mock_cluster();
558 auto mock_local_rados_client
= mock_cluster
.do_create_rados_client(
560 expect_connect(mock_cluster
, mock_local_rados_client
, "ceph", nullptr);
562 auto mock_remote_rados_client
= mock_cluster
.do_create_rados_client(
564 CephContext
* remote_cct
= nullptr;
565 expect_connect(mock_cluster
, mock_remote_rados_client
, "cluster name",
568 auto mock_local_io_ctx
= mock_local_rados_client
->do_create_ioctx(
569 m_local_io_ctx
.get_id(), m_local_io_ctx
.get_pool_name());
570 expect_create_ioctx(mock_local_rados_client
, mock_local_io_ctx
);
572 expect_mirror_uuid_get(mock_local_io_ctx
, "uuid", 0);
573 auto mock_remote_pool_poller
= new MockRemotePoolPoller();
574 expect_remote_pool_poller_init(*mock_remote_pool_poller
,
575 {"remote mirror uuid", ""}, 0);
576 expect_namespace_replayer_init(*mock_default_namespace_replayer
, 0);
577 expect_leader_watcher_init(*mock_leader_watcher
, 0);
579 MockServiceDaemon mock_service_daemon
;
580 std::string instance_id
= stringify(mock_local_io_ctx
->get_instance_id());
581 expect_service_daemon_add_or_update_instance_id_attribute(
582 mock_service_daemon
, instance_id
);
584 MockPoolReplayer
pool_replayer(&mock_threads
, &mock_service_daemon
, nullptr,
586 m_local_io_ctx
.get_id(), peer_spec
, {});
587 pool_replayer
.init("siteA");
589 ASSERT_TRUE(remote_cct
!= nullptr);
590 ASSERT_EQ("123", remote_cct
->_conf
.get_val
<std::string
>("mon_host"));
591 ASSERT_EQ("234", remote_cct
->_conf
.get_val
<std::string
>("key"));
594 expect_leader_watcher_shut_down(*mock_leader_watcher
);
595 expect_namespace_replayer_shut_down(*mock_default_namespace_replayer
);
596 expect_remote_pool_poller_shut_down(*mock_remote_pool_poller
, 0);
598 pool_replayer
.shut_down();
601 TEST_F(TestMockPoolReplayer
, AcquireReleaseLeader
) {
602 PeerSpec peer_spec
{"uuid", "cluster name", "client.name"};
603 peer_spec
.mon_host
= "123";
604 peer_spec
.key
= "234";
606 auto mock_default_namespace_replayer
= new MockNamespaceReplayer();
607 expect_namespace_replayer_is_blocklisted(*mock_default_namespace_replayer
,
610 MockThreads
mock_threads(m_threads
);
611 expect_work_queue(mock_threads
);
613 auto mock_leader_watcher
= new MockLeaderWatcher();
614 expect_leader_watcher_get_leader_instance_id(*mock_leader_watcher
);
615 expect_leader_watcher_list_instances(*mock_leader_watcher
);
616 expect_leader_watcher_is_blocklisted(*mock_leader_watcher
, false);
620 auto& mock_cluster
= get_mock_cluster();
621 auto mock_local_rados_client
= mock_cluster
.do_create_rados_client(
623 expect_connect(mock_cluster
, mock_local_rados_client
, "ceph", nullptr);
625 auto mock_remote_rados_client
= mock_cluster
.do_create_rados_client(
627 expect_connect(mock_cluster
, mock_remote_rados_client
, "cluster name",
630 auto mock_local_io_ctx
= mock_local_rados_client
->do_create_ioctx(
631 m_local_io_ctx
.get_id(), m_local_io_ctx
.get_pool_name());
632 expect_create_ioctx(mock_local_rados_client
, mock_local_io_ctx
);
634 expect_mirror_uuid_get(mock_local_io_ctx
, "uuid", 0);
635 auto mock_remote_pool_poller
= new MockRemotePoolPoller();
636 expect_remote_pool_poller_init(*mock_remote_pool_poller
,
637 {"remote mirror uuid", ""}, 0);
638 expect_namespace_replayer_init(*mock_default_namespace_replayer
, 0);
639 expect_leader_watcher_init(*mock_leader_watcher
, 0);
641 MockServiceDaemon mock_service_daemon
;
642 std::string instance_id
= stringify(mock_local_io_ctx
->get_instance_id());
643 expect_service_daemon_add_or_update_instance_id_attribute(
644 mock_service_daemon
, instance_id
);
646 MockPoolReplayer
pool_replayer(&mock_threads
, &mock_service_daemon
, nullptr,
648 m_local_io_ctx
.get_id(), peer_spec
, {});
649 pool_replayer
.init("siteA");
651 expect_service_daemon_add_or_update_attribute(
652 mock_service_daemon
, SERVICE_DAEMON_LEADER_KEY
, true);
653 expect_namespace_replayer_handle_acquire_leader(
654 *mock_default_namespace_replayer
, 0);
656 C_SaferCond on_acquire
;
657 mock_leader_watcher
->listener
->post_acquire_handler(&on_acquire
);
658 ASSERT_EQ(0, on_acquire
.wait());
660 expect_service_daemon_remove_attribute(mock_service_daemon
,
661 SERVICE_DAEMON_LEADER_KEY
);
662 expect_namespace_replayer_handle_release_leader(
663 *mock_default_namespace_replayer
, 0);
665 C_SaferCond on_release
;
666 mock_leader_watcher
->listener
->pre_release_handler(&on_release
);
667 ASSERT_EQ(0, on_release
.wait());
669 expect_leader_watcher_shut_down(*mock_leader_watcher
);
670 expect_namespace_replayer_shut_down(*mock_default_namespace_replayer
);
671 expect_remote_pool_poller_shut_down(*mock_remote_pool_poller
, 0);
673 pool_replayer
.shut_down();
676 TEST_F(TestMockPoolReplayer
, Namespaces
) {
677 PeerSpec peer_spec
{"uuid", "cluster name", "client.name"};
678 peer_spec
.mon_host
= "123";
679 peer_spec
.key
= "234";
681 g_ceph_context
->_conf
.set_val(
682 "rbd_mirror_pool_replayers_refresh_interval", "1");
684 MockNamespace mock_namespace
;
686 auto mock_default_namespace_replayer
= new MockNamespaceReplayer();
687 expect_namespace_replayer_is_blocklisted(*mock_default_namespace_replayer
,
690 auto mock_ns1_namespace_replayer
= new MockNamespaceReplayer("ns1");
691 expect_namespace_replayer_is_blocklisted(*mock_ns1_namespace_replayer
,
694 auto mock_ns2_namespace_replayer
= new MockNamespaceReplayer("ns2");
695 expect_namespace_replayer_is_blocklisted(*mock_ns2_namespace_replayer
,
698 MockThreads
mock_threads(m_threads
);
699 expect_work_queue(mock_threads
);
701 auto mock_leader_watcher
= new MockLeaderWatcher();
702 expect_leader_watcher_get_leader_instance_id(*mock_leader_watcher
);
703 expect_leader_watcher_list_instances(*mock_leader_watcher
);
704 expect_leader_watcher_is_blocklisted(*mock_leader_watcher
, false);
706 auto& mock_cluster
= get_mock_cluster();
707 auto mock_local_rados_client
= mock_cluster
.do_create_rados_client(
709 auto mock_local_io_ctx
= mock_local_rados_client
->do_create_ioctx(
710 m_local_io_ctx
.get_id(), m_local_io_ctx
.get_pool_name());
711 auto mock_remote_rados_client
= mock_cluster
.do_create_rados_client(
714 expect_mirror_mode_get(mock_local_io_ctx
);
718 expect_connect(mock_cluster
, mock_local_rados_client
, "ceph", nullptr);
719 expect_connect(mock_cluster
, mock_remote_rados_client
, "cluster name",
721 expect_create_ioctx(mock_local_rados_client
, mock_local_io_ctx
);
722 expect_mirror_uuid_get(mock_local_io_ctx
, "uuid", 0);
723 auto mock_remote_pool_poller
= new MockRemotePoolPoller();
724 expect_remote_pool_poller_init(*mock_remote_pool_poller
,
725 {"remote mirror uuid", ""}, 0);
726 expect_namespace_replayer_init(*mock_default_namespace_replayer
, 0);
727 expect_leader_watcher_init(*mock_leader_watcher
, 0);
729 MockServiceDaemon mock_service_daemon
;
730 std::string instance_id
= stringify(mock_local_io_ctx
->get_instance_id());
731 expect_service_daemon_add_or_update_instance_id_attribute(
732 mock_service_daemon
, instance_id
);
734 MockPoolReplayer
pool_replayer(&mock_threads
, &mock_service_daemon
, nullptr,
736 m_local_io_ctx
.get_id(), peer_spec
, {});
737 pool_replayer
.init("siteA");
739 C_SaferCond on_ns1_init
;
740 expect_namespace_replayer_init(*mock_ns1_namespace_replayer
, 0);
741 expect_service_daemon_add_namespace(mock_service_daemon
, "ns1");
742 expect_namespace_replayer_handle_update_leader(*mock_ns1_namespace_replayer
,
745 mock_namespace
.add("ns1");
746 ASSERT_EQ(0, on_ns1_init
.wait());
748 expect_service_daemon_add_or_update_attribute(
749 mock_service_daemon
, SERVICE_DAEMON_LEADER_KEY
, true);
750 expect_namespace_replayer_handle_acquire_leader(
751 *mock_default_namespace_replayer
, 0);
752 expect_namespace_replayer_handle_acquire_leader(
753 *mock_ns1_namespace_replayer
, 0);
755 C_SaferCond on_acquire
;
756 mock_leader_watcher
->listener
->post_acquire_handler(&on_acquire
);
757 ASSERT_EQ(0, on_acquire
.wait());
759 expect_namespace_replayer_init(*mock_ns2_namespace_replayer
, 0);
760 expect_service_daemon_add_namespace(mock_service_daemon
, "ns2");
761 C_SaferCond on_ns2_acquire
;
762 expect_namespace_replayer_handle_acquire_leader(
763 *mock_ns2_namespace_replayer
, 0, &on_ns2_acquire
);
764 expect_namespace_replayer_handle_instances_added(
765 *mock_ns2_namespace_replayer
);
767 mock_namespace
.add("ns2");
768 ASSERT_EQ(0, on_ns2_acquire
.wait());
770 C_SaferCond on_ns2_shut_down
;
771 expect_service_daemon_remove_namespace(mock_service_daemon
, "ns2");
772 expect_namespace_replayer_shut_down(*mock_ns2_namespace_replayer
,
774 mock_namespace
.remove("ns2");
775 ASSERT_EQ(0, on_ns2_shut_down
.wait());
777 expect_service_daemon_remove_attribute(mock_service_daemon
,
778 SERVICE_DAEMON_LEADER_KEY
);
779 expect_namespace_replayer_handle_release_leader(
780 *mock_default_namespace_replayer
, 0);
781 expect_namespace_replayer_handle_release_leader(
782 *mock_ns1_namespace_replayer
, 0);
784 C_SaferCond on_release
;
785 mock_leader_watcher
->listener
->pre_release_handler(&on_release
);
786 ASSERT_EQ(0, on_release
.wait());
788 expect_service_daemon_remove_namespace(mock_service_daemon
, "ns1");
789 expect_namespace_replayer_shut_down(*mock_ns1_namespace_replayer
);
790 expect_leader_watcher_shut_down(*mock_leader_watcher
);
791 expect_namespace_replayer_shut_down(*mock_default_namespace_replayer
);
792 expect_remote_pool_poller_shut_down(*mock_remote_pool_poller
, 0);
794 pool_replayer
.shut_down();
797 TEST_F(TestMockPoolReplayer
, NamespacesError
) {
798 PeerSpec peer_spec
{"uuid", "cluster name", "client.name"};
799 peer_spec
.mon_host
= "123";
800 peer_spec
.key
= "234";
802 g_ceph_context
->_conf
.set_val(
803 "rbd_mirror_pool_replayers_refresh_interval", "1");
805 MockNamespace mock_namespace
;
807 auto mock_default_namespace_replayer
= new MockNamespaceReplayer();
808 expect_namespace_replayer_is_blocklisted(*mock_default_namespace_replayer
,
810 auto mock_ns1_namespace_replayer
= new MockNamespaceReplayer("ns1");
811 auto mock_ns2_namespace_replayer
= new MockNamespaceReplayer("ns2");
812 expect_namespace_replayer_is_blocklisted(*mock_ns2_namespace_replayer
,
814 auto mock_ns3_namespace_replayer
= new MockNamespaceReplayer("ns3");
816 MockThreads
mock_threads(m_threads
);
817 expect_work_queue(mock_threads
);
819 auto mock_leader_watcher
= new MockLeaderWatcher();
820 expect_leader_watcher_get_leader_instance_id(*mock_leader_watcher
);
821 expect_leader_watcher_list_instances(*mock_leader_watcher
);
822 expect_leader_watcher_is_blocklisted(*mock_leader_watcher
, false);
824 auto& mock_cluster
= get_mock_cluster();
825 auto mock_local_rados_client
= mock_cluster
.do_create_rados_client(
827 auto mock_local_io_ctx
= mock_local_rados_client
->do_create_ioctx(
828 m_local_io_ctx
.get_id(), m_local_io_ctx
.get_pool_name());
829 auto mock_remote_rados_client
= mock_cluster
.do_create_rados_client(
832 expect_mirror_mode_get(mock_local_io_ctx
);
836 expect_connect(mock_cluster
, mock_local_rados_client
, "ceph", nullptr);
837 expect_connect(mock_cluster
, mock_remote_rados_client
, "cluster name",
839 expect_create_ioctx(mock_local_rados_client
, mock_local_io_ctx
);
840 expect_mirror_uuid_get(mock_local_io_ctx
, "uuid", 0);
841 auto mock_remote_pool_poller
= new MockRemotePoolPoller();
842 expect_remote_pool_poller_init(*mock_remote_pool_poller
,
843 {"remote mirror uuid", ""}, 0);
844 expect_namespace_replayer_init(*mock_default_namespace_replayer
, 0);
845 expect_leader_watcher_init(*mock_leader_watcher
, 0);
847 MockServiceDaemon mock_service_daemon
;
848 std::string instance_id
= stringify(mock_local_io_ctx
->get_instance_id());
849 expect_service_daemon_add_or_update_instance_id_attribute(
850 mock_service_daemon
, instance_id
);
852 MockPoolReplayer
pool_replayer(&mock_threads
, &mock_service_daemon
, nullptr,
854 m_local_io_ctx
.get_id(), peer_spec
, {});
855 pool_replayer
.init("siteA");
857 // test namespace replayer init fails for non leader
859 C_SaferCond on_ns1_init
;
860 Context
* ctx
= new LambdaContext(
861 [&mock_namespace
, &on_ns1_init
](int r
) {
862 mock_namespace
.remove("ns1");
863 on_ns1_init
.complete(r
);
865 expect_namespace_replayer_init(*mock_ns1_namespace_replayer
, -EINVAL
, ctx
);
866 mock_namespace
.add("ns1");
867 ASSERT_EQ(-EINVAL
, on_ns1_init
.wait());
869 // test acquire leader fails when default namespace replayer fails
871 expect_service_daemon_add_or_update_attribute(
872 mock_service_daemon
, SERVICE_DAEMON_LEADER_KEY
, true);
873 expect_namespace_replayer_handle_acquire_leader(
874 *mock_default_namespace_replayer
, -EINVAL
);
876 C_SaferCond on_acquire1
;
877 mock_leader_watcher
->listener
->post_acquire_handler(&on_acquire1
);
878 ASSERT_EQ(-EINVAL
, on_acquire1
.wait());
880 // test acquire leader succeeds when non-default namespace replayer fails
882 C_SaferCond on_ns2_init
;
883 expect_namespace_replayer_init(*mock_ns2_namespace_replayer
, 0);
884 expect_service_daemon_add_namespace(mock_service_daemon
, "ns2");
885 expect_namespace_replayer_handle_update_leader(*mock_ns2_namespace_replayer
,
887 mock_namespace
.add("ns2");
888 ASSERT_EQ(0, on_ns2_init
.wait());
890 expect_service_daemon_add_or_update_attribute(
891 mock_service_daemon
, SERVICE_DAEMON_LEADER_KEY
, true);
892 expect_namespace_replayer_handle_acquire_leader(
893 *mock_default_namespace_replayer
, 0);
895 expect_namespace_replayer_handle_acquire_leader(*mock_ns2_namespace_replayer
,
897 ctx
= new LambdaContext(
898 [&mock_namespace
](int) {
899 mock_namespace
.remove("ns2");
901 expect_service_daemon_remove_namespace(mock_service_daemon
, "ns2");
902 expect_namespace_replayer_shut_down(*mock_ns2_namespace_replayer
, ctx
);
903 mock_namespace
.add("ns2");
905 C_SaferCond on_acquire2
;
906 mock_leader_watcher
->listener
->post_acquire_handler(&on_acquire2
);
907 ASSERT_EQ(0, on_acquire2
.wait());
909 // test namespace replayer init fails on acquire leader
911 C_SaferCond on_ns3_shut_down
;
912 ctx
= new LambdaContext(
913 [&mock_namespace
, &on_ns3_shut_down
](int) {
914 mock_namespace
.remove("ns3");
915 on_ns3_shut_down
.complete(0);
917 expect_namespace_replayer_init(*mock_ns3_namespace_replayer
, 0);
918 expect_service_daemon_add_namespace(mock_service_daemon
, "ns3");
919 expect_namespace_replayer_handle_acquire_leader(*mock_ns3_namespace_replayer
,
921 expect_service_daemon_remove_namespace(mock_service_daemon
, "ns3");
922 expect_namespace_replayer_shut_down(*mock_ns3_namespace_replayer
, ctx
);
923 mock_namespace
.add("ns3");
924 ASSERT_EQ(0, on_ns3_shut_down
.wait());
926 expect_leader_watcher_shut_down(*mock_leader_watcher
);
927 expect_namespace_replayer_shut_down(*mock_default_namespace_replayer
);
928 expect_remote_pool_poller_shut_down(*mock_remote_pool_poller
, 0);
930 pool_replayer
.shut_down();
933 } // namespace mirror