View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.client.replication;
19  
20  import java.util.List;
21  import java.util.Map;
22  import java.util.TreeMap;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.replication.ReplicationException;
31  import org.apache.hadoop.hbase.replication.ReplicationFactory;
32  import org.apache.hadoop.hbase.replication.ReplicationPeer;
33  import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
34  import org.apache.hadoop.hbase.replication.ReplicationQueues;
35  import org.apache.hadoop.hbase.replication.ReplicationQueuesZKImpl;
36  import org.apache.hadoop.hbase.testclassification.MediumTests;
37  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
38  import org.junit.AfterClass;
39  import org.junit.BeforeClass;
40  import org.junit.Test;
41  import org.junit.experimental.categories.Category;
42  
43  import com.google.common.collect.Lists;
44  
45  import static org.junit.Assert.assertEquals;
46  import static org.junit.Assert.assertFalse;
47  import static org.junit.Assert.assertNotNull;
48  import static org.junit.Assert.assertTrue;
49  import static org.junit.Assert.fail;
50  
51  
52  /**
53   * Unit testing of ReplicationAdmin
54   */
55  @Category(MediumTests.class)
56  public class TestReplicationAdmin {
57  
58    private static final Log LOG =
59        LogFactory.getLog(TestReplicationAdmin.class);
60    private final static HBaseTestingUtility TEST_UTIL =
61        new HBaseTestingUtility();
62  
63    private final String ID_ONE = "1";
64    private final String KEY_ONE = "127.0.0.1:2181:/hbase";
65    private final String ID_SECOND = "2";
66    private final String KEY_SECOND = "127.0.0.1:2181:/hbase2";
67  
68    private static ReplicationAdmin admin;
69  
70    /**
71     * @throws java.lang.Exception
72     */
73    @BeforeClass
74    public static void setUpBeforeClass() throws Exception {
75      TEST_UTIL.startMiniZKCluster();
76      Configuration conf = TEST_UTIL.getConfiguration();
77      conf.setBoolean(HConstants.REPLICATION_ENABLE_KEY, HConstants.REPLICATION_ENABLE_DEFAULT);
78      admin = new ReplicationAdmin(conf);
79    }
80  
81    @AfterClass
82    public static void tearDownAfterClass() throws Exception {
83      if (admin != null) {
84        admin.close();
85      }
86      TEST_UTIL.shutdownMiniZKCluster();
87    }
88  
89    /**
90     * Simple testing of adding and removing peers, basically shows that
91     * all interactions with ZK work
92     * @throws Exception
93     */
94    @Test
95    public void testAddRemovePeer() throws Exception {
96      // Add a valid peer
97      admin.addPeer(ID_ONE, KEY_ONE);
98      // try adding the same (fails)
99      try {
100       admin.addPeer(ID_ONE, KEY_ONE);
101     } catch (IllegalArgumentException iae) {
102       // OK!
103     }
104     assertEquals(1, admin.getPeersCount());
105 
106     // try adding a peer contains "-"
107     try {
108       admin.addPeer(ID_ONE + "-" + ID_SECOND, KEY_ONE);
109     } catch (IllegalArgumentException iae) {
110       // OK!
111     }
112     assertEquals(1, admin.getPeersCount());
113     // try adding a peer named "lock"
114     try {
115       admin.addPeer(ReplicationQueuesZKImpl.RS_LOCK_ZNODE, KEY_ONE);
116     } catch (IllegalArgumentException iae) {
117       // OK!
118     }
119     assertEquals(1, admin.getPeersCount());
120 
121     // Try to remove an inexisting peer
122     try {
123       admin.removePeer(ID_SECOND);
124       fail();
125     } catch (IllegalArgumentException iae) {
126       // OK!
127     }
128     assertEquals(1, admin.getPeersCount());
129     // Add a second since multi-slave is supported
130     try {
131       admin.addPeer(ID_SECOND, KEY_SECOND);
132     } catch (IllegalStateException iae) {
133       fail();
134     }
135     assertEquals(2, admin.getPeersCount());
136     // Remove the first peer we added
137     admin.removePeer(ID_ONE);
138     assertEquals(1, admin.getPeersCount());
139     admin.removePeer(ID_SECOND);
140     assertEquals(0, admin.getPeersCount());
141   }
142   
143   @Test
144   public void testAddPeerWithUnDeletedQueues() throws Exception {
145     Configuration conf = TEST_UTIL.getConfiguration();
146     ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf, "Test HBaseAdmin", null);
147     ReplicationQueues repQueues =
148         ReplicationFactory.getReplicationQueues(zkw, conf, null);
149     repQueues.init("server1");
150 
151     // add queue for ID_ONE
152     repQueues.addLog(ID_ONE, "file1");
153     try {
154       admin.addPeer(ID_ONE, KEY_ONE);
155       fail();
156     } catch (ReplicationException e) {
157       // OK!
158     }
159     repQueues.removeQueue(ID_ONE);
160     assertEquals(0, repQueues.getAllQueues().size());
161 
162     // add recovered queue for ID_ONE
163     repQueues.addLog(ID_ONE + "-server2", "file1");
164     try {
165       admin.addPeer(ID_ONE, KEY_ONE);
166       fail();
167     } catch (ReplicationException e) {
168       // OK!
169     }
170     repQueues.removeAllQueues();
171     zkw.close();
172   }
173 
174   /**
175    * Tests that the peer configuration used by ReplicationAdmin contains all
176    * the peer's properties.
177    */
178   @Test
179   public void testPeerConfig() throws Exception {
180     ReplicationPeerConfig config = new ReplicationPeerConfig();
181     config.setClusterKey(KEY_ONE);
182     config.getConfiguration().put("key1", "value1");
183     config.getConfiguration().put("key2", "value2");
184     admin.addPeer(ID_ONE, config, null);
185 
186     List<ReplicationPeer> peers = admin.listReplicationPeers();
187     assertEquals(1, peers.size());
188     ReplicationPeer peerOne = peers.get(0);
189     assertNotNull(peerOne);
190     assertEquals("value1", peerOne.getConfiguration().get("key1"));
191     assertEquals("value2", peerOne.getConfiguration().get("key2"));
192 
193     admin.removePeer(ID_ONE);
194   }
195 
196   /**
197    * basic checks that when we add a peer that it is enabled, and that we can disable
198    * @throws Exception
199    */
200   @Test
201   public void testEnableDisable() throws Exception {
202     admin.addPeer(ID_ONE, KEY_ONE);
203     assertEquals(1, admin.getPeersCount());
204     assertTrue(admin.getPeerState(ID_ONE));
205     admin.disablePeer(ID_ONE);
206 
207     assertFalse(admin.getPeerState(ID_ONE));
208     try {
209       admin.getPeerState(ID_SECOND);
210     } catch (IllegalArgumentException iae) {
211       // OK!
212     }
213     admin.removePeer(ID_ONE);
214   }
215 
216   @Test
217   public void testGetTableCfsStr() {
218     // opposite of TestPerTableCFReplication#testParseTableCFsFromConfig()
219 
220     Map<TableName, List<String>> tabCFsMap = null;
221 
222     // 1. null or empty string, result should be null
223     assertEquals(null, ReplicationAdmin.getTableCfsStr(tabCFsMap));
224 
225 
226     // 2. single table: "tab1" / "tab2:cf1" / "tab3:cf1,cf3"
227     tabCFsMap = new TreeMap<TableName, List<String>>();
228     tabCFsMap.put(TableName.valueOf("tab1"), null);   // its table name is "tab1"
229     assertEquals("tab1", ReplicationAdmin.getTableCfsStr(tabCFsMap));
230 
231     tabCFsMap = new TreeMap<TableName, List<String>>();
232     tabCFsMap.put(TableName.valueOf("tab1"), Lists.newArrayList("cf1"));
233     assertEquals("tab1:cf1", ReplicationAdmin.getTableCfsStr(tabCFsMap));
234 
235     tabCFsMap = new TreeMap<TableName, List<String>>();
236     tabCFsMap.put(TableName.valueOf("tab1"), Lists.newArrayList("cf1", "cf3"));
237     assertEquals("tab1:cf1,cf3", ReplicationAdmin.getTableCfsStr(tabCFsMap));
238 
239     // 3. multiple tables: "tab1 ; tab2:cf1 ; tab3:cf1,cf3"
240     tabCFsMap = new TreeMap<TableName, List<String>>();
241     tabCFsMap.put(TableName.valueOf("tab1"), null);
242     tabCFsMap.put(TableName.valueOf("tab2"), Lists.newArrayList("cf1"));
243     tabCFsMap.put(TableName.valueOf("tab3"), Lists.newArrayList("cf1", "cf3"));
244     assertEquals("tab1;tab2:cf1;tab3:cf1,cf3", ReplicationAdmin.getTableCfsStr(tabCFsMap));
245   }
246 
247   @Test
248   public void testAppendPeerTableCFs() throws Exception {
249     // Add a valid peer
250     admin.addPeer(ID_ONE, KEY_ONE);
251 
252     admin.appendPeerTableCFs(ID_ONE, "t1");
253     assertEquals("t1", admin.getPeerTableCFs(ID_ONE));
254 
255     // append table t2 to replication
256     admin.appendPeerTableCFs(ID_ONE, "t2");
257     String peerTablesOne = admin.getPeerTableCFs(ID_ONE);
258 
259     // Different jdk's return different sort order for the tables. ( Not sure on why exactly )
260     //
261     // So instead of asserting that the string is exactly we
262     // assert that the string contains all tables and the needed separator.
263     assertTrue("Should contain t1", peerTablesOne.contains("t1"));
264     assertTrue("Should contain t2", peerTablesOne.contains("t2"));
265     assertTrue("Should contain ; as the seperator", peerTablesOne.contains(";"));
266 
267     // append table column family: f1 of t3 to replication
268     admin.appendPeerTableCFs(ID_ONE, "t3:f1");
269     String peerTablesTwo = admin.getPeerTableCFs(ID_ONE);
270     assertTrue("Should contain t1", peerTablesTwo.contains("t1"));
271     assertTrue("Should contain t2", peerTablesTwo.contains("t2"));
272     assertTrue("Should contain t3:f1", peerTablesTwo.contains("t3:f1"));
273     assertTrue("Should contain ; as the seperator", peerTablesTwo.contains(";"));
274     admin.removePeer(ID_ONE);
275   }
276 
277   @Test
278   public void testRemovePeerTableCFs() throws Exception {
279     // Add a valid peer
280     admin.addPeer(ID_ONE, KEY_ONE);
281     try {
282       admin.removePeerTableCFs(ID_ONE, "t3");
283       assertTrue(false);
284     } catch (ReplicationException e) {
285     }
286     assertEquals("", admin.getPeerTableCFs(ID_ONE));
287 
288     admin.setPeerTableCFs(ID_ONE, "t1;t2:cf1");
289     try {
290       admin.removePeerTableCFs(ID_ONE, "t3");
291       assertTrue(false);
292     } catch (ReplicationException e) {
293     }
294     assertEquals("t1;t2:cf1", admin.getPeerTableCFs(ID_ONE));
295 
296     try {
297       admin.removePeerTableCFs(ID_ONE, "t1:f1");
298       assertTrue(false);
299     } catch (ReplicationException e) {
300     }
301     admin.removePeerTableCFs(ID_ONE, "t1");
302     assertEquals("t2:cf1", admin.getPeerTableCFs(ID_ONE));
303 
304     try {
305       admin.removePeerTableCFs(ID_ONE, "t2");
306       assertTrue(false);
307     } catch (ReplicationException e) {
308     }
309     admin.removePeerTableCFs(ID_ONE, "t2:cf1");
310     assertEquals("", admin.getPeerTableCFs(ID_ONE));
311     admin.removePeer(ID_ONE);
312   }
313 }