Skip to content

Commit 7affedc

Browse files
committed
HBASE-22809 Allow creating table in group when rs group contains no live servers
1 parent e4b1720 commit 7affedc

3 files changed

Lines changed: 67 additions & 72 deletions

File tree

hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java

Lines changed: 64 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
import java.io.IOException;
2222
import java.util.Collections;
2323
import java.util.List;
24+
import java.util.Objects;
2425
import java.util.Optional;
2526
import java.util.Set;
2627
import java.util.stream.Collectors;
2728
import org.apache.hadoop.hbase.CoprocessorEnvironment;
28-
import org.apache.hadoop.hbase.HBaseIOException;
2929
import org.apache.hadoop.hbase.HConstants;
3030
import org.apache.hadoop.hbase.NamespaceDescriptor;
3131
import org.apache.hadoop.hbase.ServerName;
@@ -68,7 +68,7 @@ public void start(CoprocessorEnvironment env) throws IOException {
6868
groupInfoManager = RSGroupInfoManagerImpl.getInstance(master);
6969
groupAdminServer = new RSGroupAdminServer(master, groupInfoManager);
7070
Class<?> clazz =
71-
master.getConfiguration().getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, null);
71+
master.getConfiguration().getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, null);
7272
if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) {
7373
throw new IOException("Configured balancer does not support RegionServer groups.");
7474
}
@@ -108,85 +108,120 @@ RSGroupAdminServiceImpl getGroupAdminService() {
108108

109109
@Override
110110
public void postClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx,
111-
List<ServerName> servers, List<ServerName> notClearedServers) throws IOException {
111+
List<ServerName> servers, List<ServerName> notClearedServers) throws IOException {
112112
Set<Address> clearedServer =
113-
servers.stream().filter(server -> !notClearedServers.contains(server))
114-
.map(ServerName::getAddress).collect(Collectors.toSet());
113+
servers.stream().filter(server -> !notClearedServers.contains(server))
114+
.map(ServerName::getAddress).collect(Collectors.toSet());
115115
if (!clearedServer.isEmpty()) {
116116
groupAdminServer.removeServers(clearedServer);
117117
}
118118
}
119119

120-
private void checkGroupExists(Optional<String> optGroupName) throws IOException {
120+
private RSGroupInfo checkGroupExists(Optional<String> optGroupName) throws IOException {
121121
if (optGroupName.isPresent()) {
122122
String groupName = optGroupName.get();
123-
if (groupAdminServer.getRSGroupInfo(groupName) == null) {
123+
RSGroupInfo group = groupAdminServer.getRSGroupInfo(groupName);
124+
if (group == null) {
124125
throw new ConstraintException("Region server group " + groupName + " does not exit");
125126
}
127+
return group;
126128
}
129+
return null;
127130
}
128131

129-
private boolean rsgroupHasServersOnline(TableDescriptor desc) throws IOException {
132+
// Do not allow creating new tables which has an empty rs group, expect the default rs group.
133+
// Notice that we do not check for online servers, as this is not stable because region server can
134+
// die at any time.
135+
private void checkForEmptyGroup(TableDescriptor desc) throws IOException {
136+
if (desc.getTableName().isSystemTable()) {
137+
// do not check for system tables as we may block the bootstrap.
138+
return;
139+
}
130140
RSGroupInfo rsGroupInfo;
131141
Optional<String> optGroupName = desc.getRegionServerGroup();
132142
if (optGroupName.isPresent()) {
133143
String groupName = optGroupName.get();
134144
if (groupName.equals(RSGroupInfo.DEFAULT_GROUP)) {
135145
// do not check for default group
136-
return true;
146+
return;
137147
}
138148
rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName);
139149
if (rsGroupInfo == null) {
140150
throw new ConstraintException(
141-
"RSGroup " + groupName + " for table " + desc.getTableName() + " does not exist");
151+
"RSGroup " + groupName + " for table " + desc.getTableName() + " does not exist");
142152
}
143153
} else {
144154
NamespaceDescriptor nd =
145-
master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString());
155+
master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString());
146156
String groupNameOfNs = nd.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP);
147157
if (groupNameOfNs == null || groupNameOfNs.equals(RSGroupInfo.DEFAULT_GROUP)) {
148158
// do not check for default group
149-
return true;
159+
return;
150160
}
151161
rsGroupInfo = groupAdminServer.getRSGroupInfo(groupNameOfNs);
152162
if (rsGroupInfo == null) {
153163
throw new ConstraintException("RSGroup " + groupNameOfNs + " for table " +
154-
desc.getTableName() + "(inherit from namespace) does not exist");
164+
desc.getTableName() + "(inherit from namespace) does not exist");
155165
}
156166
}
157-
return master.getServerManager().createDestinationServersList().stream()
158-
.anyMatch(onlineServer -> rsGroupInfo.containsServer(onlineServer.getAddress()));
167+
if (rsGroupInfo.getServers().isEmpty()) {
168+
throw new ConstraintException(
169+
"No servers in the rsgroup " + rsGroupInfo.getName() + " for " + desc);
170+
}
159171
}
160172

