Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / rbd_mirror / test_ClusterWatcher.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 #include "include/rados/librados.hpp"
4 #include "common/Cond.h"
5 #include "common/errno.h"
6 #include "common/Mutex.h"
7 #include "librbd/internal.h"
8 #include "librbd/api/Mirror.h"
9 #include "tools/rbd_mirror/ClusterWatcher.h"
10 #include "tools/rbd_mirror/ServiceDaemon.h"
11 #include "tools/rbd_mirror/types.h"
12 #include "test/rbd_mirror/test_fixture.h"
13 #include "test/librados/test.h"
14 #include "gtest/gtest.h"
15 #include <boost/scope_exit.hpp>
16 #include <iostream>
17 #include <map>
18 #include <memory>
19 #include <set>
20
21 using rbd::mirror::ClusterWatcher;
22 using rbd::mirror::peer_t;
23 using rbd::mirror::RadosRef;
24 using std::map;
25 using std::set;
26 using std::string;
27
28 void register_test_cluster_watcher() {
29 }
30
31 class TestClusterWatcher : public ::rbd::mirror::TestFixture {
32 public:
33
34   TestClusterWatcher() : m_lock("TestClusterWatcherLock")
35   {
36     m_cluster = std::make_shared<librados::Rados>();
37     EXPECT_EQ("", connect_cluster_pp(*m_cluster));
38   }
39
40   ~TestClusterWatcher() override {
41     m_cluster->wait_for_latest_osdmap();
42     for (auto& pool : m_pools) {
43       EXPECT_EQ(0, m_cluster->pool_delete(pool.c_str()));
44     }
45   }
46
47   void SetUp() override {
48     TestFixture::SetUp();
49     m_service_daemon.reset(new rbd::mirror::ServiceDaemon<>(g_ceph_context,
50                                                             m_cluster,
51                                                             m_threads));
52     m_cluster_watcher.reset(new ClusterWatcher(m_cluster, m_lock,
53                                                m_service_daemon.get()));
54   }
55
56   void TearDown() override {
57     m_service_daemon.reset();
58     m_cluster_watcher.reset();
59     TestFixture::TearDown();
60   }
61
62   void create_pool(bool enable_mirroring, const peer_t &peer,
63                    string *uuid = nullptr, string *name=nullptr) {
64     string pool_name = get_temp_pool_name("test-rbd-mirror-");
65     ASSERT_EQ(0, m_cluster->pool_create(pool_name.c_str()));
66
67     int64_t pool_id = m_cluster->pool_lookup(pool_name.c_str());
68     ASSERT_GE(pool_id, 0);
69
70     librados::IoCtx ioctx;
71     ASSERT_EQ(0, m_cluster->ioctx_create2(pool_id, ioctx));
72     ioctx.application_enable("rbd", true);
73
74     m_pools.insert(pool_name);
75     if (enable_mirroring) {
76       ASSERT_EQ(0, librbd::api::Mirror<>::mode_set(ioctx,
77                                                    RBD_MIRROR_MODE_POOL));
78
79       std::string gen_uuid;
80       ASSERT_EQ(0, librbd::api::Mirror<>::peer_add(ioctx,
81                                                    uuid != nullptr ? uuid :
82                                                                      &gen_uuid,
83                                                    peer.cluster_name,
84                                                    peer.client_name));
85       m_pool_peers[pool_id].insert(peer);
86     }
87     if (name != nullptr) {
88       *name = pool_name;
89     }
90   }
91
92   void delete_pool(const string &name, const peer_t &peer) {
93     int64_t pool_id = m_cluster->pool_lookup(name.c_str());
94     ASSERT_GE(pool_id, 0);
95     if (m_pool_peers.find(pool_id) != m_pool_peers.end()) {
96       m_pool_peers[pool_id].erase(peer);
97       if (m_pool_peers[pool_id].empty()) {
98         m_pool_peers.erase(pool_id);
99       }
100     }
101     m_pools.erase(name);
102     ASSERT_EQ(0, m_cluster->pool_delete(name.c_str()));
103   }
104
105   void create_cache_pool(const string &base_pool, string *cache_pool_name) {
106     bufferlist inbl;
107     *cache_pool_name = get_temp_pool_name("test-rbd-mirror-");
108     ASSERT_EQ(0, m_cluster->pool_create(cache_pool_name->c_str()));
109
110     ASSERT_EQ(0, m_cluster->mon_command(
111       "{\"prefix\": \"osd tier add\", \"pool\": \"" + base_pool +
112       "\", \"tierpool\": \"" + *cache_pool_name +
113       "\", \"force_nonempty\": \"--force-nonempty\" }",
114       inbl, NULL, NULL));
115     ASSERT_EQ(0, m_cluster->mon_command(
116       "{\"prefix\": \"osd tier set-overlay\", \"pool\": \"" + base_pool +
117       "\", \"overlaypool\": \"" + *cache_pool_name + "\"}",
118       inbl, NULL, NULL));
119     ASSERT_EQ(0, m_cluster->mon_command(
120       "{\"prefix\": \"osd tier cache-mode\", \"pool\": \"" + *cache_pool_name +
121       "\", \"mode\": \"writeback\"}",
122       inbl, NULL, NULL));
123     m_cluster->wait_for_latest_osdmap();
124   }
125
126   void remove_cache_pool(const string &base_pool, const string &cache_pool) {
127     bufferlist inbl;
128     // tear down tiers
129     ASSERT_EQ(0, m_cluster->mon_command(
130       "{\"prefix\": \"osd tier remove-overlay\", \"pool\": \"" + base_pool +
131       "\"}",
132       inbl, NULL, NULL));
133     ASSERT_EQ(0, m_cluster->mon_command(
134       "{\"prefix\": \"osd tier remove\", \"pool\": \"" + base_pool +
135       "\", \"tierpool\": \"" + cache_pool + "\"}",
136       inbl, NULL, NULL));
137     m_cluster->wait_for_latest_osdmap();
138     m_cluster->pool_delete(cache_pool.c_str());
139   }
140
141   void check_peers() {
142     m_cluster_watcher->refresh_pools();
143     Mutex::Locker l(m_lock);
144     ASSERT_EQ(m_pool_peers, m_cluster_watcher->get_pool_peers());
145   }
146
147   RadosRef m_cluster;
148   Mutex m_lock;
149   unique_ptr<rbd::mirror::ServiceDaemon<>> m_service_daemon;
150   unique_ptr<ClusterWatcher> m_cluster_watcher;
151
152   set<string> m_pools;
153   ClusterWatcher::PoolPeers m_pool_peers;
154 };
155
156 TEST_F(TestClusterWatcher, NoPools) {
157   check_peers();
158 }
159
160 TEST_F(TestClusterWatcher, NoMirroredPools) {
161   check_peers();
162   create_pool(false, peer_t());
163   check_peers();
164   create_pool(false, peer_t());
165   check_peers();
166   create_pool(false, peer_t());
167   check_peers();
168 }
169
170 TEST_F(TestClusterWatcher, ReplicatedPools) {
171   peer_t site1("", "site1", "mirror1");
172   peer_t site2("", "site2", "mirror2");
173   string first_pool, last_pool;
174   check_peers();
175   create_pool(true, site1, &site1.uuid, &first_pool);
176   check_peers();
177   create_pool(false, peer_t());
178   check_peers();
179   create_pool(false, peer_t());
180   check_peers();
181   create_pool(false, peer_t());
182   check_peers();
183   create_pool(true, site2, &site2.uuid);
184   check_peers();
185   create_pool(true, site2, &site2.uuid);
186   check_peers();
187   create_pool(true, site2, &site2.uuid, &last_pool);
188   check_peers();
189   delete_pool(first_pool, site1);
190   check_peers();
191   delete_pool(last_pool, site2);
192   check_peers();
193 }
194
195 TEST_F(TestClusterWatcher, CachePools) {
196   peer_t site1("", "site1", "mirror1");
197   string base1, base2, cache1, cache2;
198   create_pool(true, site1, &site1.uuid, &base1);
199   check_peers();
200
201   create_cache_pool(base1, &cache1);
202   BOOST_SCOPE_EXIT( base1, cache1, this_ ) {
203     this_->remove_cache_pool(base1, cache1);
204   } BOOST_SCOPE_EXIT_END;
205   check_peers();
206
207   create_pool(false, peer_t(), nullptr, &base2);
208   create_cache_pool(base2, &cache2);
209   BOOST_SCOPE_EXIT( base2, cache2, this_ ) {
210     this_->remove_cache_pool(base2, cache2);
211   } BOOST_SCOPE_EXIT_END;
212   check_peers();
213 }