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.ArrayList;
21  import java.util.HashMap;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.TreeMap;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.apache.hadoop.conf.Configuration;
29  import org.apache.hadoop.hbase.HBaseTestingUtility;
30  import org.apache.hadoop.hbase.HConstants;
31  import org.apache.hadoop.hbase.TableName;
32  import org.apache.hadoop.hbase.replication.ReplicationException;
33  import org.apache.hadoop.hbase.replication.ReplicationFactory;
34  import org.apache.hadoop.hbase.replication.ReplicationPeer;
35  import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
36  import org.apache.hadoop.hbase.replication.ReplicationQueues;
37  import org.apache.hadoop.hbase.replication.ReplicationQueuesZKImpl;
38  import org.apache.hadoop.hbase.testclassification.MediumTests;
39  import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
40  import org.junit.AfterClass;
41  import org.junit.BeforeClass;
42  import org.junit.Test;
43  import org.junit.experimental.categories.Category;
44  
45  import com.google.common.collect.Lists;
46  
47  import static org.junit.Assert.assertEquals;
48  import static org.junit.Assert.assertFalse;
49  import static org.junit.Assert.assertNotNull;
50  import static org.junit.Assert.assertNull;
51  import static org.junit.Assert.assertTrue;
52  import static org.junit.Assert.fail;
53  
54  
55  /**
56   * Unit testing of ReplicationAdmin
57   */
58  @Category(MediumTests.class)
59  public class TestReplicationAdmin {
60  
61    private static final Log LOG =
62        LogFactory.getLog(TestReplicationAdmin.class);
63    private final static HBaseTestingUtility TEST_UTIL =
64        new HBaseTestingUtility();
65  
66    private final String ID_ONE = "1";
67    private final String KEY_ONE = "127.0.0.1:2181:/hbase";
68    private final String ID_SECOND = "2";
69    private final String KEY_SECOND = "127.0.0.1:2181:/hbase2";
70  
71    private static ReplicationAdmin admin;
72  
73    /**
74     * @throws java.lang.Exception
75     */
76    @BeforeClass
77    public static void setUpBeforeClass() throws Exception {
78      TEST_UTIL.startMiniZKCluster();
79      Configuration conf = TEST_UTIL.getConfiguration();
80      conf.setBoolean(HConstants.REPLICATION_ENABLE_KEY, HConstants.REPLICATION_ENABLE_DEFAULT);
81      admin = new ReplicationAdmin(conf);
82    }
83  
84    @AfterClass
85    public static void tearDownAfterClass() throws Exception {
86      if (admin != null) {
87        admin.close();
88      }
89      TEST_UTIL.shutdownMiniZKCluster();
90    }
91  
92    /**
93     * Simple testing of adding and removing peers, basically shows that
94     * all interactions with ZK work
95     * @throws Exception
96     */
97    @Test
98    public void testAddRemovePeer() throws Exception {
99      ReplicationPeerConfig rpc1 = new ReplicationPeerConfig();
100     rpc1.setClusterKey(KEY_ONE);
101     ReplicationPeerConfig rpc2 = new ReplicationPeerConfig();
102     rpc2.setClusterKey(KEY_SECOND);
103     // Add a valid peer
104     admin.addPeer(ID_ONE, rpc1);
105     // try adding the same (fails)
106     try {
107       admin.addPeer(ID_ONE, rpc1);
108     } catch (IllegalArgumentException iae) {
109       // OK!
110     }
111     assertEquals(1, admin.getPeersCount());
112 
113     // try adding a peer contains "-"
114     try {
115       admin.addPeer(ID_ONE + "-" + ID_SECOND, KEY_ONE);
116     } catch (IllegalArgumentException iae) {
117       // OK!
118     }
119     assertEquals(1, admin.getPeersCount());
120     // try adding a peer named "lock"
121     try {
122       admin.addPeer(ReplicationQueuesZKImpl.RS_LOCK_ZNODE, KEY_ONE);
123     } catch (IllegalArgumentException iae) {
124       // OK!
125     }
126     assertEquals(1, admin.getPeersCount());
127 
128     // Try to remove an inexisting peer
129     try {
130       admin.removePeer(ID_SECOND);
131       fail();
132     } catch (IllegalArgumentException iae) {
133       // OK!
134     }
135     assertEquals(1, admin.getPeersCount());
136     // Add a second since multi-slave is supported
137     try {
138       admin.addPeer(ID_SECOND, rpc2);
139     } catch (IllegalStateException iae) {
140       fail();
141     }
142     assertEquals(2, admin.getPeersCount());
143     // Remove the first peer we added
144     admin.removePeer(ID_ONE);
145     assertEquals(1, admin.getPeersCount());
146     admin.removePeer(ID_SECOND);
147     assertEquals(0, admin.getPeersCount());
148   }
149   
150   @Test
151   public void testAddPeerWithUnDeletedQueues() throws Exception {
152     ReplicationPeerConfig rpc1 = new ReplicationPeerConfig();
153     rpc1.setClusterKey(KEY_ONE);
154     ReplicationPeerConfig rpc2 = new ReplicationPeerConfig();
155     rpc2.setClusterKey(KEY_SECOND);
156     Configuration conf = TEST_UTIL.getConfiguration();
157     ZooKeeperWatcher zkw = new ZooKeeperWatcher(conf, "Test HBaseAdmin", null);
158     ReplicationQueues repQueues =
159         ReplicationFactory.getReplicationQueues(zkw, conf, null);
160     repQueues.init("server1");
161 
162     // add queue for ID_ONE
163     repQueues.addLog(ID_ONE, "file1");
164     try {
165       admin.addPeer(ID_ONE, rpc1);
166       fail();
167     } catch (ReplicationException e) {
168       // OK!
169     }
170     repQueues.removeQueue(ID_ONE);
171     assertEquals(0, repQueues.getAllQueues().size());
172 
173     // add recovered queue for ID_ONE
174     repQueues.addLog(ID_ONE + "-server2", "file1");
175     try {
176       admin.addPeer(ID_ONE, rpc2);
177       fail();
178     } catch (ReplicationException e) {
179       // OK!
180     }
181     repQueues.removeAllQueues();
182     zkw.close();
183   }
184 
185   /**
186    * Tests that the peer configuration used by ReplicationAdmin contains all
187    * the peer's properties.
188    */
189   @Test
190   public void testPeerConfig() throws Exception {
191     ReplicationPeerConfig config = new ReplicationPeerConfig();
192     config.setClusterKey(KEY_ONE);
193     config.getConfiguration().put("key1", "value1");
194     config.getConfiguration().put("key2", "value2");
195     admin.addPeer(ID_ONE, config, null);
196 
197     List<ReplicationPeer> peers = admin.listReplicationPeers();
198     assertEquals(1, peers.size());
199     ReplicationPeer peerOne = peers.get(0);
200     assertNotNull(peerOne);
201     assertEquals("value1", peerOne.getConfiguration().get("key1"));
202     assertEquals("value2", peerOne.getConfiguration().get("key2"));
203 
204     admin.removePeer(ID_ONE);
205   }
206 
207   /**
208    * basic checks that when we add a peer that it is enabled, and that we can disable
209    * @throws Exception
210    */
211   @Test
212   public void testEnableDisable() throws Exception {
213     ReplicationPeerConfig rpc1 = new ReplicationPeerConfig();
214     rpc1.setClusterKey(KEY_ONE);
215     admin.addPeer(ID_ONE, rpc1);
216     assertEquals(1, admin.getPeersCount());
217     assertTrue(admin.getPeerState(ID_ONE));
218     admin.disablePeer(ID_ONE);
219 
220     assertFalse(admin.getPeerState(ID_ONE));
221     try {
222       admin.getPeerState(ID_SECOND);
223     } catch (IllegalArgumentException iae) {
224       // OK!
225     }
226     admin.removePeer(ID_ONE);
227   }
228 
229   @Test
230   public void testAppendPeerTableCFs() throws Exception {
231     ReplicationPeerConfig rpc1 = new ReplicationPeerConfig();
232     rpc1.setClusterKey(KEY_ONE);
233     TableName tab1 = TableName.valueOf("t1");
234     TableName tab2 = TableName.valueOf("t2");
235     TableName tab3 = TableName.valueOf("t3");
236     TableName tab4 = TableName.valueOf("t4");
237 
238     // Add a valid peer
239     admin.addPeer(ID_ONE, rpc1);
240 
241     Map<TableName, List<String>> tableCFs = new HashMap<>();
242 
243     tableCFs.put(tab1, null);
244     admin.appendPeerTableCFs(ID_ONE, tableCFs);
245     Map<TableName, List<String>> result = admin.getPeerConfig(ID_ONE).getTableCFsMap();
246     assertEquals(1, result.size());
247     assertEquals(true, result.containsKey(tab1));
248     assertNull(result.get(tab1));
249 
250     // append table t2 to replication
251     tableCFs.clear();
252     tableCFs.put(tab2, null);
253     admin.appendPeerTableCFs(ID_ONE, tableCFs);
254     result = admin.getPeerConfig(ID_ONE).getTableCFsMap();
255     assertEquals(2, result.size());
256     assertTrue("Should contain t1", result.containsKey(tab1));
257     assertTrue("Should contain t2", result.containsKey(tab2));
258     assertNull(result.get(tab1));
259     assertNull(result.get(tab2));
260 
261     // append table column family: f1 of t3 to replication
262     tableCFs.clear();
263     tableCFs.put(tab3, new ArrayList<String>());
264     tableCFs.get(tab3).add("f1");
265     admin.appendPeerTableCFs(ID_ONE, tableCFs);
266     result = admin.getPeerConfig(ID_ONE).getTableCFsMap();
267     assertEquals(3, result.size());
268     assertTrue("Should contain t1", result.containsKey(tab1));
269     assertTrue("Should contain t2", result.containsKey(tab2));
270     assertTrue("Should contain t3", result.containsKey(tab3));
271     assertNull(result.get(tab1));
272     assertNull(result.get(tab2));
273     assertEquals(1, result.get(tab3).size());
274     assertEquals("f1", result.get(tab3).get(0));
275 
276     tableCFs.clear();
277     tableCFs.put(tab4, new ArrayList<String>());
278     tableCFs.get(tab4).add("f1");
279     tableCFs.get(tab4).add("f2");
280     admin.appendPeerTableCFs(ID_ONE, tableCFs);
281     result = admin.getPeerConfig(ID_ONE).getTableCFsMap();
282     assertEquals(4, result.size());
283     assertTrue("Should contain t1", result.containsKey(tab1));
284     assertTrue("Should contain t2", result.containsKey(tab2));
285     assertTrue("Should contain t3", result.containsKey(tab3));
286     assertTrue("Should contain t4", result.containsKey(tab4));
287     assertNull(result.get(tab1));
288     assertNull(result.get(tab2));
289     assertEquals(1, result.get(tab3).size());
290     assertEquals("f1", result.get(tab3).get(0));
291     assertEquals(2, result.get(tab4).size());
292     assertEquals("f1", result.get(tab4).get(0));
293     assertEquals("f2", result.get(tab4).get(1));
294 
295     admin.removePeer(ID_ONE);
296   }
297 
298   @Test
299   public void testRemovePeerTableCFs() throws Exception {
300     ReplicationPeerConfig rpc1 = new ReplicationPeerConfig();
301     rpc1.setClusterKey(KEY_ONE);
302     TableName tab1 = TableName.valueOf("t1");
303     TableName tab2 = TableName.valueOf("t2");
304     TableName tab3 = TableName.valueOf("t3");
305     // Add a valid peer
306     admin.addPeer(ID_ONE, rpc1);
307     Map<TableName, List<String>> tableCFs = new HashMap<>();
308     try {
309       tableCFs.put(tab3, null);
310       admin.removePeerTableCFs(ID_ONE, tableCFs);
311       assertTrue(false);
312     } catch (ReplicationException e) {
313     }
314     assertNull(admin.getPeerConfig(ID_ONE).getTableCFsMap());
315 
316     tableCFs.clear();
317     tableCFs.put(tab1, null);
318     tableCFs.put(tab2, new ArrayList<String>());
319     tableCFs.get(tab2).add("cf1");
320     admin.setPeerTableCFs(ID_ONE, tableCFs);
321     try {
322       tableCFs.clear();
323       tableCFs.put(tab3, null);
324       admin.removePeerTableCFs(ID_ONE, tableCFs);
325       assertTrue(false);
326     } catch (ReplicationException e) {
327     }
328     Map<TableName, List<String>> result = admin.getPeerConfig(ID_ONE).getTableCFsMap();
329     assertEquals(2, result.size());
330     assertTrue("Should contain t1", result.containsKey(tab1));
331     assertTrue("Should contain t2", result.containsKey(tab2));
332     assertNull(result.get(tab1));
333     assertEquals(1, result.get(tab2).size());
334     assertEquals("cf1", result.get(tab2).get(0));
335 
336     tableCFs.clear();
337     tableCFs.put(tab1, new ArrayList<String>());
338     tableCFs.get(tab1).add("f1");
339     try {
340       admin.removePeerTableCFs(ID_ONE, tableCFs);
341       assertTrue(false);
342     } catch (ReplicationException e) {
343     }
344     tableCFs.clear();
345     tableCFs.put(tab1, null);
346     admin.removePeerTableCFs(ID_ONE, tableCFs);
347     result = admin.getPeerConfig(ID_ONE).getTableCFsMap();
348     assertEquals(1, result.size());
349     assertEquals(1, result.get(tab2).size());
350     assertEquals("cf1", result.get(tab2).get(0));
351 
352     tableCFs.clear();
353     tableCFs.put(tab2, null);
354     try {
355       admin.removePeerTableCFs(ID_ONE, tableCFs);
356       assertTrue(false);
357     } catch (ReplicationException e) {
358     }
359     tableCFs.clear();
360     tableCFs.put(tab2, new ArrayList<String>());
361     tableCFs.get(tab2).add("cf1");
362     admin.removePeerTableCFs(ID_ONE, tableCFs);
363     assertNull(admin.getPeerConfig(ID_ONE).getTableCFsMap());
364     admin.removePeer(ID_ONE);
365   }
366 
367   @Test
368   public void testPeerBandwidth() throws ReplicationException {
369     ReplicationPeerConfig rpc = new ReplicationPeerConfig();
370     rpc.setClusterKey(KEY_ONE);
371     admin.addPeer(ID_ONE, rpc);
372     admin.peerAdded(ID_ONE);
373 
374     rpc = admin.getPeerConfig(ID_ONE);
375     assertEquals(0, rpc.getBandwidth());
376 
377     rpc.setBandwidth(2097152);
378     admin.updatePeerConfig(ID_ONE, rpc);
379 
380     assertEquals(2097152, admin.getPeerConfig(ID_ONE).getBandwidth());
381     admin.removePeer(ID_ONE);
382   }
383 
384   @Test
385   public void testUpdatePeerConfig() throws Exception {
386     TableName tab1 = TableName.valueOf("t1");
387     TableName tab2 = TableName.valueOf("t2");
388     Map<TableName, List<String>> tableCFs = new HashMap<>();
389 
390     ReplicationPeerConfig config = new ReplicationPeerConfig();
391     config.setClusterKey(KEY_ONE);
392     config.getConfiguration().put("key1", "value1");
393     tableCFs.put(tab1, new ArrayList<String>());
394     config.setTableCFsMap(tableCFs);
395     admin.addPeer(ID_ONE, config, null);
396     admin.peerAdded(ID_ONE);
397 
398     config = admin.getPeerConfig(ID_ONE);
399     assertEquals("value1", config.getConfiguration().get("key1"));
400     assertNull(config.getConfiguration().get("key2"));
401     assertTrue(config.getTableCFsMap().containsKey(tab1));
402     assertFalse(config.getTableCFsMap().containsKey(tab2));
403 
404     // Update replication peer config
405     config = new ReplicationPeerConfig();
406     config.setClusterKey(KEY_ONE);
407     config.getConfiguration().put("key2", "value2");
408     tableCFs.clear();
409     tableCFs.put(tab2, new ArrayList<String>());
410     config.setTableCFsMap(tableCFs);
411     admin.updatePeerConfig(ID_ONE, config);
412 
413     config = admin.getPeerConfig(ID_ONE);
414     assertEquals("value1", config.getConfiguration().get("key1"));
415     assertEquals("value2", config.getConfiguration().get("key2"));
416     assertFalse(config.getTableCFsMap().containsKey(tab1));
417     assertTrue(config.getTableCFsMap().containsKey(tab2));
418 
419     admin.removePeer(ID_ONE);
420   }
421 }