Revert "HBASE-22809 Allow creating table in group when rs group contains no live servers (#464)"

This reverts commit 928ecfb443.
This commit is contained in:
Duo Zhang 2019-09-10 11:14:10 +08:00
parent 4a22c74b3c
commit 1c150e0947
3 changed files with 94 additions and 71 deletions

View File

@ -21,12 +21,11 @@ import com.google.protobuf.Service;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.hadoop.hbase.CoprocessorEnvironment; import org.apache.hadoop.hbase.CoprocessorEnvironment;
import org.apache.hadoop.hbase.HBaseIOException;
import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.ServerName;
@ -69,7 +68,7 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
groupInfoManager = RSGroupInfoManagerImpl.getInstance(master); groupInfoManager = RSGroupInfoManagerImpl.getInstance(master);
groupAdminServer = new RSGroupAdminServer(master, groupInfoManager); groupAdminServer = new RSGroupAdminServer(master, groupInfoManager);
Class<?> clazz = Class<?> clazz =
master.getConfiguration().getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, null); master.getConfiguration().getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, null);
if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) { if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) {
throw new IOException("Configured balancer does not support RegionServer groups."); throw new IOException("Configured balancer does not support RegionServer groups.");
} }
@ -109,101 +108,85 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver {
@Override @Override
public void postClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx, public void postClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
List<ServerName> servers, List<ServerName> notClearedServers) throws IOException { List<ServerName> servers, List<ServerName> notClearedServers) throws IOException {
Set<Address> clearedServer = Set<Address> clearedServer =
servers.stream().filter(server -> !notClearedServers.contains(server)) servers.stream().filter(server -> !notClearedServers.contains(server))
.map(ServerName::getAddress).collect(Collectors.toSet()); .map(ServerName::getAddress).collect(Collectors.toSet());
if (!clearedServer.isEmpty()) { if (!clearedServer.isEmpty()) {
groupAdminServer.removeServers(clearedServer); groupAdminServer.removeServers(clearedServer);
} }
} }
private RSGroupInfo checkGroupExists(Optional<String> optGroupName, Supplier<String> forWhom) private void checkGroupExists(Optional<String> optGroupName) throws IOException {
throws IOException {
if (optGroupName.isPresent()) { if (optGroupName.isPresent()) {
String groupName = optGroupName.get(); String groupName = optGroupName.get();
RSGroupInfo group = groupAdminServer.getRSGroupInfo(groupName); if (groupAdminServer.getRSGroupInfo(groupName) == null) {
if (group == null) { throw new ConstraintException("Region server group " + groupName + " does not exit");
throw new ConstraintException(
"Region server group " + groupName + " for " + forWhom.get() + " does not exit");
} }
return group;
} }
return null;
} }
private Optional<String> getNamespaceGroup(NamespaceDescriptor namespaceDesc) { private boolean rsgroupHasServersOnline(TableDescriptor desc) throws IOException {
return Optional RSGroupInfo rsGroupInfo;
.ofNullable(namespaceDesc.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP)); Optional<String> optGroupName = desc.getRegionServerGroup();
} if (optGroupName.isPresent()) {
String groupName = optGroupName.get();
// Do not allow creating new tables/namespaces which has an empty rs group, expect the default rs if (groupName.equals(RSGroupInfo.DEFAULT_GROUP)) {
// group. Notice that we do not check for online servers, as this is not stable because region // do not check for default group
// servers can die at any time. return true;
private void checkGroupNotEmpty(RSGroupInfo rsGroupInfo, Supplier<String> forWhom) }
throws ConstraintException { rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName);
if (rsGroupInfo == null || rsGroupInfo.getName().equals(RSGroupInfo.DEFAULT_GROUP)) { if (rsGroupInfo == null) {
// we do not have a rs group config or we explicitly set the rs group to default, then no need throw new ConstraintException(
// to check. "RSGroup " + groupName + " for table " + desc.getTableName() + " does not exist");
return; }
} } else {
if (rsGroupInfo.getServers().isEmpty()) { NamespaceDescriptor nd =
throw new ConstraintException( master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString());
"No servers in the rsgroup " + rsGroupInfo.getName() + " for " + forWhom.get()); String groupNameOfNs = nd.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP);
if (groupNameOfNs == null || groupNameOfNs.equals(RSGroupInfo.DEFAULT_GROUP)) {
// do not check for default group
return true;
}
rsGroupInfo = groupAdminServer.getRSGroupInfo(groupNameOfNs);
if (rsGroupInfo == null) {
throw new ConstraintException("RSGroup " + groupNameOfNs + " for table " +
desc.getTableName() + "(inherit from namespace) does not exist");
}
} }
return master.getServerManager().createDestinationServersList().stream()
.anyMatch(onlineServer -> rsGroupInfo.containsServer(onlineServer.getAddress()));
} }
@Override @Override
public void preCreateTableAction(ObserverContext<MasterCoprocessorEnvironment> ctx, public void preCreateTableAction(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableDescriptor desc, RegionInfo[] regions) throws IOException { TableDescriptor desc, RegionInfo[] regions) throws IOException {
if (desc.getTableName().isSystemTable()) { checkGroupExists(desc.getRegionServerGroup());
// do not check for system tables as we may block the bootstrap. if (!desc.getTableName().isSystemTable() && !rsgroupHasServersOnline(desc)) {
return; throw new HBaseIOException("No online servers in the rsgroup for " + desc);
} }
Supplier<String> forWhom = () -> "table " + desc.getTableName();
RSGroupInfo rsGroupInfo = checkGroupExists(desc.getRegionServerGroup(), forWhom);
if (rsGroupInfo == null) {
// we do not set rs group info on table, check if we have one on namespace
String namespace = desc.getTableName().getNamespaceAsString();
NamespaceDescriptor nd = master.getClusterSchema().getNamespace(namespace);
forWhom = () -> "table " + desc.getTableName() + "(inherit from namespace)";
rsGroupInfo = checkGroupExists(getNamespaceGroup(nd), forWhom);
}
checkGroupNotEmpty(rsGroupInfo, forWhom);
} }
@Override @Override
public TableDescriptor preModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx, public TableDescriptor preModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
TableName tableName, TableDescriptor currentDescriptor, TableDescriptor newDescriptor) TableName tableName, TableDescriptor currentDescriptor, TableDescriptor newDescriptor)
throws IOException { throws IOException {
if (!currentDescriptor.getRegionServerGroup().equals(newDescriptor.getRegionServerGroup())) { checkGroupExists(newDescriptor.getRegionServerGroup());
Supplier<String> forWhom = () -> "table " + newDescriptor.getTableName();
RSGroupInfo rsGroupInfo = checkGroupExists(newDescriptor.getRegionServerGroup(), forWhom);
checkGroupNotEmpty(rsGroupInfo, forWhom);
}
return MasterObserver.super.preModifyTable(ctx, tableName, currentDescriptor, newDescriptor); return MasterObserver.super.preModifyTable(ctx, tableName, currentDescriptor, newDescriptor);
} }
private void checkNamespaceGroup(NamespaceDescriptor nd) throws IOException {
Supplier<String> forWhom = () -> "namespace " + nd.getName();
RSGroupInfo rsGroupInfo = checkGroupExists(getNamespaceGroup(nd), forWhom);
checkGroupNotEmpty(rsGroupInfo, forWhom);
}
@Override @Override
public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
NamespaceDescriptor ns) throws IOException { NamespaceDescriptor ns) throws IOException {
checkNamespaceGroup(ns); checkGroupExists(
Optional.ofNullable(ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP)));
} }
@Override @Override
public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
NamespaceDescriptor currentNsDescriptor, NamespaceDescriptor newNsDescriptor) NamespaceDescriptor currentNsDescriptor, NamespaceDescriptor newNsDescriptor)
throws IOException { throws IOException {
if (!Objects.equals( checkGroupExists(Optional
currentNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP), .ofNullable(newNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP)));
newNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP))) {
checkNamespaceGroup(newNsDescriptor);
}
} }
} }

