/** * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable * law or agreed to in writing, software distributed under the License is distributed on an "AS IS" * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License * for the specific language governing permissions and limitations under the License. */ package org.apache.hadoop.hbase.client.replication; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.UUID; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableNotFoundException; import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.ConnectionFactory; import org.apache.hadoop.hbase.replication.BaseReplicationEndpoint; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.TestReplicationBase; import org.apache.hadoop.hbase.testclassification.ClientTests; import org.apache.hadoop.hbase.testclassification.MediumTests; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.TestName; /** * Unit testing of ReplicationAdmin with clusters */ @Category({ MediumTests.class, ClientTests.class }) public class TestReplicationAdminWithClusters extends TestReplicationBase { static Connection connection1; static Connection connection2; static Admin admin1; static Admin admin2; static ReplicationAdmin adminExt; @Rule public TestName name = new TestName(); @BeforeClass public static void setUpBeforeClass() throws Exception { TestReplicationBase.setUpBeforeClass(); connection1 = ConnectionFactory.createConnection(conf1); connection2 = ConnectionFactory.createConnection(conf2); admin1 = connection1.getAdmin(); admin2 = connection2.getAdmin(); adminExt = new ReplicationAdmin(conf1); } @AfterClass public static void tearDownAfterClass() throws Exception { admin1.close(); admin2.close(); adminExt.close(); connection1.close(); connection2.close(); TestReplicationBase.tearDownAfterClass(); } @Test(timeout = 300000) public void disableNotFullReplication() throws Exception { HTableDescriptor table = new HTableDescriptor(admin2.getTableDescriptor(tableName)); HColumnDescriptor f = new HColumnDescriptor("notReplicatedFamily"); table.addFamily(f); admin1.disableTable(tableName); admin1.modifyTable(tableName, table); admin1.enableTable(tableName); admin1.disableTableReplication(tableName); table = admin1.getTableDescriptor(tableName); for (HColumnDescriptor fam : table.getColumnFamilies()) { assertEquals(fam.getScope(), HConstants.REPLICATION_SCOPE_LOCAL); } } @Test(timeout = 300000) public void testEnableReplicationWhenSlaveClusterDoesntHaveTable() throws Exception { admin1.disableTableReplication(tableName); admin2.disableTable(tableName); admin2.deleteTable(tableName); assertFalse(admin2.tableExists(tableName)); admin1.enableTableReplication(tableName); assertTrue(admin2.tableExists(tableName)); } @Test(timeout = 300000) public void testEnableReplicationWhenReplicationNotEnabled() throws Exception { HTableDescriptor table = admin1.getTableDescriptor(tableName); for (HColumnDescriptor fam : table.getColumnFamilies()) { fam.setScope(HConstants.REPLICATION_SCOPE_LOCAL); } admin1.disableTable(tableName); admin1.modifyTable(tableName, table); admin1.enableTable(tableName); admin2.disableTable(tableName); admin2.modifyTable(tableName, table); admin2.enableTable(tableName); admin1.enableTableReplication(tableName); table = admin1.getTableDescriptor(tableName); for (HColumnDescriptor fam : table.getColumnFamilies()) { assertEquals(fam.getScope(), HConstants.REPLICATION_SCOPE_GLOBAL); } } @Test(timeout = 300000) public void testEnableReplicationWhenTableDescriptorIsNotSameInClusters() throws Exception { HTableDescriptor table = new HTableDescriptor(admin2.getTableDescriptor(tableName)); HColumnDescriptor f = new HColumnDescriptor("newFamily"); table.addFamily(f); admin2.disableTable(tableName); admin2.modifyTable(tableName, table); admin2.enableTable(tableName); try { admin1.enableTableReplication(tableName); fail("Exception should be thrown if table descriptors in the clusters are not same."); } catch (RuntimeException ignored) { } admin1.disableTable(tableName); admin1.modifyTable(tableName, table); admin1.enableTable(tableName); admin1.enableTableReplication(tableName); table = admin1.getTableDescriptor(tableName); for (HColumnDescriptor fam : table.getColumnFamilies()) { assertEquals(fam.getScope(), HConstants.REPLICATION_SCOPE_GLOBAL); } } @Test(timeout = 300000) public void testDisableAndEnableReplication() throws Exception { admin1.disableTableReplication(tableName); HTableDescriptor table = admin1.getTableDescriptor(tableName); for (HColumnDescriptor fam : table.getColumnFamilies()) { assertEquals(fam.getScope(), HConstants.REPLICATION_SCOPE_LOCAL); } table = admin2.getTableDescriptor(tableName); for (HColumnDescriptor fam : table.getColumnFamilies()) { assertEquals(fam.getScope(), HConstants.REPLICATION_SCOPE_LOCAL); } admin1.enableTableReplication(tableName); table = admin1.getTableDescriptor(tableName); for (HColumnDescriptor fam : table.getColumnFamilies()) { assertEquals(fam.getScope(), HConstants.REPLICATION_SCOPE_GLOBAL); } } @Test(timeout = 300000, expected = TableNotFoundException.class) public void testDisableReplicationForNonExistingTable() throws Exception { admin1.disableTableReplication(TableName.valueOf(name.getMethodName())); } @Test(timeout = 300000, expected = TableNotFoundException.class) public void testEnableReplicationForNonExistingTable() throws Exception { admin1.enableTableReplication(TableName.valueOf(name.getMethodName())); } @Test(timeout = 300000, expected = IllegalArgumentException.class) public void testDisableReplicationWhenTableNameAsNull() throws Exception { admin1.disableTableReplication(null); } @Test(timeout = 300000, expected = IllegalArgumentException.class) public void testEnableReplicationWhenTableNameAsNull() throws Exception { admin1.enableTableReplication(null); } /* * Test enable table replication should create table only in user explicit specified table-cfs. * HBASE-14717 */ @Test(timeout = 300000) public void testEnableReplicationForExplicitSetTableCfs() throws Exception { final TableName tableName = TableName.valueOf(name.getMethodName()); String peerId = "2"; if (admin2.isTableAvailable(TestReplicationBase.tableName)) { admin2.disableTable(TestReplicationBase.tableName); admin2.deleteTable(TestReplicationBase.tableName); } assertFalse("Table should not exists in the peer cluster", admin2.isTableAvailable(TestReplicationBase.tableName)); Map<TableName, ? extends Collection<String>> tableCfs = new HashMap<>(); tableCfs.put(tableName, null); try { adminExt.setPeerTableCFs(peerId, tableCfs); admin1.enableTableReplication(TestReplicationBase.tableName); assertFalse("Table should not be created if user has set table cfs explicitly for the " + "peer and this is not part of that collection", admin2.isTableAvailable(TestReplicationBase.tableName)); tableCfs.put(TestReplicationBase.tableName, null); adminExt.setPeerTableCFs(peerId, tableCfs); admin1.enableTableReplication(TestReplicationBase.tableName); assertTrue( "Table should be created if user has explicitly added table into table cfs collection", admin2.isTableAvailable(TestReplicationBase.tableName)); } finally { adminExt.removePeerTableCFs(peerId, adminExt.getPeerTableCFs(peerId)); admin1.disableTableReplication(TestReplicationBase.tableName); } } @Test(timeout=300000) public void testReplicationPeerConfigUpdateCallback() throws Exception { String peerId = "1"; ReplicationPeerConfig rpc = new ReplicationPeerConfig(); rpc.setClusterKey(utility2.getClusterKey()); rpc.setReplicationEndpointImpl(TestUpdatableReplicationEndpoint.class.getName()); rpc.getConfiguration().put("key1", "value1"); admin1.addReplicationPeer(peerId, rpc); rpc.getConfiguration().put("key1", "value2"); admin.updatePeerConfig(peerId, rpc); if (!TestUpdatableReplicationEndpoint.hasCalledBack()) { synchronized(TestUpdatableReplicationEndpoint.class) { TestUpdatableReplicationEndpoint.class.wait(2000L); } } assertEquals(true, TestUpdatableReplicationEndpoint.hasCalledBack()); } public static class TestUpdatableReplicationEndpoint extends BaseReplicationEndpoint { private static boolean calledBack = false; public static boolean hasCalledBack(){ return calledBack; } @Override public synchronized void peerConfigUpdated(ReplicationPeerConfig rpc){ calledBack = true; notifyAll(); } @Override protected void doStart() { notifyStarted(); } @Override protected void doStop() { notifyStopped(); } @Override public UUID getPeerUUID() { return UUID.randomUUID(); } @Override public boolean replicate(ReplicateContext replicateContext) { return false; } } }