161173
@Override
162174
public void preCreateTableAction(ObserverContext<MasterCoprocessorEnvironment> ctx,
163-
TableDescriptor desc, RegionInfo[] regions) throws IOException {
175+
TableDescriptor desc, RegionInfo[] regions) throws IOException {
164176
checkGroupExists(desc.getRegionServerGroup());
165-
if (!desc.getTableName().isSystemTable() && !rsgroupHasServersOnline(desc)) {
166-
throw new HBaseIOException("No online servers in the rsgroup for " + desc);
167-
}
177+
checkForEmptyGroup(desc);
168178
}
169179

170180
@Override
171181
public TableDescriptor preModifyTable(ObserverContext<MasterCoprocessorEnvironment> ctx,
172-
TableName tableName, TableDescriptor currentDescriptor, TableDescriptor newDescriptor)
173-
throws IOException {
174-
checkGroupExists(newDescriptor.getRegionServerGroup());
182+
TableName tableName, TableDescriptor currentDescriptor, TableDescriptor newDescriptor)
183+
throws IOException {
184+
if (!currentDescriptor.getRegionServerGroup().equals(newDescriptor.getRegionServerGroup())) {
185+
RSGroupInfo group = checkGroupExists(newDescriptor.getRegionServerGroup());
186+
if (group != null && group.getServers().isEmpty()) {
187+
throw new ConstraintException(
188+
"No servers in the rsgroup " + group.getName() + " for " + newDescriptor);
189+
}
190+
}
175191
return MasterObserver.super.preModifyTable(ctx, tableName, currentDescriptor, newDescriptor);
176192
}
177193

194+
private void checkNamespaceGroup(NamespaceDescriptor ns) throws IOException {
195+
String groupName = ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP);
196+
if (groupName == null || groupName.equals(RSGroupInfo.DEFAULT_GROUP)) {
197+
// do not check for default group
198+
return;
199+
}
200+
RSGroupInfo group = groupAdminServer.getRSGroupInfo(groupName);
201+
if (group == null) {
202+
throw new ConstraintException(
203+
"RSGroup " + groupName + " for namespace " + ns.getName() + " does not exist");
204+
}
205+
if (group.getServers().isEmpty()) {
206+
throw new ConstraintException(
207+
"No servers in the rsgroup " + group.getName() + " for namespace " + ns.getName());
208+
}
209+
}
210+
178211
@Override
179212
public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
180-
NamespaceDescriptor ns) throws IOException {
181-
checkGroupExists(
182-
Optional.ofNullable(ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP)));
213+
NamespaceDescriptor ns) throws IOException {
214+
checkNamespaceGroup(ns);
183215
}
184216

185217
@Override
186218
public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx,
187-
NamespaceDescriptor currentNsDescriptor, NamespaceDescriptor newNsDescriptor)
188-
throws IOException {
189-
checkGroupExists(Optional
190-
.ofNullable(newNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP)));
219+
NamespaceDescriptor currentNsDescriptor, NamespaceDescriptor newNsDescriptor)
220+
throws IOException {
221+
if (!Objects.equals(
222+
currentNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP),
223+
newNsDescriptor.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP))) {
224+
checkNamespaceGroup(newNsDescriptor);
225+
}
191226
}
192227
}

hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,14 @@ public void testNamespaceConstraint() throws Exception {
152152
String nsName = tablePrefix + "_foo";
153153
String groupName = tablePrefix + "_foo";
154154
LOG.info("testNamespaceConstraint");
155-
rsGroupAdmin.addRSGroup(groupName);
155+
addGroup(groupName, 1);
156156
assertTrue(observer.preAddRSGroupCalled);
157157
assertTrue(observer.postAddRSGroupCalled);
158158

159159
admin.createNamespace(NamespaceDescriptor.create(nsName)
160160
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());
161+
RSGroupInfo rsGroupInfo = rsGroupAdmin.getRSGroupInfo(groupName);
162+
rsGroupAdmin.moveServers(rsGroupInfo.getServers(), RSGroupInfo.DEFAULT_GROUP);
161163
// test removing a referenced group
162164
try {
163165
rsGroupAdmin.removeRSGroup(groupName);

hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/TestRSGroupsBasics.java

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,8 @@
2020
import static org.junit.Assert.assertEquals;
2121
import static org.junit.Assert.assertFalse;
2222
import static org.junit.Assert.assertTrue;
23-
import static org.junit.Assert.fail;
2423

2524
import java.io.IOException;
26-
import java.util.ArrayList;
27-
import java.util.Iterator;
2825
import java.util.List;
2926
import java.util.Set;
3027
import org.apache.hadoop.hbase.HBaseClassTestRule;
@@ -136,45 +133,6 @@ public boolean evaluate() throws Exception {
136133
Assert.assertEquals(1, admin.getRegions(targetServer).size());
137134
}
138135

139-
@Test
140-
public void testCreateWhenRsgroupNoOnlineServers() throws Exception {
141-
LOG.info("testCreateWhenRsgroupNoOnlineServers");
142-
143-
// set rsgroup has no online servers and test create table
144-
final RSGroupInfo appInfo = addGroup("appInfo", 1);
145-
Iterator<Address> iterator = appInfo.getServers().iterator();
146-
List<ServerName> serversToDecommission = new ArrayList<>();
147-
ServerName targetServer = getServerName(iterator.next());
148-
assertTrue(master.getServerManager().getOnlineServers().containsKey(targetServer));
149-
serversToDecommission.add(targetServer);
150-
admin.decommissionRegionServers(serversToDecommission, true);
151-
assertEquals(1, admin.listDecommissionedRegionServers().size());
152-
153-
final TableName tableName = TableName.valueOf(tablePrefix + "_ns", name.getMethodName());
154-
admin.createNamespace(NamespaceDescriptor.create(tableName.getNamespaceAsString())
155-
.addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, appInfo.getName()).build());
156-
final TableDescriptor desc = TableDescriptorBuilder.newBuilder(tableName)
157-
.setColumnFamily(ColumnFamilyDescriptorBuilder.of("f")).build();
158-
try {
159-
admin.createTable(desc);
160-
fail("Shouldn't create table successfully!");
161-
} catch (Exception e) {
162-
LOG.debug("create table error", e);
163-
}
164-
165-
// recommission and test create table
166-
admin.recommissionRegionServer(targetServer, null);
167-
assertEquals(0, admin.listDecommissionedRegionServers().size());
168-
admin.createTable(desc);
169-
// wait for created table to be assigned
170-
TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate<Exception>() {
171-
@Override
172-
public boolean evaluate() throws Exception {
173-
return getTableRegionMap().get(desc.getTableName()) != null;
174-
}
175-
});
176-
}
177-
178136
@Test
179137
public void testDefaultNamespaceCreateAndAssign() throws Exception {
180138
LOG.info("testDefaultNamespaceCreateAndAssign");

0 commit comments

Comments
 (0)