HBASE-21265 Split up TestRSGroups
Signed-off-by: Ted Yu <tyu@apache.org> Conflicts: hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroups.java hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.java hbase-rsgroup/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase.java
This commit is contained in:
parent
9e3f3fdc1f
commit
24d19e87e0
|
@ -40,13 +40,13 @@ import org.slf4j.LoggerFactory;
|
|||
* Test enable RSGroup
|
||||
*/
|
||||
@Category({ MediumTests.class })
|
||||
public class TestEnableRSGroup {
|
||||
public class TestEnableRSGroups {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestEnableRSGroup.class);
|
||||
HBaseClassTestRule.forClass(TestEnableRSGroups.class);
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TestEnableRSGroup.class);
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TestEnableRSGroups.class);
|
||||
|
||||
private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
|
||||
|
||||
|
@ -71,7 +71,8 @@ public class TestEnableRSGroup {
|
|||
LOG.info("stopped master...");
|
||||
final Configuration conf = TEST_UTIL.getMiniHBaseCluster().getConfiguration();
|
||||
conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, RSGroupAdminEndpoint.class.getName());
|
||||
conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, RSGroupBasedLoadBalancer.class.getName());
|
||||
conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
|
||||
RSGroupBasedLoadBalancer.class.getName());
|
||||
|
||||
TEST_UTIL.getMiniHBaseCluster().startMaster();
|
||||
TEST_UTIL.getMiniHBaseCluster().waitForActiveAndReadyMaster(60000);
|
|
@ -1,547 +0,0 @@
|
|||
/**
|
||||
* 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.rsgroup;
|
||||
|
||||
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.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.HBaseTestingUtility;
|
||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||
import org.apache.hadoop.hbase.HConstants;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.MiniHBaseCluster;
|
||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.Waiter;
|
||||
import org.apache.hadoop.hbase.Waiter.Predicate;
|
||||
import org.apache.hadoop.hbase.client.ClusterConnection;
|
||||
import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
|
||||
import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor;
|
||||
import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
|
||||
import org.apache.hadoop.hbase.coprocessor.MasterObserver;
|
||||
import org.apache.hadoop.hbase.coprocessor.ObserverContext;
|
||||
import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
|
||||
import org.apache.hadoop.hbase.master.ServerManager;
|
||||
import org.apache.hadoop.hbase.master.TableNamespaceManager;
|
||||
import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
|
||||
import org.apache.hadoop.hbase.net.Address;
|
||||
import org.apache.hadoop.hbase.quotas.QuotaTableUtil;
|
||||
import org.apache.hadoop.hbase.quotas.QuotaUtil;
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
|
||||
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;
|
||||
|
||||
@Category({MediumTests.class})
|
||||
public class TestRSGroups extends TestRSGroupsBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestRSGroups.class);
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroups.class);
|
||||
private static boolean INIT = false;
|
||||
private static RSGroupAdminEndpoint rsGroupAdminEndpoint;
|
||||
private static CPMasterObserver observer;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
TEST_UTIL = new HBaseTestingUtility();
|
||||
TEST_UTIL.getConfiguration().setFloat(
|
||||
"hbase.master.balancer.stochastic.tableSkewCost", 6000);
|
||||
TEST_UTIL.getConfiguration().set(
|
||||
HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
|
||||
RSGroupBasedLoadBalancer.class.getName());
|
||||
TEST_UTIL.getConfiguration().set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY,
|
||||
RSGroupAdminEndpoint.class.getName() + "," + CPMasterObserver.class.getName());
|
||||
TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE - 1);
|
||||
TEST_UTIL.getConfiguration().setInt(
|
||||
ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART,
|
||||
NUM_SLAVES_BASE - 1);
|
||||
TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
|
||||
initialize();
|
||||
}
|
||||
|
||||
private static void initialize() throws Exception {
|
||||
admin = TEST_UTIL.getAdmin();
|
||||
cluster = TEST_UTIL.getHBaseCluster();
|
||||
master = ((MiniHBaseCluster)cluster).getMaster();
|
||||
|
||||
//wait for balancer to come online
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return master.isInitialized() &&
|
||||
((RSGroupBasedLoadBalancer) master.getLoadBalancer()).isOnline();
|
||||
}
|
||||
});
|
||||
admin.setBalancerRunning(false,true);
|
||||
rsGroupAdmin = new VerifyingRSGroupAdminClient(
|
||||
new RSGroupAdminClient(TEST_UTIL.getConnection()), TEST_UTIL.getConfiguration());
|
||||
MasterCoprocessorHost host = master.getMasterCoprocessorHost();
|
||||
observer = (CPMasterObserver) host.findCoprocessor(CPMasterObserver.class.getName());
|
||||
rsGroupAdminEndpoint = (RSGroupAdminEndpoint)
|
||||
host.findCoprocessor(RSGroupAdminEndpoint.class.getName());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
TEST_UTIL.shutdownMiniCluster();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeMethod() throws Exception {
|
||||
if (!INIT) {
|
||||
INIT = true;
|
||||
afterMethod();
|
||||
}
|
||||
observer.resetFlags();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterMethod() throws Exception {
|
||||
deleteTableIfNecessary();
|
||||
deleteNamespaceIfNecessary();
|
||||
deleteGroups();
|
||||
|
||||
for(ServerName sn : admin.listDecommissionedRegionServers()){
|
||||
admin.recommissionRegionServer(sn, null);
|
||||
}
|
||||
assertTrue(admin.listDecommissionedRegionServers().isEmpty());
|
||||
|
||||
int missing = NUM_SLAVES_BASE - getNumServers();
|
||||
LOG.info("Restoring servers: "+missing);
|
||||
for(int i=0; i<missing; i++) {
|
||||
((MiniHBaseCluster)cluster).startRegionServer();
|
||||
}
|
||||
|
||||
rsGroupAdmin.addRSGroup("master");
|
||||
ServerName masterServerName =
|
||||
((MiniHBaseCluster)cluster).getMaster().getServerName();
|
||||
|
||||
try {
|
||||
rsGroupAdmin.moveServers(Sets.newHashSet(masterServerName.getAddress()), "master");
|
||||
} catch (Exception ex) {
|
||||
LOG.warn("Got this on setup, FYI", ex);
|
||||
}
|
||||
assertTrue(observer.preMoveServersCalled);
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
LOG.info("Waiting for cleanup to finish " + rsGroupAdmin.listRSGroups());
|
||||
//Might be greater since moving servers back to default
|
||||
//is after starting a server
|
||||
|
||||
return rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size()
|
||||
== NUM_SLAVES_BASE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicStartUp() throws IOException {
|
||||
RSGroupInfo defaultInfo = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
|
||||
assertEquals(4, defaultInfo.getServers().size());
|
||||
// Assignment of root and meta regions.
|
||||
int count = master.getAssignmentManager().getRegionStates().getRegionAssignments().size();
|
||||
//3 meta,namespace, group
|
||||
assertEquals(3, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamespaceCreateAndAssign() throws Exception {
|
||||
LOG.info("testNamespaceCreateAndAssign");
|
||||
String nsName = tablePrefix+"_foo";
|
||||
final TableName tableName = TableName.valueOf(nsName, tablePrefix + "_testCreateAndAssign");
|
||||
RSGroupInfo appInfo = addGroup("appInfo", 1);
|
||||
admin.createNamespace(NamespaceDescriptor.create(nsName)
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "appInfo").build());
|
||||
final HTableDescriptor desc = new HTableDescriptor(tableName);
|
||||
desc.addFamily(new HColumnDescriptor("f"));
|
||||
admin.createTable(desc);
|
||||
//wait for created table to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getTableRegionMap().get(desc.getTableName()) != null;
|
||||
}
|
||||
});
|
||||
ServerName targetServer =
|
||||
ServerName.parseServerName(appInfo.getServers().iterator().next().toString());
|
||||
AdminProtos.AdminService.BlockingInterface rs =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
//verify it was assigned to the right group
|
||||
Assert.assertEquals(1, ProtobufUtil.getOnlineRegions(rs).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultNamespaceCreateAndAssign() throws Exception {
|
||||
LOG.info("testDefaultNamespaceCreateAndAssign");
|
||||
String tableName = tablePrefix + "_testCreateAndAssign";
|
||||
admin.modifyNamespace(NamespaceDescriptor.create("default")
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "default").build());
|
||||
final HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
|
||||
desc.addFamily(new HColumnDescriptor("f"));
|
||||
admin.createTable(desc);
|
||||
//wait for created table to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getTableRegionMap().get(desc.getTableName()) != null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamespaceConstraint() throws Exception {
|
||||
String nsName = tablePrefix+"_foo";
|
||||
String groupName = tablePrefix+"_foo";
|
||||
LOG.info("testNamespaceConstraint");
|
||||
rsGroupAdmin.addRSGroup(groupName);
|
||||
assertTrue(observer.preAddRSGroupCalled);
|
||||
assertTrue(observer.postAddRSGroupCalled);
|
||||
|
||||
admin.createNamespace(NamespaceDescriptor.create(nsName)
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName)
|
||||
.build());
|
||||
//test removing a referenced group
|
||||
try {
|
||||
rsGroupAdmin.removeRSGroup(groupName);
|
||||
fail("Expected a constraint exception");
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
//test modify group
|
||||
//changing with the same name is fine
|
||||
admin.modifyNamespace(
|
||||
NamespaceDescriptor.create(nsName)
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName)
|
||||
.build());
|
||||
String anotherGroup = tablePrefix+"_anotherGroup";
|
||||
rsGroupAdmin.addRSGroup(anotherGroup);
|
||||
//test add non-existent group
|
||||
admin.deleteNamespace(nsName);
|
||||
rsGroupAdmin.removeRSGroup(groupName);
|
||||
assertTrue(observer.preRemoveRSGroupCalled);
|
||||
assertTrue(observer.postRemoveRSGroupCalled);
|
||||
try {
|
||||
admin.createNamespace(NamespaceDescriptor.create(nsName)
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "foo")
|
||||
.build());
|
||||
fail("Expected a constraint exception");
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupInfoMultiAccessing() throws Exception {
|
||||
RSGroupInfoManager manager = rsGroupAdminEndpoint.getGroupInfoManager();
|
||||
RSGroupInfo defaultGroup = manager.getRSGroup("default");
|
||||
// getRSGroup updates default group's server list
|
||||
// this process must not affect other threads iterating the list
|
||||
Iterator<Address> it = defaultGroup.getServers().iterator();
|
||||
manager.getRSGroup("default");
|
||||
it.next();
|
||||
}
|
||||
|
||||
public static class CPMasterObserver implements MasterCoprocessor, MasterObserver {
|
||||
boolean preBalanceRSGroupCalled = false;
|
||||
boolean postBalanceRSGroupCalled = false;
|
||||
boolean preMoveServersCalled = false;
|
||||
boolean postMoveServersCalled = false;
|
||||
boolean preMoveTablesCalled = false;
|
||||
boolean postMoveTablesCalled = false;
|
||||
boolean preAddRSGroupCalled = false;
|
||||
boolean postAddRSGroupCalled = false;
|
||||
boolean preRemoveRSGroupCalled = false;
|
||||
boolean postRemoveRSGroupCalled = false;
|
||||
boolean preRemoveServersCalled = false;
|
||||
boolean postRemoveServersCalled = false;
|
||||
boolean preMoveServersAndTables = false;
|
||||
boolean postMoveServersAndTables = false;
|
||||
|
||||
void resetFlags() {
|
||||
preBalanceRSGroupCalled = false;
|
||||
postBalanceRSGroupCalled = false;
|
||||
preMoveServersCalled = false;
|
||||
postMoveServersCalled = false;
|
||||
preMoveTablesCalled = false;
|
||||
postMoveTablesCalled = false;
|
||||
preAddRSGroupCalled = false;
|
||||
postAddRSGroupCalled = false;
|
||||
preRemoveRSGroupCalled = false;
|
||||
postRemoveRSGroupCalled = false;
|
||||
preRemoveServersCalled = false;
|
||||
postRemoveServersCalled = false;
|
||||
preMoveServersAndTables = false;
|
||||
postMoveServersAndTables = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<MasterObserver> getMasterObserver() {
|
||||
return Optional.of(this);
|
||||
}
|
||||
@Override
|
||||
public void preMoveServersAndTables(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
|
||||
preMoveServersAndTables = true;
|
||||
}
|
||||
@Override
|
||||
public void postMoveServersAndTables(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
Set<Address> servers, Set<TableName> tables, String targetGroup) throws IOException {
|
||||
postMoveServersAndTables = true;
|
||||
}
|
||||
@Override
|
||||
public void preRemoveServers(
|
||||
final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
Set<Address> servers) throws IOException {
|
||||
preRemoveServersCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void postRemoveServers(
|
||||
final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
Set<Address> servers) throws IOException {
|
||||
postRemoveServersCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void preRemoveRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String name) throws IOException {
|
||||
preRemoveRSGroupCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void postRemoveRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String name) throws IOException {
|
||||
postRemoveRSGroupCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void preAddRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String name) throws IOException {
|
||||
preAddRSGroupCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void postAddRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String name) throws IOException {
|
||||
postAddRSGroupCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void preMoveTables(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
Set<TableName> tables, String targetGroup) throws IOException {
|
||||
preMoveTablesCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void postMoveTables(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
Set<TableName> tables, String targetGroup) throws IOException {
|
||||
postMoveTablesCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void preMoveServers(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
Set<Address> servers, String targetGroup) throws IOException {
|
||||
preMoveServersCalled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postMoveServers(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
Set<Address> servers, String targetGroup) throws IOException {
|
||||
postMoveServersCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void preBalanceRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String groupName) throws IOException {
|
||||
preBalanceRSGroupCalled = true;
|
||||
}
|
||||
@Override
|
||||
public void postBalanceRSGroup(final ObserverContext<MasterCoprocessorEnvironment> ctx,
|
||||
String groupName, boolean balancerRan) throws IOException {
|
||||
postBalanceRSGroupCalled = true;
|
||||
}
|
||||
}
|
||||
@Test
|
||||
public void testMoveServersAndTables() throws Exception {
|
||||
super.testMoveServersAndTables();
|
||||
assertTrue(observer.preMoveServersAndTables);
|
||||
assertTrue(observer.postMoveServersAndTables);
|
||||
}
|
||||
@Test
|
||||
public void testTableMoveTruncateAndDrop() throws Exception {
|
||||
super.testTableMoveTruncateAndDrop();
|
||||
assertTrue(observer.preMoveTablesCalled);
|
||||
assertTrue(observer.postMoveTablesCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveServers() throws Exception {
|
||||
super.testRemoveServers();
|
||||
assertTrue(observer.preRemoveServersCalled);
|
||||
assertTrue(observer.postRemoveServersCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMisplacedRegions() throws Exception {
|
||||
final TableName tableName = TableName.valueOf(tablePrefix+"_testMisplacedRegions");
|
||||
LOG.info("testMisplacedRegions");
|
||||
|
||||
final RSGroupInfo RSGroupInfo = addGroup("testMisplacedRegions", 1);
|
||||
|
||||
TEST_UTIL.createMultiRegionTable(tableName, new byte[]{'f'}, 15);
|
||||
TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
|
||||
|
||||
rsGroupAdminEndpoint.getGroupInfoManager()
|
||||
.moveTables(Sets.newHashSet(tableName), RSGroupInfo.getName());
|
||||
|
||||
admin.setBalancerRunning(true,true);
|
||||
assertTrue(rsGroupAdmin.balanceRSGroup(RSGroupInfo.getName()));
|
||||
admin.setBalancerRunning(false,true);
|
||||
assertTrue(observer.preBalanceRSGroupCalled);
|
||||
assertTrue(observer.postBalanceRSGroupCalled);
|
||||
|
||||
TEST_UTIL.waitFor(60000, new Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
ServerName serverName =
|
||||
ServerName.valueOf(RSGroupInfo.getServers().iterator().next().toString(), 1);
|
||||
return admin.getConnection().getAdmin()
|
||||
.getOnlineRegions(serverName).size() == 15;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloneSnapshot() throws Exception {
|
||||
byte[] FAMILY = Bytes.toBytes("test");
|
||||
String snapshotName = tableName.getNameAsString() + "_snap";
|
||||
TableName clonedTableName = TableName.valueOf(tableName.getNameAsString() + "_clone");
|
||||
|
||||
// create base table
|
||||
TEST_UTIL.createTable(tableName, FAMILY);
|
||||
|
||||
// create snapshot
|
||||
admin.snapshot(snapshotName, tableName);
|
||||
|
||||
// clone
|
||||
admin.cloneSnapshot(snapshotName, clonedTableName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRSGroupsWithHBaseQuota() throws Exception {
|
||||
TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
|
||||
restartHBaseCluster();
|
||||
try {
|
||||
TEST_UTIL.waitFor(90000, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return admin.isTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, false);
|
||||
restartHBaseCluster();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRSGroupListDoesNotContainFailedTableCreation() throws Exception {
|
||||
toggleQuotaCheckAndRestartMiniCluster(true);
|
||||
String nsp = "np1";
|
||||
NamespaceDescriptor nspDesc =
|
||||
NamespaceDescriptor.create(nsp).addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "5")
|
||||
.addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "2").build();
|
||||
admin.createNamespace(nspDesc);
|
||||
assertEquals(3, admin.listNamespaceDescriptors().length);
|
||||
HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
|
||||
HTableDescriptor tableDescOne =
|
||||
new HTableDescriptor(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table1"));
|
||||
tableDescOne.addFamily(fam1);
|
||||
admin.createTable(tableDescOne);
|
||||
|
||||
HTableDescriptor tableDescTwo =
|
||||
new HTableDescriptor(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table2"));
|
||||
tableDescTwo.addFamily(fam1);
|
||||
boolean constraintViolated = false;
|
||||
|
||||
try {
|
||||
admin.createTable(tableDescTwo, Bytes.toBytes("AAA"), Bytes.toBytes("ZZZ"),
|
||||
6);
|
||||
Assert.fail("Creation table should fail because of quota violation.");
|
||||
} catch (Exception exp) {
|
||||
assertTrue(exp instanceof IOException);
|
||||
constraintViolated = true;
|
||||
} finally {
|
||||
assertTrue("Constraint not violated for table " + tableDescTwo.getTableName(),
|
||||
constraintViolated);
|
||||
}
|
||||
List<RSGroupInfo> rsGroupInfoList = rsGroupAdmin.listRSGroups();
|
||||
boolean foundTable2 = false;
|
||||
boolean foundTable1 = false;
|
||||
for(int i = 0; i < rsGroupInfoList.size(); i++){
|
||||
if(rsGroupInfoList.get(i).getTables().contains(tableDescTwo.getTableName())){
|
||||
foundTable2 = true;
|
||||
}
|
||||
if(rsGroupInfoList.get(i).getTables().contains(tableDescOne.getTableName())){
|
||||
foundTable1 = true;
|
||||
}
|
||||
}
|
||||
assertFalse("Found table2 in rsgroup list.", foundTable2);
|
||||
assertTrue("Did not find table1 in rsgroup list", foundTable1);
|
||||
|
||||
TEST_UTIL.deleteTable(tableDescOne.getTableName());
|
||||
admin.deleteNamespace(nspDesc.getName());
|
||||
toggleQuotaCheckAndRestartMiniCluster(false);
|
||||
|
||||
}
|
||||
private void toggleQuotaCheckAndRestartMiniCluster(boolean enable) throws Exception{
|
||||
TEST_UTIL.shutdownMiniCluster();
|
||||
TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, enable);
|
||||
TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE - 1);
|
||||
TEST_UTIL.getConfiguration().setInt(
|
||||
ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART,
|
||||
NUM_SLAVES_BASE - 1);
|
||||
TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
|
||||
initialize();
|
||||
}
|
||||
|
||||
private void restartHBaseCluster() throws Exception {
|
||||
LOG.info("\n\nShutting down cluster");
|
||||
TEST_UTIL.shutdownMiniHBaseCluster();
|
||||
LOG.info("\n\nSleeping a bit");
|
||||
Thread.sleep(2000);
|
||||
TEST_UTIL.restartHBaseCluster(NUM_SLAVES_BASE - 1);
|
||||
initialize();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,441 @@
|
|||
/**
|
||||
* 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.rsgroup;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.TableNotFoundException;
|
||||
import org.apache.hadoop.hbase.Waiter;
|
||||
import org.apache.hadoop.hbase.constraint.ConstraintException;
|
||||
import org.apache.hadoop.hbase.master.ServerManager;
|
||||
import org.apache.hadoop.hbase.master.TableNamespaceManager;
|
||||
import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
|
||||
import org.apache.hadoop.hbase.net.Address;
|
||||
import org.apache.hadoop.hbase.quotas.QuotaUtil;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
|
||||
|
||||
@Category({MediumTests.class})
|
||||
public class TestRSGroupsAdmin1 extends TestRSGroupsBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestRSGroupsAdmin1.class);
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsAdmin1.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
setUpTestBeforeClass();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
tearDownAfterClass();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeMethod() throws Exception {
|
||||
setUpBeforeMethod();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterMethod() throws Exception {
|
||||
tearDownAfterMethod();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidGroupNames() throws IOException {
|
||||
String[] badNames = {"foo*","foo@","-"};
|
||||
String[] goodNames = {"foo_123"};
|
||||
|
||||
for(String entry: badNames) {
|
||||
try {
|
||||
rsGroupAdmin.addRSGroup(entry);
|
||||
fail("Expected a constraint exception for: "+entry);
|
||||
} catch(ConstraintException ex) {
|
||||
//expected
|
||||
}
|
||||
}
|
||||
|
||||
for(String entry: goodNames) {
|
||||
rsGroupAdmin.addRSGroup(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBogusArgs() throws Exception {
|
||||
assertNull(rsGroupAdmin.getRSGroupInfoOfTable(TableName.valueOf("nonexistent")));
|
||||
assertNull(rsGroupAdmin.getRSGroupOfServer(Address.fromParts("bogus",123)));
|
||||
assertNull(rsGroupAdmin.getRSGroupInfo("bogus"));
|
||||
|
||||
try {
|
||||
rsGroupAdmin.removeRSGroup("bogus");
|
||||
fail("Expected removing bogus group to fail");
|
||||
} catch(ConstraintException ex) {
|
||||
//expected
|
||||
}
|
||||
|
||||
try {
|
||||
rsGroupAdmin.moveTables(Sets.newHashSet(TableName.valueOf("bogustable")), "bogus");
|
||||
fail("Expected move with bogus group to fail");
|
||||
} catch(ConstraintException|TableNotFoundException ex) {
|
||||
//expected
|
||||
}
|
||||
|
||||
try {
|
||||
rsGroupAdmin.moveServers(Sets.newHashSet(Address.fromParts("bogus",123)), "bogus");
|
||||
fail("Expected move with bogus group to fail");
|
||||
} catch(ConstraintException ex) {
|
||||
//expected
|
||||
}
|
||||
|
||||
try {
|
||||
admin.setBalancerRunning(true,true);
|
||||
rsGroupAdmin.balanceRSGroup("bogus");
|
||||
admin.setBalancerRunning(false,true);
|
||||
fail("Expected move with bogus group to fail");
|
||||
} catch(ConstraintException ex) {
|
||||
//expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamespaceConstraint() throws Exception {
|
||||
String nsName = tablePrefix+"_foo";
|
||||
String groupName = tablePrefix+"_foo";
|
||||
LOG.info("testNamespaceConstraint");
|
||||
rsGroupAdmin.addRSGroup(groupName);
|
||||
assertTrue(observer.preAddRSGroupCalled);
|
||||
assertTrue(observer.postAddRSGroupCalled);
|
||||
|
||||
admin.createNamespace(NamespaceDescriptor.create(nsName)
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName)
|
||||
.build());
|
||||
//test removing a referenced group
|
||||
try {
|
||||
rsGroupAdmin.removeRSGroup(groupName);
|
||||
fail("Expected a constraint exception");
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
//test modify group
|
||||
//changing with the same name is fine
|
||||
admin.modifyNamespace(
|
||||
NamespaceDescriptor.create(nsName)
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName)
|
||||
.build());
|
||||
String anotherGroup = tablePrefix+"_anotherGroup";
|
||||
rsGroupAdmin.addRSGroup(anotherGroup);
|
||||
//test add non-existent group
|
||||
admin.deleteNamespace(nsName);
|
||||
rsGroupAdmin.removeRSGroup(groupName);
|
||||
assertTrue(observer.preRemoveRSGroupCalled);
|
||||
assertTrue(observer.postRemoveRSGroupCalled);
|
||||
try {
|
||||
admin.createNamespace(NamespaceDescriptor.create(nsName)
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "foo")
|
||||
.build());
|
||||
fail("Expected a constraint exception");
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupInfoMultiAccessing() throws Exception {
|
||||
RSGroupInfoManager manager = rsGroupAdminEndpoint.getGroupInfoManager();
|
||||
RSGroupInfo defaultGroup = manager.getRSGroup("default");
|
||||
// getRSGroup updates default group's server list
|
||||
// this process must not affect other threads iterating the list
|
||||
Iterator<Address> it = defaultGroup.getServers().iterator();
|
||||
manager.getRSGroup("default");
|
||||
it.next();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFailRemoveGroup() throws IOException, InterruptedException {
|
||||
int initNumGroups = rsGroupAdmin.listRSGroups().size();
|
||||
addGroup("bar", 3);
|
||||
TEST_UTIL.createTable(tableName, Bytes.toBytes("f"));
|
||||
rsGroupAdmin.moveTables(Sets.newHashSet(tableName), "bar");
|
||||
RSGroupInfo barGroup = rsGroupAdmin.getRSGroupInfo("bar");
|
||||
//group is not empty therefore it should fail
|
||||
try {
|
||||
rsGroupAdmin.removeRSGroup(barGroup.getName());
|
||||
fail("Expected remove group to fail");
|
||||
} catch(IOException e) {
|
||||
}
|
||||
//group cannot lose all it's servers therefore it should fail
|
||||
try {
|
||||
rsGroupAdmin.moveServers(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
|
||||
fail("Expected move servers to fail");
|
||||
} catch(IOException e) {
|
||||
}
|
||||
|
||||
rsGroupAdmin.moveTables(barGroup.getTables(), RSGroupInfo.DEFAULT_GROUP);
|
||||
try {
|
||||
rsGroupAdmin.removeRSGroup(barGroup.getName());
|
||||
fail("Expected move servers to fail");
|
||||
} catch(IOException e) {
|
||||
}
|
||||
|
||||
rsGroupAdmin.moveServers(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
|
||||
rsGroupAdmin.removeRSGroup(barGroup.getName());
|
||||
|
||||
Assert.assertEquals(initNumGroups, rsGroupAdmin.listRSGroups().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiTableMove() throws Exception {
|
||||
final TableName tableNameA = TableName.valueOf(tablePrefix + name.getMethodName() + "A");
|
||||
final TableName tableNameB = TableName.valueOf(tablePrefix + name.getMethodName() + "B");
|
||||
final byte[] familyNameBytes = Bytes.toBytes("f");
|
||||
String newGroupName = getGroupName(name.getMethodName());
|
||||
final RSGroupInfo newGroup = addGroup(newGroupName, 1);
|
||||
|
||||
TEST_UTIL.createTable(tableNameA, familyNameBytes);
|
||||
TEST_UTIL.createTable(tableNameB, familyNameBytes);
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
List<String> regionsA = getTableRegionMap().get(tableNameA);
|
||||
if (regionsA == null) {
|
||||
return false;
|
||||
}
|
||||
List<String> regionsB = getTableRegionMap().get(tableNameB);
|
||||
if (regionsB == null) {
|
||||
return false;
|
||||
}
|
||||
return getTableRegionMap().get(tableNameA).size() >= 1
|
||||
&& getTableRegionMap().get(tableNameB).size() >= 1;
|
||||
}
|
||||
});
|
||||
|
||||
RSGroupInfo tableGrpA = rsGroupAdmin.getRSGroupInfoOfTable(tableNameA);
|
||||
assertTrue(tableGrpA.getName().equals(RSGroupInfo.DEFAULT_GROUP));
|
||||
|
||||
RSGroupInfo tableGrpB = rsGroupAdmin.getRSGroupInfoOfTable(tableNameB);
|
||||
assertTrue(tableGrpB.getName().equals(RSGroupInfo.DEFAULT_GROUP));
|
||||
//change table's group
|
||||
LOG.info("Moving table [" + tableNameA + "," + tableNameB + "] to " + newGroup.getName());
|
||||
rsGroupAdmin.moveTables(Sets.newHashSet(tableNameA, tableNameB), newGroup.getName());
|
||||
|
||||
//verify group change
|
||||
Assert.assertEquals(newGroup.getName(),
|
||||
rsGroupAdmin.getRSGroupInfoOfTable(tableNameA).getName());
|
||||
|
||||
Assert.assertEquals(newGroup.getName(),
|
||||
rsGroupAdmin.getRSGroupInfoOfTable(tableNameB).getName());
|
||||
|
||||
//verify tables' not exist in old group
|
||||
Set<TableName> DefaultTables =
|
||||
rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables();
|
||||
assertFalse(DefaultTables.contains(tableNameA));
|
||||
assertFalse(DefaultTables.contains(tableNameB));
|
||||
|
||||
//verify tables' exist in new group
|
||||
Set<TableName> newGroupTables = rsGroupAdmin.getRSGroupInfo(newGroupName).getTables();
|
||||
assertTrue(newGroupTables.contains(tableNameA));
|
||||
assertTrue(newGroupTables.contains(tableNameB));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTableMoveTruncateAndDrop() throws Exception {
|
||||
final byte[] familyNameBytes = Bytes.toBytes("f");
|
||||
String newGroupName = getGroupName(name.getMethodName());
|
||||
final RSGroupInfo newGroup = addGroup(newGroupName, 2);
|
||||
|
||||
TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
List<String> regions = getTableRegionMap().get(tableName);
|
||||
if (regions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getTableRegionMap().get(tableName).size() >= 5;
|
||||
}
|
||||
});
|
||||
|
||||
RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
|
||||
assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
|
||||
|
||||
//change table's group
|
||||
LOG.info("Moving table "+tableName+" to "+newGroup.getName());
|
||||
rsGroupAdmin.moveTables(Sets.newHashSet(tableName), newGroup.getName());
|
||||
|
||||
//verify group change
|
||||
Assert.assertEquals(newGroup.getName(),
|
||||
rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
|
||||
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
Map<ServerName, List<String>> serverMap = getTableServerRegionMap().get(tableName);
|
||||
int count = 0;
|
||||
if (serverMap != null) {
|
||||
for (ServerName rs : serverMap.keySet()) {
|
||||
if (newGroup.containsServer(rs.getAddress())) {
|
||||
count += serverMap.get(rs).size();
|
||||
}
|
||||
}
|
||||
}
|
||||
return count == 5;
|
||||
}
|
||||
});
|
||||
|
||||
//test truncate
|
||||
admin.disableTable(tableName);
|
||||
admin.truncateTable(tableName, true);
|
||||
Assert.assertEquals(1, rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
|
||||
Assert.assertEquals(tableName, rsGroupAdmin.getRSGroupInfo(
|
||||
newGroup.getName()).getTables().first());
|
||||
|
||||
//verify removed table is removed from group
|
||||
TEST_UTIL.deleteTable(tableName);
|
||||
Assert.assertEquals(0, rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
|
||||
|
||||
assertTrue(observer.preMoveTablesCalled);
|
||||
assertTrue(observer.postMoveTablesCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDisabledTableMove() throws Exception {
|
||||
final byte[] familyNameBytes = Bytes.toBytes("f");
|
||||
String newGroupName = getGroupName(name.getMethodName());
|
||||
final RSGroupInfo newGroup = addGroup(newGroupName, 2);
|
||||
|
||||
TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
List<String> regions = getTableRegionMap().get(tableName);
|
||||
if (regions == null) {
|
||||
return false;
|
||||
}
|
||||
return getTableRegionMap().get(tableName).size() >= 5;
|
||||
}
|
||||
});
|
||||
|
||||
RSGroupInfo tableGrp = rsGroupAdmin.getRSGroupInfoOfTable(tableName);
|
||||
assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));
|
||||
|
||||
//test disable table
|
||||
admin.disableTable(tableName);
|
||||
|
||||
//change table's group
|
||||
LOG.info("Moving table "+ tableName + " to " + newGroup.getName());
|
||||
rsGroupAdmin.moveTables(Sets.newHashSet(tableName), newGroup.getName());
|
||||
|
||||
//verify group change
|
||||
Assert.assertEquals(newGroup.getName(),
|
||||
rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRSGroupListDoesNotContainFailedTableCreation() throws Exception {
|
||||
toggleQuotaCheckAndRestartMiniCluster(true);
|
||||
String nsp = "np1";
|
||||
NamespaceDescriptor nspDesc =
|
||||
NamespaceDescriptor.create(nsp)
|
||||
.addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "5")
|
||||
.addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "2").build();
|
||||
admin.createNamespace(nspDesc);
|
||||
assertEquals(3, admin.listNamespaceDescriptors().length);
|
||||
HColumnDescriptor fam1 = new HColumnDescriptor("fam1");
|
||||
HTableDescriptor tableDescOne =
|
||||
new HTableDescriptor(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table1"));
|
||||
tableDescOne.addFamily(fam1);
|
||||
admin.createTable(tableDescOne);
|
||||
|
||||
HTableDescriptor tableDescTwo =
|
||||
new HTableDescriptor(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table2"));
|
||||
tableDescTwo.addFamily(fam1);
|
||||
boolean constraintViolated = false;
|
||||
|
||||
try {
|
||||
admin.createTable(tableDescTwo, Bytes.toBytes("AAA"), Bytes.toBytes("ZZZ"),
|
||||
6);
|
||||
Assert.fail("Creation table should fail because of quota violation.");
|
||||
} catch (Exception exp) {
|
||||
assertTrue(exp instanceof IOException);
|
||||
constraintViolated = true;
|
||||
} finally {
|
||||
assertTrue("Constraint not violated for table " + tableDescTwo.getTableName(),
|
||||
constraintViolated);
|
||||
}
|
||||
List<RSGroupInfo> rsGroupInfoList = rsGroupAdmin.listRSGroups();
|
||||
boolean foundTable2 = false;
|
||||
boolean foundTable1 = false;
|
||||
for(int i = 0; i < rsGroupInfoList.size(); i++){
|
||||
if(rsGroupInfoList.get(i).getTables().contains(tableDescTwo.getTableName())){
|
||||
foundTable2 = true;
|
||||
}
|
||||
if(rsGroupInfoList.get(i).getTables().contains(tableDescOne.getTableName())){
|
||||
foundTable1 = true;
|
||||
}
|
||||
}
|
||||
assertFalse("Found table2 in rsgroup list.", foundTable2);
|
||||
assertTrue("Did not find table1 in rsgroup list", foundTable1);
|
||||
|
||||
TEST_UTIL.deleteTable(tableDescOne.getTableName());
|
||||
admin.deleteNamespace(nspDesc.getName());
|
||||
toggleQuotaCheckAndRestartMiniCluster(false);
|
||||
|
||||
}
|
||||
|
||||
private void toggleQuotaCheckAndRestartMiniCluster(boolean enable) throws Exception{
|
||||
TEST_UTIL.shutdownMiniCluster();
|
||||
TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, enable);
|
||||
TEST_UTIL.startMiniCluster(NUM_SLAVES_BASE - 1);
|
||||
TEST_UTIL.getConfiguration().setInt(
|
||||
ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART,
|
||||
NUM_SLAVES_BASE - 1);
|
||||
TEST_UTIL.getConfiguration().setBoolean(SnapshotManager.HBASE_SNAPSHOT_ENABLED, true);
|
||||
initialize();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,487 @@
|
|||
/**
|
||||
* 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.rsgroup;
|
||||
|
||||
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.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.hadoop.hbase.ClusterMetrics.Option;
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.Waiter;
|
||||
import org.apache.hadoop.hbase.client.ClusterConnection;
|
||||
import org.apache.hadoop.hbase.client.RegionInfo;
|
||||
import org.apache.hadoop.hbase.constraint.ConstraintException;
|
||||
import org.apache.hadoop.hbase.net.Address;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetServerInfoRequest;
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
|
||||
|
||||
@Category({MediumTests.class})
|
||||
public class TestRSGroupsAdmin2 extends TestRSGroupsBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestRSGroupsAdmin2.class);
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsAdmin2.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
setUpTestBeforeClass();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
tearDownAfterClass();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeMethod() throws Exception {
|
||||
setUpBeforeMethod();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterMethod() throws Exception {
|
||||
tearDownAfterMethod();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegionMove() throws Exception {
|
||||
final RSGroupInfo newGroup = addGroup(getGroupName(name.getMethodName()), 1);
|
||||
final byte[] familyNameBytes = Bytes.toBytes("f");
|
||||
// All the regions created below will be assigned to the default group.
|
||||
TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 6);
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
List<String> regions = getTableRegionMap().get(tableName);
|
||||
if (regions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getTableRegionMap().get(tableName).size() >= 6;
|
||||
}
|
||||
});
|
||||
|
||||
//get target region to move
|
||||
Map<ServerName,List<String>> assignMap =
|
||||
getTableServerRegionMap().get(tableName);
|
||||
String targetRegion = null;
|
||||
for(ServerName server : assignMap.keySet()) {
|
||||
targetRegion = assignMap.get(server).size() > 0 ? assignMap.get(server).get(0) : null;
|
||||
if(targetRegion != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//get server which is not a member of new group
|
||||
ServerName targetServer = null;
|
||||
for (ServerName server : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS))
|
||||
.getLiveServerMetrics().keySet()) {
|
||||
if (!newGroup.containsServer(server.getAddress())) {
|
||||
targetServer = server;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final AdminProtos.AdminService.BlockingInterface targetRS =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
|
||||
//move target server to group
|
||||
rsGroupAdmin.moveServers(Sets.newHashSet(targetServer.getAddress()),
|
||||
newGroup.getName());
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return ProtobufUtil.getOnlineRegions(targetRS).size() <= 0;
|
||||
}
|
||||
});
|
||||
|
||||
// Lets move this region to the new group.
|
||||
TEST_UTIL.getAdmin().move(Bytes.toBytes(RegionInfo.encodeRegionName(
|
||||
Bytes.toBytes(targetRegion))), Bytes.toBytes(targetServer.getServerName()));
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return
|
||||
getTableRegionMap().get(tableName) != null &&
|
||||
getTableRegionMap().get(tableName).size() == 6 &&
|
||||
admin.getClusterMetrics(EnumSet.of(Option.REGIONS_IN_TRANSITION))
|
||||
.getRegionStatesInTransition().size() < 1;
|
||||
}
|
||||
});
|
||||
|
||||
//verify that targetServer didn't open it
|
||||
for (RegionInfo region: ProtobufUtil.getOnlineRegions(targetRS)) {
|
||||
if (targetRegion.equals(region.getRegionNameAsString())) {
|
||||
fail("Target server opened region");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegionServerMove() throws IOException,
|
||||
InterruptedException {
|
||||
int initNumGroups = rsGroupAdmin.listRSGroups().size();
|
||||
RSGroupInfo appInfo = addGroup(getGroupName(name.getMethodName()), 1);
|
||||
RSGroupInfo adminInfo = addGroup(getGroupName(name.getMethodName()), 1);
|
||||
RSGroupInfo dInfo = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
|
||||
Assert.assertEquals(initNumGroups + 2, rsGroupAdmin.listRSGroups().size());
|
||||
assertEquals(1, adminInfo.getServers().size());
|
||||
assertEquals(1, appInfo.getServers().size());
|
||||
assertEquals(getNumServers() - 2, dInfo.getServers().size());
|
||||
rsGroupAdmin.moveServers(appInfo.getServers(),
|
||||
RSGroupInfo.DEFAULT_GROUP);
|
||||
rsGroupAdmin.removeRSGroup(appInfo.getName());
|
||||
rsGroupAdmin.moveServers(adminInfo.getServers(),
|
||||
RSGroupInfo.DEFAULT_GROUP);
|
||||
rsGroupAdmin.removeRSGroup(adminInfo.getName());
|
||||
Assert.assertEquals(rsGroupAdmin.listRSGroups().size(), initNumGroups);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveServers() throws Exception {
|
||||
//create groups and assign servers
|
||||
addGroup("bar", 3);
|
||||
rsGroupAdmin.addRSGroup("foo");
|
||||
|
||||
RSGroupInfo barGroup = rsGroupAdmin.getRSGroupInfo("bar");
|
||||
RSGroupInfo fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
|
||||
assertEquals(3, barGroup.getServers().size());
|
||||
assertEquals(0, fooGroup.getServers().size());
|
||||
|
||||
//test fail bogus server move
|
||||
try {
|
||||
rsGroupAdmin.moveServers(Sets.newHashSet(Address.fromString("foo:9999")),"foo");
|
||||
fail("Bogus servers shouldn't have been successfully moved.");
|
||||
} catch(IOException ex) {
|
||||
String exp = "Source RSGroup for server foo:9999 does not exist.";
|
||||
String msg = "Expected '"+exp+"' in exception message: ";
|
||||
assertTrue(msg+" "+ex.getMessage(), ex.getMessage().contains(exp));
|
||||
}
|
||||
|
||||
//test success case
|
||||
LOG.info("moving servers "+barGroup.getServers()+" to group foo");
|
||||
rsGroupAdmin.moveServers(barGroup.getServers(), fooGroup.getName());
|
||||
|
||||
barGroup = rsGroupAdmin.getRSGroupInfo("bar");
|
||||
fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
|
||||
assertEquals(0,barGroup.getServers().size());
|
||||
assertEquals(3,fooGroup.getServers().size());
|
||||
|
||||
LOG.info("moving servers "+fooGroup.getServers()+" to group default");
|
||||
rsGroupAdmin.moveServers(fooGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
|
||||
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getNumServers() ==
|
||||
rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size();
|
||||
}
|
||||
});
|
||||
|
||||
fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
|
||||
assertEquals(0,fooGroup.getServers().size());
|
||||
|
||||
//test group removal
|
||||
LOG.info("Remove group "+barGroup.getName());
|
||||
rsGroupAdmin.removeRSGroup(barGroup.getName());
|
||||
Assert.assertEquals(null, rsGroupAdmin.getRSGroupInfo(barGroup.getName()));
|
||||
LOG.info("Remove group "+fooGroup.getName());
|
||||
rsGroupAdmin.removeRSGroup(fooGroup.getName());
|
||||
Assert.assertEquals(null, rsGroupAdmin.getRSGroupInfo(fooGroup.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveServers() throws Exception {
|
||||
LOG.info("testRemoveServers");
|
||||
final RSGroupInfo newGroup = addGroup(getGroupName(name.getMethodName()), 3);
|
||||
Iterator<Address> iterator = newGroup.getServers().iterator();
|
||||
ServerName targetServer = ServerName.parseServerName(iterator.next().toString());
|
||||
|
||||
// remove online servers
|
||||
try {
|
||||
rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
|
||||
fail("Online servers shouldn't have been successfully removed.");
|
||||
} catch(IOException ex) {
|
||||
String exp = "Server " + targetServer.getAddress()
|
||||
+ " is an online server, not allowed to remove.";
|
||||
String msg = "Expected '" + exp + "' in exception message: ";
|
||||
assertTrue(msg + " " + ex.getMessage(), ex.getMessage().contains(exp));
|
||||
}
|
||||
assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
|
||||
|
||||
// remove dead servers
|
||||
NUM_DEAD_SERVERS = cluster.getClusterMetrics().getDeadServerNames().size();
|
||||
AdminProtos.AdminService.BlockingInterface targetRS =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
try {
|
||||
targetServer = ProtobufUtil.toServerName(targetRS.getServerInfo(null,
|
||||
GetServerInfoRequest.newBuilder().build()).getServerInfo().getServerName());
|
||||
//stopping may cause an exception
|
||||
//due to the connection loss
|
||||
LOG.info("stopping server " + targetServer.getServerName());
|
||||
targetRS.stopServer(null,
|
||||
AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
|
||||
NUM_DEAD_SERVERS ++;
|
||||
} catch(Exception e) {
|
||||
}
|
||||
|
||||
//wait for stopped regionserver to dead server list
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return !master.getServerManager().areDeadServersInProgress()
|
||||
&& cluster.getClusterMetrics().getDeadServerNames().size() == NUM_DEAD_SERVERS;
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
|
||||
fail("Dead servers shouldn't have been successfully removed.");
|
||||
} catch(IOException ex) {
|
||||
String exp = "Server " + targetServer.getAddress() + " is on the dead servers list,"
|
||||
+ " Maybe it will come back again, not allowed to remove.";
|
||||
String msg = "Expected '" + exp + "' in exception message: ";
|
||||
assertTrue(msg + " " + ex.getMessage(), ex.getMessage().contains(exp));
|
||||
}
|
||||
assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
|
||||
|
||||
// remove decommissioned servers
|
||||
List<ServerName> serversToDecommission = new ArrayList<>();
|
||||
targetServer = ServerName.parseServerName(iterator.next().toString());
|
||||
targetRS = ((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
targetServer = ProtobufUtil.toServerName(targetRS.getServerInfo(null,
|
||||
GetServerInfoRequest.newBuilder().build()).getServerInfo().getServerName());
|
||||
assertTrue(master.getServerManager().getOnlineServers().containsKey(targetServer));
|
||||
serversToDecommission.add(targetServer);
|
||||
|
||||
admin.decommissionRegionServers(serversToDecommission, true);
|
||||
assertEquals(1, admin.listDecommissionedRegionServers().size());
|
||||
|
||||
assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
|
||||
rsGroupAdmin.removeServers(Sets.newHashSet(targetServer.getAddress()));
|
||||
Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
|
||||
assertFalse(newGroupServers.contains(targetServer.getAddress()));
|
||||
assertEquals(2, newGroupServers.size());
|
||||
|
||||
assertTrue(observer.preRemoveServersCalled);
|
||||
assertTrue(observer.postRemoveServersCalled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveServersAndTables() throws Exception {
|
||||
LOG.info("testMoveServersAndTables");
|
||||
final RSGroupInfo newGroup = addGroup(getGroupName(name.getMethodName()), 1);
|
||||
//create table
|
||||
final byte[] familyNameBytes = Bytes.toBytes("f");
|
||||
TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
List<String> regions = getTableRegionMap().get(tableName);
|
||||
if (regions == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getTableRegionMap().get(tableName).size() >= 5;
|
||||
}
|
||||
});
|
||||
|
||||
//get server which is not a member of new group
|
||||
ServerName targetServer = null;
|
||||
for(ServerName server : admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS))
|
||||
.getLiveServerMetrics().keySet()) {
|
||||
if(!newGroup.containsServer(server.getAddress()) &&
|
||||
!rsGroupAdmin.getRSGroupInfo("master").containsServer(server.getAddress())) {
|
||||
targetServer = server;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug("Print group info : " + rsGroupAdmin.listRSGroups());
|
||||
int oldDefaultGroupServerSize =
|
||||
rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size();
|
||||
int oldDefaultGroupTableSize =
|
||||
rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables().size();
|
||||
|
||||
//test fail bogus server move
|
||||
try {
|
||||
rsGroupAdmin.moveServersAndTables(Sets.newHashSet(Address.fromString("foo:9999")),
|
||||
Sets.newHashSet(tableName), newGroup.getName());
|
||||
fail("Bogus servers shouldn't have been successfully moved.");
|
||||
} catch(IOException ex) {
|
||||
String exp = "Source RSGroup for server foo:9999 does not exist.";
|
||||
String msg = "Expected '" + exp + "' in exception message: ";
|
||||
assertTrue(msg + " " + ex.getMessage(), ex.getMessage().contains(exp));
|
||||
}
|
||||
|
||||
//test fail server move
|
||||
try {
|
||||
rsGroupAdmin.moveServersAndTables(Sets.newHashSet(targetServer.getAddress()),
|
||||
Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);
|
||||
fail("servers shouldn't have been successfully moved.");
|
||||
} catch(IOException ex) {
|
||||
String exp = "Target RSGroup " + RSGroupInfo.DEFAULT_GROUP +
|
||||
" is same as source " + RSGroupInfo.DEFAULT_GROUP + " RSGroup.";
|
||||
String msg = "Expected '" + exp + "' in exception message: ";
|
||||
assertTrue(msg + " " + ex.getMessage(), ex.getMessage().contains(exp));
|
||||
}
|
||||
|
||||
//verify default group info
|
||||
Assert.assertEquals(oldDefaultGroupServerSize,
|
||||
rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size());
|
||||
Assert.assertEquals(oldDefaultGroupTableSize,
|
||||
rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getTables().size());
|
||||
|
||||
//verify new group info
|
||||
Assert.assertEquals(1,
|
||||
rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers().size());
|
||||
Assert.assertEquals(0,
|
||||
rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables().size());
|
||||
|
||||
//get all region to move targetServer
|
||||
List<String> regionList = getTableRegionMap().get(tableName);
|
||||
for(String region : regionList) {
|
||||
// Lets move this region to the targetServer
|
||||
TEST_UTIL.getAdmin().move(Bytes.toBytes(RegionInfo.encodeRegionName(Bytes.toBytes(region))),
|
||||
Bytes.toBytes(targetServer.getServerName()));
|
||||
}
|
||||
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getTableRegionMap().get(tableName) != null &&
|
||||
getTableRegionMap().get(tableName).size() == 5 &&
|
||||
getTableServerRegionMap().get(tableName).size() == 1 &&
|
||||
admin.getClusterMetrics(EnumSet.of(Option.REGIONS_IN_TRANSITION))
|
||||
.getRegionStatesInTransition().size() < 1;
|
||||
}
|
||||
});
|
||||
|
||||
//verify that all region move to targetServer
|
||||
Assert.assertEquals(5, getTableServerRegionMap().get(tableName).get(targetServer).size());
|
||||
|
||||
//move targetServer and table to newGroup
|
||||
LOG.info("moving server and table to newGroup");
|
||||
rsGroupAdmin.moveServersAndTables(Sets.newHashSet(targetServer.getAddress()),
|
||||
Sets.newHashSet(tableName), newGroup.getName());
|
||||
|
||||
//verify group change
|
||||
Assert.assertEquals(newGroup.getName(),
|
||||
rsGroupAdmin.getRSGroupInfoOfTable(tableName).getName());
|
||||
|
||||
//verify servers' not exist in old group
|
||||
Set<Address> defaultServers = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP)
|
||||
.getServers();
|
||||
assertFalse(defaultServers.contains(targetServer.getAddress()));
|
||||
|
||||
//verify servers' exist in new group
|
||||
Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
|
||||
assertTrue(newGroupServers.contains(targetServer.getAddress()));
|
||||
|
||||
//verify tables' not exist in old group
|
||||
Set<TableName> defaultTables = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP)
|
||||
.getTables();
|
||||
assertFalse(defaultTables.contains(tableName));
|
||||
|
||||
//verify tables' exist in new group
|
||||
Set<TableName> newGroupTables = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getTables();
|
||||
assertTrue(newGroupTables.contains(tableName));
|
||||
|
||||
//verify that all region still assgin on targetServer
|
||||
Assert.assertEquals(5, getTableServerRegionMap().get(tableName).get(targetServer).size());
|
||||
|
||||
assertTrue(observer.preMoveServersAndTables);
|
||||
assertTrue(observer.postMoveServersAndTables);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveServersFromDefaultGroup() throws Exception {
|
||||
//create groups and assign servers
|
||||
rsGroupAdmin.addRSGroup("foo");
|
||||
|
||||
RSGroupInfo fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
|
||||
assertEquals(0, fooGroup.getServers().size());
|
||||
RSGroupInfo defaultGroup = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
|
||||
|
||||
//test remove all servers from default
|
||||
try {
|
||||
rsGroupAdmin.moveServers(defaultGroup.getServers(), fooGroup.getName());
|
||||
fail(RSGroupAdminServer.KEEP_ONE_SERVER_IN_DEFAULT_ERROR_MESSAGE);
|
||||
} catch (ConstraintException ex) {
|
||||
assertTrue(ex.getMessage().contains(RSGroupAdminServer
|
||||
.KEEP_ONE_SERVER_IN_DEFAULT_ERROR_MESSAGE));
|
||||
}
|
||||
|
||||
//test success case, remove one server from default ,keep at least one server
|
||||
if (defaultGroup.getServers().size() > 1) {
|
||||
Address serverInDefaultGroup = defaultGroup.getServers().iterator().next();
|
||||
LOG.info("moving server " + serverInDefaultGroup + " from group default to group " +
|
||||
fooGroup.getName());
|
||||
rsGroupAdmin.moveServers(Sets.newHashSet(serverInDefaultGroup), fooGroup.getName());
|
||||
}
|
||||
|
||||
fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
|
||||
LOG.info("moving servers " + fooGroup.getServers() + " to group default");
|
||||
rsGroupAdmin.moveServers(fooGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);
|
||||
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getNumServers() ==
|
||||
rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().size();
|
||||
}
|
||||
});
|
||||
|
||||
fooGroup = rsGroupAdmin.getRSGroupInfo("foo");
|
||||
assertEquals(0, fooGroup.getServers().size());
|
||||
|
||||
//test group removal
|
||||
LOG.info("Remove group " + fooGroup.getName());
|
||||
rsGroupAdmin.removeRSGroup(fooGroup.getName());
|
||||
Assert.assertEquals(null, rsGroupAdmin.getRSGroupInfo(fooGroup.getName()));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/**
|
||||
* 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.rsgroup;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.Waiter;
|
||||
import org.apache.hadoop.hbase.Waiter.Predicate;
|
||||
import org.apache.hadoop.hbase.client.RegionInfo;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
|
||||
|
||||
@Category({MediumTests.class})
|
||||
public class TestRSGroupsBalance extends TestRSGroupsBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestRSGroupsBalance.class);
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsBalance.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
setUpTestBeforeClass();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
tearDownAfterClass();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeMethod() throws Exception {
|
||||
setUpBeforeMethod();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterMethod() throws Exception {
|
||||
tearDownAfterMethod();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupBalance() throws Exception {
|
||||
LOG.info(name.getMethodName());
|
||||
String newGroupName = getGroupName(name.getMethodName());
|
||||
final RSGroupInfo newGroup = addGroup(newGroupName, 3);
|
||||
|
||||
final TableName tableName = TableName.valueOf(tablePrefix+"_ns", name.getMethodName());
|
||||
admin.createNamespace(
|
||||
NamespaceDescriptor.create(tableName.getNamespaceAsString())
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, newGroupName).build());
|
||||
final byte[] familyNameBytes = Bytes.toBytes("f");
|
||||
final HTableDescriptor desc = new HTableDescriptor(tableName);
|
||||
desc.addFamily(new HColumnDescriptor("f"));
|
||||
byte [] startKey = Bytes.toBytes("aaaaa");
|
||||
byte [] endKey = Bytes.toBytes("zzzzz");
|
||||
admin.createTable(desc, startKey, endKey, 6);
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
List<String> regions = getTableRegionMap().get(tableName);
|
||||
if (regions == null) {
|
||||
return false;
|
||||
}
|
||||
return regions.size() >= 6;
|
||||
}
|
||||
});
|
||||
|
||||
//make assignment uneven, move all regions to one server
|
||||
Map<ServerName,List<String>> assignMap =
|
||||
getTableServerRegionMap().get(tableName);
|
||||
final ServerName first = assignMap.entrySet().iterator().next().getKey();
|
||||
for(RegionInfo region: admin.getTableRegions(tableName)) {
|
||||
if(!assignMap.get(first).contains(region.getRegionNameAsString())) {
|
||||
admin.move(region.getEncodedNameAsBytes(), Bytes.toBytes(first.getServerName()));
|
||||
}
|
||||
}
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
Map<ServerName, List<String>> map = getTableServerRegionMap().get(tableName);
|
||||
if (map == null) {
|
||||
return true;
|
||||
}
|
||||
List<String> regions = map.get(first);
|
||||
if (regions == null) {
|
||||
return true;
|
||||
}
|
||||
return regions.size() >= 6;
|
||||
}
|
||||
});
|
||||
|
||||
//balance the other group and make sure it doesn't affect the new group
|
||||
admin.setBalancerRunning(true,true);
|
||||
rsGroupAdmin.balanceRSGroup(RSGroupInfo.DEFAULT_GROUP);
|
||||
assertEquals(6, getTableServerRegionMap().get(tableName).get(first).size());
|
||||
|
||||
//disable balance, balancer will not be run and return false
|
||||
admin.setBalancerRunning(false,true);
|
||||
assertFalse(rsGroupAdmin.balanceRSGroup(newGroupName));
|
||||
assertEquals(6, getTableServerRegionMap().get(tableName).get(first).size());
|
||||
|
||||
//enable balance
|
||||
admin.setBalancerRunning(true,true);
|
||||
rsGroupAdmin.balanceRSGroup(newGroupName);
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
for (List<String> regions : getTableServerRegionMap().get(tableName).values()) {
|
||||
if (2 != regions.size()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
admin.setBalancerRunning(false,true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMisplacedRegions() throws Exception {
|
||||
final TableName tableName = TableName.valueOf(tablePrefix+"_testMisplacedRegions");
|
||||
LOG.info("testMisplacedRegions");
|
||||
|
||||
final RSGroupInfo RSGroupInfo = addGroup("testMisplacedRegions", 1);
|
||||
|
||||
TEST_UTIL.createMultiRegionTable(tableName, new byte[]{'f'}, 15);
|
||||
TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
|
||||
|
||||
rsGroupAdminEndpoint.getGroupInfoManager()
|
||||
.moveTables(Sets.newHashSet(tableName), RSGroupInfo.getName());
|
||||
|
||||
admin.setBalancerRunning(true,true);
|
||||
assertTrue(rsGroupAdmin.balanceRSGroup(RSGroupInfo.getName()));
|
||||
admin.setBalancerRunning(false,true);
|
||||
assertTrue(observer.preBalanceRSGroupCalled);
|
||||
assertTrue(observer.postBalanceRSGroupCalled);
|
||||
|
||||
TEST_UTIL.waitFor(60000, new Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
ServerName serverName =
|
||||
ServerName.valueOf(RSGroupInfo.getServers().iterator().next().toString(), 1);
|
||||
return admin.getConnection().getAdmin()
|
||||
.getOnlineRegions(serverName).size() == 15;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,320 @@
|
|||
/**
|
||||
* 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.rsgroup;
|
||||
|
||||
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.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.Waiter;
|
||||
import org.apache.hadoop.hbase.client.ClusterConnection;
|
||||
import org.apache.hadoop.hbase.net.Address;
|
||||
import org.apache.hadoop.hbase.quotas.QuotaTableUtil;
|
||||
import org.apache.hadoop.hbase.quotas.QuotaUtil;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetServerInfoRequest;
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
|
||||
|
||||
@Category({MediumTests.class})
|
||||
public class TestRSGroupsBasics extends TestRSGroupsBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestRSGroupsBasics.class);
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsBasics.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
setUpTestBeforeClass();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
tearDownAfterClass();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeMethod() throws Exception {
|
||||
setUpBeforeMethod();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterMethod() throws Exception {
|
||||
tearDownAfterMethod();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicStartUp() throws IOException {
|
||||
RSGroupInfo defaultInfo = rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP);
|
||||
assertEquals(4, defaultInfo.getServers().size());
|
||||
// Assignment of root and meta regions.
|
||||
int count = master.getAssignmentManager().getRegionStates().getRegionAssignments().size();
|
||||
//3 meta,namespace, group
|
||||
assertEquals(3, count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndDrop() throws Exception {
|
||||
TEST_UTIL.createTable(tableName, Bytes.toBytes("cf"));
|
||||
//wait for created table to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getTableRegionMap().get(tableName) != null;
|
||||
}
|
||||
});
|
||||
TEST_UTIL.deleteTable(tableName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMultiRegion() throws IOException {
|
||||
byte[] end = {1,3,5,7,9};
|
||||
byte[] start = {0,2,4,6,8};
|
||||
byte[][] f = {Bytes.toBytes("f")};
|
||||
TEST_UTIL.createTable(tableName, f,1,start,end,10);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamespaceCreateAndAssign() throws Exception {
|
||||
LOG.info("testNamespaceCreateAndAssign");
|
||||
String nsName = tablePrefix+"_foo";
|
||||
final TableName tableName = TableName.valueOf(nsName, tablePrefix + "_testCreateAndAssign");
|
||||
RSGroupInfo appInfo = addGroup("appInfo", 1);
|
||||
admin.createNamespace(NamespaceDescriptor.create(nsName)
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "appInfo").build());
|
||||
final HTableDescriptor desc = new HTableDescriptor(tableName);
|
||||
desc.addFamily(new HColumnDescriptor("f"));
|
||||
admin.createTable(desc);
|
||||
//wait for created table to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getTableRegionMap().get(desc.getTableName()) != null;
|
||||
}
|
||||
});
|
||||
ServerName targetServer =
|
||||
ServerName.parseServerName(appInfo.getServers().iterator().next().toString());
|
||||
AdminProtos.AdminService.BlockingInterface rs =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
//verify it was assigned to the right group
|
||||
Assert.assertEquals(1, ProtobufUtil.getOnlineRegions(rs).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateWhenRsgroupNoOnlineServers() throws Exception {
|
||||
LOG.info("testCreateWhenRsgroupNoOnlineServers");
|
||||
|
||||
// set rsgroup has no online servers and test create table
|
||||
final RSGroupInfo appInfo = addGroup("appInfo", 1);
|
||||
Iterator<Address> iterator = appInfo.getServers().iterator();
|
||||
List<ServerName> serversToDecommission = new ArrayList<>();
|
||||
ServerName targetServer = ServerName.parseServerName(iterator.next().toString());
|
||||
AdminProtos.AdminService.BlockingInterface targetRS =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
targetServer = ProtobufUtil.toServerName(
|
||||
targetRS.getServerInfo(null, GetServerInfoRequest.newBuilder().build()).getServerInfo()
|
||||
.getServerName());
|
||||
assertTrue(master.getServerManager().getOnlineServers().containsKey(targetServer));
|
||||
serversToDecommission.add(targetServer);
|
||||
admin.decommissionRegionServers(serversToDecommission, true);
|
||||
assertEquals(1, admin.listDecommissionedRegionServers().size());
|
||||
|
||||
final TableName tableName = TableName.valueOf(tablePrefix + "_ns", name.getMethodName());
|
||||
admin.createNamespace(NamespaceDescriptor.create(tableName.getNamespaceAsString())
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, appInfo.getName()).build());
|
||||
final HTableDescriptor desc = new HTableDescriptor(tableName);
|
||||
desc.addFamily(new HColumnDescriptor("f"));
|
||||
try {
|
||||
admin.createTable(desc);
|
||||
fail("Shouldn't create table successfully!");
|
||||
} catch (Exception e) {
|
||||
LOG.debug("create table error", e);
|
||||
}
|
||||
|
||||
// recommission and test create table
|
||||
admin.recommissionRegionServer(targetServer, null);
|
||||
assertEquals(0, admin.listDecommissionedRegionServers().size());
|
||||
admin.createTable(desc);
|
||||
// wait for created table to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override public boolean evaluate() throws Exception {
|
||||
return getTableRegionMap().get(desc.getTableName()) != null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultNamespaceCreateAndAssign() throws Exception {
|
||||
LOG.info("testDefaultNamespaceCreateAndAssign");
|
||||
String tableName = tablePrefix + "_testCreateAndAssign";
|
||||
admin.modifyNamespace(NamespaceDescriptor.create("default")
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "default").build());
|
||||
final HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName));
|
||||
desc.addFamily(new HColumnDescriptor("f"));
|
||||
admin.createTable(desc);
|
||||
//wait for created table to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getTableRegionMap().get(desc.getTableName()) != null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloneSnapshot() throws Exception {
|
||||
byte[] FAMILY = Bytes.toBytes("test");
|
||||
String snapshotName = tableName.getNameAsString() + "_snap";
|
||||
TableName clonedTableName = TableName.valueOf(tableName.getNameAsString() + "_clone");
|
||||
|
||||
// create base table
|
||||
TEST_UTIL.createTable(tableName, FAMILY);
|
||||
|
||||
// create snapshot
|
||||
admin.snapshot(snapshotName, tableName);
|
||||
|
||||
// clone
|
||||
admin.cloneSnapshot(snapshotName, clonedTableName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearDeadServers() throws Exception {
|
||||
LOG.info("testClearDeadServers");
|
||||
final RSGroupInfo newGroup = addGroup(getGroupName(name.getMethodName()), 3);
|
||||
NUM_DEAD_SERVERS = cluster.getClusterMetrics().getDeadServerNames().size();
|
||||
|
||||
ServerName targetServer = ServerName.parseServerName(
|
||||
newGroup.getServers().iterator().next().toString());
|
||||
AdminProtos.AdminService.BlockingInterface targetRS =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
try {
|
||||
targetServer = ProtobufUtil.toServerName(targetRS.getServerInfo(null,
|
||||
GetServerInfoRequest.newBuilder().build()).getServerInfo().getServerName());
|
||||
//stopping may cause an exception
|
||||
//due to the connection loss
|
||||
targetRS.stopServer(null,
|
||||
AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
|
||||
NUM_DEAD_SERVERS ++;
|
||||
} catch(Exception e) {
|
||||
}
|
||||
//wait for stopped regionserver to dead server list
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return !master.getServerManager().areDeadServersInProgress()
|
||||
&& cluster.getClusterMetrics().getDeadServerNames().size() == NUM_DEAD_SERVERS;
|
||||
}
|
||||
});
|
||||
assertFalse(cluster.getClusterMetrics().getLiveServerMetrics().containsKey(targetServer));
|
||||
assertTrue(cluster.getClusterMetrics().getDeadServerNames().contains(targetServer));
|
||||
assertTrue(newGroup.getServers().contains(targetServer.getAddress()));
|
||||
|
||||
//clear dead servers list
|
||||
List<ServerName> notClearedServers = admin.clearDeadServers(Lists.newArrayList(targetServer));
|
||||
assertEquals(0, notClearedServers.size());
|
||||
|
||||
Set<Address> newGroupServers = rsGroupAdmin.getRSGroupInfo(newGroup.getName()).getServers();
|
||||
assertFalse(newGroupServers.contains(targetServer.getAddress()));
|
||||
assertEquals(2, newGroupServers.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearNotProcessedDeadServer() throws Exception {
|
||||
LOG.info("testClearNotProcessedDeadServer");
|
||||
NUM_DEAD_SERVERS = cluster.getClusterMetrics().getDeadServerNames().size();
|
||||
RSGroupInfo appInfo = addGroup("deadServerGroup", 1);
|
||||
ServerName targetServer =
|
||||
ServerName.parseServerName(appInfo.getServers().iterator().next().toString());
|
||||
AdminProtos.AdminService.BlockingInterface targetRS =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
try {
|
||||
targetServer = ProtobufUtil.toServerName(targetRS.getServerInfo(null,
|
||||
AdminProtos.GetServerInfoRequest.newBuilder().build()).getServerInfo().getServerName());
|
||||
//stopping may cause an exception
|
||||
//due to the connection loss
|
||||
targetRS.stopServer(null,
|
||||
AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
|
||||
NUM_DEAD_SERVERS ++;
|
||||
} catch(Exception e) {
|
||||
}
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return cluster.getClusterMetrics().getDeadServerNames().size() == NUM_DEAD_SERVERS;
|
||||
}
|
||||
});
|
||||
List<ServerName> notClearedServers =
|
||||
admin.clearDeadServers(Lists.newArrayList(targetServer));
|
||||
assertEquals(1, notClearedServers.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRSGroupsWithHBaseQuota() throws Exception {
|
||||
TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, true);
|
||||
restartHBaseCluster();
|
||||
try {
|
||||
TEST_UTIL.waitFor(90000, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return admin.isTableAvailable(QuotaTableUtil.QUOTA_TABLE_NAME);
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
TEST_UTIL.getConfiguration().setBoolean(QuotaUtil.QUOTA_CONF_KEY, false);
|
||||
restartHBaseCluster();
|
||||
}
|
||||
}
|
||||
|
||||
private void restartHBaseCluster() throws Exception {
|
||||
LOG.info("\n\nShutting down cluster");
|
||||
TEST_UTIL.shutdownMiniHBaseCluster();
|
||||
LOG.info("\n\nSleeping a bit");
|
||||
Thread.sleep(2000);
|
||||
TEST_UTIL.restartHBaseCluster(NUM_SLAVES_BASE - 1);
|
||||
initialize();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* 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.rsgroup;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.hadoop.hbase.HBaseClassTestRule;
|
||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||
import org.apache.hadoop.hbase.NamespaceDescriptor;
|
||||
import org.apache.hadoop.hbase.ServerName;
|
||||
import org.apache.hadoop.hbase.TableName;
|
||||
import org.apache.hadoop.hbase.Waiter;
|
||||
import org.apache.hadoop.hbase.client.ClusterConnection;
|
||||
import org.apache.hadoop.hbase.client.RegionInfo;
|
||||
import org.apache.hadoop.hbase.net.Address;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.experimental.categories.Category;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
|
||||
|
||||
@Category({MediumTests.class})
|
||||
public class TestRSGroupsKillRS extends TestRSGroupsBase {
|
||||
|
||||
@ClassRule
|
||||
public static final HBaseClassTestRule CLASS_RULE =
|
||||
HBaseClassTestRule.forClass(TestRSGroupsKillRS.class);
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsKillRS.class);
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception {
|
||||
setUpTestBeforeClass();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
tearDownAfterClass();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void beforeMethod() throws Exception {
|
||||
setUpBeforeMethod();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterMethod() throws Exception {
|
||||
tearDownAfterMethod();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testKillRS() throws Exception {
|
||||
RSGroupInfo appInfo = addGroup("appInfo", 1);
|
||||
|
||||
final TableName tableName = TableName.valueOf(tablePrefix+"_ns", name.getMethodName());
|
||||
admin.createNamespace(
|
||||
NamespaceDescriptor.create(tableName.getNamespaceAsString())
|
||||
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, appInfo.getName()).build());
|
||||
final HTableDescriptor desc = new HTableDescriptor(tableName);
|
||||
desc.addFamily(new HColumnDescriptor("f"));
|
||||
admin.createTable(desc);
|
||||
//wait for created table to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return getTableRegionMap().get(desc.getTableName()) != null;
|
||||
}
|
||||
});
|
||||
|
||||
ServerName targetServer = ServerName.parseServerName(
|
||||
appInfo.getServers().iterator().next().toString());
|
||||
AdminProtos.AdminService.BlockingInterface targetRS =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
RegionInfo targetRegion = ProtobufUtil.getOnlineRegions(targetRS).get(0);
|
||||
Assert.assertEquals(1, ProtobufUtil.getOnlineRegions(targetRS).size());
|
||||
|
||||
try {
|
||||
//stopping may cause an exception
|
||||
//due to the connection loss
|
||||
targetRS.stopServer(null,
|
||||
AdminProtos.StopServerRequest.newBuilder().setReason("Die").build());
|
||||
} catch(Exception e) {
|
||||
}
|
||||
assertFalse(cluster.getClusterMetrics().getLiveServerMetrics().containsKey(targetServer));
|
||||
|
||||
//wait for created table to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return cluster.getClusterMetrics().getRegionStatesInTransition().isEmpty();
|
||||
}
|
||||
});
|
||||
Set<Address> newServers = Sets.newHashSet();
|
||||
newServers.add(
|
||||
rsGroupAdmin.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP).getServers().iterator().next());
|
||||
rsGroupAdmin.moveServers(newServers, appInfo.getName());
|
||||
|
||||
//Make sure all the table's regions get reassigned
|
||||
//disabling the table guarantees no conflicting assign/unassign (ie SSH) happens
|
||||
admin.disableTable(tableName);
|
||||
admin.enableTable(tableName);
|
||||
|
||||
//wait for region to be assigned
|
||||
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
|
||||
@Override
|
||||
public boolean evaluate() throws Exception {
|
||||
return cluster.getClusterMetrics().getRegionStatesInTransition().isEmpty();
|
||||
}
|
||||
});
|
||||
|
||||
targetServer = ServerName.parseServerName(
|
||||
newServers.iterator().next().toString());
|
||||
targetRS =
|
||||
((ClusterConnection) admin.getConnection()).getAdmin(targetServer);
|
||||
Assert.assertEquals(1, ProtobufUtil.getOnlineRegions(targetRS).size());
|
||||
Assert.assertEquals(tableName,
|
||||
ProtobufUtil.getOnlineRegions(targetRS).get(0).getTable());
|
||||
}
|
||||
|
||||
}
|
|
@ -36,6 +36,7 @@ import org.apache.hadoop.hbase.master.ServerManager;
|
|||
import org.apache.hadoop.hbase.regionserver.HRegionServer;
|
||||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.apache.hadoop.hbase.security.access.TableAuthManager;
|
|||
import org.apache.hadoop.hbase.testclassification.MediumTests;
|
||||
import org.apache.hadoop.hbase.testclassification.SecurityTests;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
|
@ -177,9 +178,10 @@ public class TestRSGroupsWithACL extends SecureTestUtil{
|
|||
try {
|
||||
assertEquals(4, AccessControlClient.getUserPermissions(systemUserConnection,
|
||||
TEST_TABLE.toString()).size());
|
||||
} catch (AssertionError e) {
|
||||
fail(e.getMessage());
|
||||
} catch (Throwable e) {
|
||||
LOG.error("error during call of AccessControlClient.getUserPermissions. ", e);
|
||||
fail("error during call of AccessControlClient.getUserPermissions.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue