1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "ClusterWatcher.h"
5 #include "common/debug.h"
6 #include "common/errno.h"
7 #include "cls/rbd/cls_rbd_client.h"
8 #include "librbd/internal.h"
9 #include "librbd/api/Mirror.h"
10 #include "tools/rbd_mirror/ServiceDaemon.h"
12 #define dout_context g_ceph_context
13 #define dout_subsys ceph_subsys_rbd_mirror
15 #define dout_prefix *_dout << "rbd::mirror::ClusterWatcher:" << this << " " \
22 using std::unique_ptr;
25 using librados::Rados;
26 using librados::IoCtx;
31 ClusterWatcher::ClusterWatcher(RadosRef cluster, Mutex &lock,
32 ServiceDaemon<librbd::ImageCtx>* service_daemon)
33 : m_cluster(cluster), m_lock(lock), m_service_daemon(service_daemon)
37 const ClusterWatcher::PoolPeers& ClusterWatcher::get_pool_peers() const
39 assert(m_lock.is_locked());
43 void ClusterWatcher::refresh_pools()
45 dout(20) << "enter" << dendl;
49 read_pool_peers(&pool_peers, &pool_names);
51 Mutex::Locker l(m_lock);
52 m_pool_peers = pool_peers;
53 // TODO: perhaps use a workqueue instead, once we get notifications
54 // about config changes for existing pools
57 void ClusterWatcher::read_pool_peers(PoolPeers *pool_peers,
58 PoolNames *pool_names)
60 list<pair<int64_t, string> > pools;
61 int r = m_cluster->pool_list2(pools);
63 derr << "error listing pools: " << cpp_strerror(r) << dendl;
67 std::set<int64_t> service_pool_ids;
68 for (auto& kv : pools) {
69 int64_t pool_id = kv.first;
70 auto& pool_name = kv.second;
72 r = m_cluster->pool_get_base_tier(pool_id, &base_tier);
74 dout(10) << "pool " << pool_name << " no longer exists" << dendl;
77 derr << "Error retrieving base tier for pool " << pool_name << dendl;
80 if (pool_id != base_tier) {
81 // pool is a cache; skip it
86 r = m_cluster->ioctx_create2(pool_id, ioctx);
88 dout(10) << "pool " << pool_id << " no longer exists" << dendl;
91 derr << "Error accessing pool " << pool_name << cpp_strerror(r) << dendl;
95 cls::rbd::MirrorMode mirror_mode_internal;
96 r = librbd::cls_client::mirror_mode_get(&ioctx, &mirror_mode_internal);
97 if (r == 0 && mirror_mode_internal == cls::rbd::MIRROR_MODE_DISABLED) {
98 dout(10) << "mirroring is disabled for pool " << pool_name << dendl;
102 service_pool_ids.insert(pool_id);
103 if (m_service_pools.find(pool_id) == m_service_pools.end()) {
104 m_service_pools[pool_id] = {};
105 m_service_daemon->add_pool(pool_id, pool_name);
109 dout(10) << "access denied querying pool " << pool_name << dendl;
110 m_service_pools[pool_id] = m_service_daemon->add_or_update_callout(
111 pool_id, m_service_pools[pool_id],
112 service_daemon::CALLOUT_LEVEL_WARNING, "access denied");
115 derr << "could not tell whether mirroring was enabled for " << pool_name
116 << " : " << cpp_strerror(r) << dendl;
117 m_service_pools[pool_id] = m_service_daemon->add_or_update_callout(
118 pool_id, m_service_pools[pool_id],
119 service_daemon::CALLOUT_LEVEL_WARNING, "mirroring mode query failed");
123 vector<librbd::mirror_peer_t> configs;
124 r = librbd::api::Mirror<>::peer_list(ioctx, &configs);
126 derr << "error reading mirroring config for pool " << pool_name
127 << cpp_strerror(r) << dendl;
128 m_service_pools[pool_id] = m_service_daemon->add_or_update_callout(
129 pool_id, m_service_pools[pool_id],
130 service_daemon::CALLOUT_LEVEL_ERROR, "mirroring peer list failed");
134 if (m_service_pools[pool_id] != service_daemon::CALLOUT_ID_NONE) {
135 m_service_daemon->remove_callout(pool_id, m_service_pools[pool_id]);
136 m_service_pools[pool_id] = service_daemon::CALLOUT_ID_NONE;
139 pool_peers->insert({pool_id, Peers{configs.begin(), configs.end()}});
140 pool_names->insert(pool_name);
143 for (auto it = m_service_pools.begin(); it != m_service_pools.end(); ) {
144 auto current_it(it++);
145 if (service_pool_ids.find(current_it->first) == service_pool_ids.end()) {
146 m_service_daemon->remove_pool(current_it->first);
147 m_service_pools.erase(current_it->first);
152 } // namespace mirror