001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client.replication; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertTrue; 023import static org.junit.Assert.fail; 024 025import java.util.Collection; 026import java.util.HashMap; 027import java.util.Map; 028import java.util.UUID; 029import org.apache.hadoop.hbase.HBaseClassTestRule; 030import org.apache.hadoop.hbase.HColumnDescriptor; 031import org.apache.hadoop.hbase.HConstants; 032import org.apache.hadoop.hbase.HTableDescriptor; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.TableNotFoundException; 035import org.apache.hadoop.hbase.client.Admin; 036import org.apache.hadoop.hbase.client.Connection; 037import org.apache.hadoop.hbase.client.ConnectionFactory; 038import org.apache.hadoop.hbase.replication.BaseReplicationEndpoint; 039import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; 040import org.apache.hadoop.hbase.replication.TestReplicationBase; 041import org.apache.hadoop.hbase.testclassification.ClientTests; 042import org.apache.hadoop.hbase.testclassification.MediumTests; 043import org.junit.AfterClass; 044import org.junit.BeforeClass; 045import org.junit.ClassRule; 046import org.junit.Rule; 047import org.junit.Test; 048import org.junit.experimental.categories.Category; 049import org.junit.rules.TestName; 050 051/** 052 * Unit testing of ReplicationAdmin with clusters 053 */ 054@Category({ MediumTests.class, ClientTests.class }) 055public class TestReplicationAdminWithClusters extends TestReplicationBase { 056 057 @ClassRule 058 public static final HBaseClassTestRule CLASS_RULE = 059 HBaseClassTestRule.forClass(TestReplicationAdminWithClusters.class); 060 061 static Connection connection1; 062 static Connection connection2; 063 static Admin admin1; 064 static Admin admin2; 065 static ReplicationAdmin adminExt; 066 067 @Rule 068 public TestName name = new TestName(); 069 070 @BeforeClass 071 public static void setUpBeforeClass() throws Exception { 072 TestReplicationBase.setUpBeforeClass(); 073 connection1 = ConnectionFactory.createConnection(conf1); 074 connection2 = ConnectionFactory.createConnection(conf2); 075 admin1 = connection1.getAdmin(); 076 admin2 = connection2.getAdmin(); 077 adminExt = new ReplicationAdmin(conf1); 078 } 079 080 @AfterClass 081 public static void tearDownAfterClass() throws Exception { 082 admin1.close(); 083 admin2.close(); 084 adminExt.close(); 085 connection1.close(); 086 connection2.close(); 087 TestReplicationBase.tearDownAfterClass(); 088 } 089 090 @Test 091 public void disableNotFullReplication() throws Exception { 092 HTableDescriptor table = new HTableDescriptor(admin2.getTableDescriptor(tableName)); 093 HColumnDescriptor f = new HColumnDescriptor("notReplicatedFamily"); 094 table.addFamily(f); 095 admin1.disableTable(tableName); 096 admin1.modifyTable(tableName, table); 097 admin1.enableTable(tableName); 098 099 admin1.disableTableReplication(tableName); 100 table = admin1.getTableDescriptor(tableName); 101 for (HColumnDescriptor fam : table.getColumnFamilies()) { 102 assertEquals(HConstants.REPLICATION_SCOPE_LOCAL, fam.getScope()); 103 } 104 105 admin1.deleteColumnFamily(table.getTableName(), f.getName()); 106 } 107 108 @Test 109 public void testEnableReplicationWhenSlaveClusterDoesntHaveTable() throws Exception { 110 admin1.disableTableReplication(tableName); 111 admin2.disableTable(tableName); 112 admin2.deleteTable(tableName); 113 assertFalse(admin2.tableExists(tableName)); 114 admin1.enableTableReplication(tableName); 115 assertTrue(admin2.tableExists(tableName)); 116 } 117 118 @Test 119 public void testEnableReplicationWhenReplicationNotEnabled() throws Exception { 120 HTableDescriptor table = new HTableDescriptor(admin1.getTableDescriptor(tableName)); 121 for (HColumnDescriptor fam : table.getColumnFamilies()) { 122 fam.setScope(HConstants.REPLICATION_SCOPE_LOCAL); 123 } 124 admin1.disableTable(tableName); 125 admin1.modifyTable(tableName, table); 126 admin1.enableTable(tableName); 127 128 admin2.disableTable(tableName); 129 admin2.modifyTable(tableName, table); 130 admin2.enableTable(tableName); 131 132 admin1.enableTableReplication(tableName); 133 table = admin1.getTableDescriptor(tableName); 134 for (HColumnDescriptor fam : table.getColumnFamilies()) { 135 assertEquals(HConstants.REPLICATION_SCOPE_GLOBAL, fam.getScope()); 136 } 137 } 138 139 @Test 140 public void testEnableReplicationWhenTableDescriptorIsNotSameInClusters() throws Exception { 141 HTableDescriptor table = new HTableDescriptor(admin2.getTableDescriptor(tableName)); 142 HColumnDescriptor f = new HColumnDescriptor("newFamily"); 143 table.addFamily(f); 144 admin2.disableTable(tableName); 145 admin2.modifyTable(tableName, table); 146 admin2.enableTable(tableName); 147 148 try { 149 admin1.enableTableReplication(tableName); 150 fail("Exception should be thrown if table descriptors in the clusters are not same."); 151 } catch (RuntimeException ignored) { 152 153 } 154 admin1.disableTable(tableName); 155 admin1.modifyTable(tableName, table); 156 admin1.enableTable(tableName); 157 admin1.enableTableReplication(tableName); 158 table = admin1.getTableDescriptor(tableName); 159 for (HColumnDescriptor fam : table.getColumnFamilies()) { 160 assertEquals(HConstants.REPLICATION_SCOPE_GLOBAL, fam.getScope()); 161 } 162 163 admin1.deleteColumnFamily(tableName, f.getName()); 164 admin2.deleteColumnFamily(tableName, f.getName()); 165 } 166 167 @Test 168 public void testDisableAndEnableReplication() throws Exception { 169 admin1.disableTableReplication(tableName); 170 HTableDescriptor table = admin1.getTableDescriptor(tableName); 171 for (HColumnDescriptor fam : table.getColumnFamilies()) { 172 assertEquals(HConstants.REPLICATION_SCOPE_LOCAL, fam.getScope()); 173 } 174 admin1.enableTableReplication(tableName); 175 table = admin1.getTableDescriptor(tableName); 176 for (HColumnDescriptor fam : table.getColumnFamilies()) { 177 assertEquals(HConstants.REPLICATION_SCOPE_GLOBAL, fam.getScope()); 178 } 179 } 180 181 @Test(expected = TableNotFoundException.class) 182 public void testDisableReplicationForNonExistingTable() throws Exception { 183 admin1.disableTableReplication(TableName.valueOf(name.getMethodName())); 184 } 185 186 @Test(expected = TableNotFoundException.class) 187 public void testEnableReplicationForNonExistingTable() throws Exception { 188 admin1.enableTableReplication(TableName.valueOf(name.getMethodName())); 189 } 190 191 @Test(expected = IllegalArgumentException.class) 192 public void testDisableReplicationWhenTableNameAsNull() throws Exception { 193 admin1.disableTableReplication(null); 194 } 195 196 @Test(expected = IllegalArgumentException.class) 197 public void testEnableReplicationWhenTableNameAsNull() throws Exception { 198 admin1.enableTableReplication(null); 199 } 200 201 /* 202 * Test enable table replication should create table only in user explicit specified table-cfs. 203 * HBASE-14717 204 */ 205 @Test 206 public void testEnableReplicationForExplicitSetTableCfs() throws Exception { 207 final TableName tableName = TableName.valueOf(name.getMethodName()); 208 String peerId = "2"; 209 if (admin2.isTableAvailable(TestReplicationBase.tableName)) { 210 admin2.disableTable(TestReplicationBase.tableName); 211 admin2.deleteTable(TestReplicationBase.tableName); 212 } 213 assertFalse("Table should not exists in the peer cluster", 214 admin2.isTableAvailable(TestReplicationBase.tableName)); 215 216 // update peer config 217 ReplicationPeerConfig rpc = admin1.getReplicationPeerConfig(peerId); 218 rpc.setReplicateAllUserTables(false); 219 admin1.updateReplicationPeerConfig(peerId, rpc); 220 221 Map<TableName, ? extends Collection<String>> tableCfs = new HashMap<>(); 222 tableCfs.put(tableName, null); 223 try { 224 adminExt.setPeerTableCFs(peerId, tableCfs); 225 admin1.enableTableReplication(TestReplicationBase.tableName); 226 assertFalse("Table should not be created if user has set table cfs explicitly for the " 227 + "peer and this is not part of that collection", 228 admin2.isTableAvailable(TestReplicationBase.tableName)); 229 230 tableCfs.put(TestReplicationBase.tableName, null); 231 adminExt.setPeerTableCFs(peerId, tableCfs); 232 admin1.enableTableReplication(TestReplicationBase.tableName); 233 assertTrue( 234 "Table should be created if user has explicitly added table into table cfs collection", 235 admin2.isTableAvailable(TestReplicationBase.tableName)); 236 } finally { 237 adminExt.removePeerTableCFs(peerId, adminExt.getPeerTableCFs(peerId)); 238 admin1.disableTableReplication(TestReplicationBase.tableName); 239 240 rpc = admin1.getReplicationPeerConfig(peerId); 241 rpc.setReplicateAllUserTables(true); 242 admin1.updateReplicationPeerConfig(peerId, rpc); 243 } 244 } 245 246 @Test 247 public void testReplicationPeerConfigUpdateCallback() throws Exception { 248 String peerId = "1"; 249 ReplicationPeerConfig rpc = new ReplicationPeerConfig(); 250 rpc.setClusterKey(utility2.getClusterKey()); 251 rpc.setReplicationEndpointImpl(TestUpdatableReplicationEndpoint.class.getName()); 252 rpc.getConfiguration().put("key1", "value1"); 253 254 admin1.addReplicationPeer(peerId, rpc); 255 256 rpc.getConfiguration().put("key1", "value2"); 257 admin.updatePeerConfig(peerId, rpc); 258 if (!TestUpdatableReplicationEndpoint.hasCalledBack()) { 259 synchronized (TestUpdatableReplicationEndpoint.class) { 260 TestUpdatableReplicationEndpoint.class.wait(2000L); 261 } 262 } 263 264 assertEquals(true, TestUpdatableReplicationEndpoint.hasCalledBack()); 265 266 admin.removePeer(peerId); 267 } 268 269 public static class TestUpdatableReplicationEndpoint extends BaseReplicationEndpoint { 270 private static boolean calledBack = false; 271 public static boolean hasCalledBack(){ 272 return calledBack; 273 } 274 @Override 275 public synchronized void peerConfigUpdated(ReplicationPeerConfig rpc){ 276 calledBack = true; 277 notifyAll(); 278 } 279 280 @Override 281 public void start() { 282 startAsync(); 283 } 284 285 @Override 286 public void stop() { 287 stopAsync(); 288 } 289 290 @Override 291 protected void doStart() { 292 notifyStarted(); 293 } 294 295 @Override 296 protected void doStop() { 297 notifyStopped(); 298 } 299 300 @Override 301 public UUID getPeerUUID() { 302 return utility1.getRandomUUID(); 303 } 304 305 @Override 306 public boolean replicate(ReplicateContext replicateContext) { 307 return false; 308 } 309 } 310}