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