View File

@ -152,14 +152,12 @@ public class TestRSGroupsAdmin1 extends TestRSGroupsBase {
String nsName = tablePrefix + "_foo"; String nsName = tablePrefix + "_foo";
String groupName = tablePrefix + "_foo"; String groupName = tablePrefix + "_foo";
LOG.info("testNamespaceConstraint"); LOG.info("testNamespaceConstraint");
addGroup(groupName, 1); rsGroupAdmin.addRSGroup(groupName);
assertTrue(observer.preAddRSGroupCalled); assertTrue(observer.preAddRSGroupCalled);
assertTrue(observer.postAddRSGroupCalled); assertTrue(observer.postAddRSGroupCalled);
admin.createNamespace(NamespaceDescriptor.create(nsName) admin.createNamespace(NamespaceDescriptor.create(nsName)
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build()); .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());
RSGroupInfo rsGroupInfo = rsGroupAdmin.getRSGroupInfo(groupName);
rsGroupAdmin.moveServers(rsGroupInfo.getServers(), RSGroupInfo.DEFAULT_GROUP);
// test removing a referenced group // test removing a referenced group
try { try {
rsGroupAdmin.removeRSGroup(groupName); rsGroupAdmin.removeRSGroup(groupName);

View File

@ -20,8 +20,11 @@ package org.apache.hadoop.hbase.rsgroup;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseClassTestRule;
@ -133,6 +136,45 @@ public class TestRSGroupsBasics extends TestRSGroupsBase {
Assert.assertEquals(1, admin.getRegions(targetServer).size()); Assert.assertEquals(1, admin.getRegions(targetServer).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 = getServerName(iterator.next());
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 TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName)
.setColumnFamily(ColumnFamilyDescriptorBuilder.of("f")).build();
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 @Test
public void testDefaultNamespaceCreateAndAssign() throws Exception { public void testDefaultNamespaceCreateAndAssign() throws Exception {
LOG.info("testDefaultNamespaceCreateAndAssign"); LOG.info("testDefaultNamespaceCreateAndAssign");