001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hbase.rsgroup; 020 021import com.google.protobuf.RpcCallback; 022import com.google.protobuf.RpcController; 023import com.google.protobuf.Service; 024 025import java.io.IOException; 026import java.util.Collections; 027import java.util.HashSet; 028import java.util.List; 029import java.util.Optional; 030import java.util.Set; 031import java.util.stream.Collectors; 032 033import org.apache.hadoop.conf.Configuration; 034import org.apache.hadoop.hbase.CoprocessorEnvironment; 035import org.apache.hadoop.hbase.HBaseIOException; 036import org.apache.hadoop.hbase.HConstants; 037import org.apache.hadoop.hbase.MasterNotRunningException; 038import org.apache.hadoop.hbase.NamespaceDescriptor; 039import org.apache.hadoop.hbase.PleaseHoldException; 040import org.apache.hadoop.hbase.ServerName; 041import org.apache.hadoop.hbase.TableName; 042import org.apache.hadoop.hbase.client.RegionInfo; 043import org.apache.hadoop.hbase.client.SnapshotDescription; 044import org.apache.hadoop.hbase.client.TableDescriptor; 045import org.apache.hadoop.hbase.constraint.ConstraintException; 046import org.apache.hadoop.hbase.coprocessor.CoreCoprocessor; 047import org.apache.hadoop.hbase.coprocessor.HasMasterServices; 048import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor; 049import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; 050import org.apache.hadoop.hbase.coprocessor.MasterObserver; 051import org.apache.hadoop.hbase.coprocessor.ObserverContext; 052import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils; 053import org.apache.hadoop.hbase.ipc.RpcServer; 054import org.apache.hadoop.hbase.master.MasterServices; 055import org.apache.hadoop.hbase.net.Address; 056import org.apache.hadoop.hbase.protobuf.ProtobufUtil; 057import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos; 058import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos; 059import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.AddRSGroupRequest; 060import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.AddRSGroupResponse; 061import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupRequest; 062import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupResponse; 063import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerRequest; 064import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerResponse; 065import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableRequest; 066import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableResponse; 067import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoRequest; 068import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoResponse; 069import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosRequest; 070import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosResponse; 071import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersAndTablesRequest; 072import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersAndTablesResponse; 073import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersRequest; 074import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersResponse; 075import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveTablesRequest; 076import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveTablesResponse; 077import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RSGroupAdminService; 078import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupRequest; 079import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupResponse; 080import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest; 081import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse; 082import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RenameRSGroupRequest; 083import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RenameRSGroupResponse; 084import org.apache.hadoop.hbase.protobuf.generated.TableProtos; 085import org.apache.hadoop.hbase.security.User; 086import org.apache.hadoop.hbase.security.UserProvider; 087import org.apache.hadoop.hbase.security.access.AccessChecker; 088import org.apache.hadoop.hbase.security.access.Permission.Action; 089import org.apache.hadoop.util.Shell.ShellCommandExecutor; 090import org.apache.yetus.audience.InterfaceAudience; 091import org.slf4j.Logger; 092import org.slf4j.LoggerFactory; 093import org.apache.hbase.thirdparty.com.google.common.collect.Sets; 094 095// TODO: Encapsulate MasterObserver functions into separate subclass. 096@CoreCoprocessor 097@InterfaceAudience.Private 098public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver { 099 private static final Logger LOG = LoggerFactory.getLogger(RSGroupAdminEndpoint.class); 100 101 private MasterServices master = null; 102 // Only instance of RSGroupInfoManager. RSGroup aware load balancers ask for this instance on 103 // their setup. 104 private RSGroupInfoManager groupInfoManager; 105 private RSGroupAdminServer groupAdminServer; 106 private final RSGroupAdminService groupAdminService = new RSGroupAdminServiceImpl(); 107 private AccessChecker accessChecker; 108 109 /** Provider for mapping principal names to Users */ 110 private UserProvider userProvider; 111 112 @Override 113 public void start(CoprocessorEnvironment env) throws IOException { 114 if (!(env instanceof HasMasterServices)) { 115 throw new IOException("Does not implement HMasterServices"); 116 } 117 118 master = ((HasMasterServices)env).getMasterServices(); 119 groupInfoManager = RSGroupInfoManagerImpl.getInstance(master); 120 groupAdminServer = new RSGroupAdminServer(master, groupInfoManager); 121 Class<?> clazz = 122 master.getConfiguration().getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, null); 123 if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) { 124 throw new IOException("Configured balancer does not support RegionServer groups."); 125 } 126 accessChecker = ((HasMasterServices) env).getMasterServices().getAccessChecker(); 127 128 // set the user-provider. 129 this.userProvider = UserProvider.instantiate(env.getConfiguration()); 130 } 131 132 @Override 133 public void stop(CoprocessorEnvironment env) { 134 } 135 136 @Override 137 public Iterable<Service> getServices() { 138 return Collections.singleton(groupAdminService); 139 } 140 141 @Override 142 public Optional<MasterObserver> getMasterObserver() { 143 return Optional.of(this); 144 } 145 146 RSGroupInfoManager getGroupInfoManager() { 147 return groupInfoManager; 148 } 149 150 /** 151 * Implementation of RSGroupAdminService defined in RSGroupAdmin.proto. 152 * This class calls {@link RSGroupAdminServer} for actual work, converts result to protocol 153 * buffer response, handles exceptions if any occurred and then calls the {@code RpcCallback} with 154 * the response. 155 */ 156 private class RSGroupAdminServiceImpl extends RSGroupAdminProtos.RSGroupAdminService { 157 @Override 158 public void getRSGroupInfo(RpcController controller, 159 GetRSGroupInfoRequest request, RpcCallback<GetRSGroupInfoResponse> done) { 160 GetRSGroupInfoResponse.Builder builder = GetRSGroupInfoResponse.newBuilder(); 161 String groupName = request.getRSGroupName(); 162 LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, group=" 163 + groupName); 164 try { 165 checkPermission("getRSGroupInfo"); 166 RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName); 167 if (rsGroupInfo != null) { 168 builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(rsGroupInfo)); 169 } 170 } catch (IOException e) { 171 CoprocessorRpcUtils.setControllerException(controller, e); 172 } 173 done.run(builder.build()); 174 } 175 176 @Override 177 public void getRSGroupInfoOfTable(RpcController controller, 178 GetRSGroupInfoOfTableRequest request, RpcCallback<GetRSGroupInfoOfTableResponse> done) { 179 GetRSGroupInfoOfTableResponse.Builder builder = GetRSGroupInfoOfTableResponse.newBuilder(); 180 TableName tableName = ProtobufUtil.toTableName(request.getTableName()); 181 LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table=" 182 + tableName); 183 try { 184 checkPermission("getRSGroupInfoOfTable"); 185 RSGroupInfo RSGroupInfo = groupAdminServer.getRSGroupInfoOfTable(tableName); 186 if (RSGroupInfo != null) { 187 builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo)); 188 } 189 } catch (IOException e) { 190 CoprocessorRpcUtils.setControllerException(controller, e); 191 } 192 done.run(builder.build()); 193 } 194 195 @Override 196 public void moveServers(RpcController controller, MoveServersRequest request, 197 RpcCallback<MoveServersResponse> done) { 198 MoveServersResponse.Builder builder = MoveServersResponse.newBuilder(); 199 Set<Address> hostPorts = Sets.newHashSet(); 200 for (HBaseProtos.ServerName el : request.getServersList()) { 201 hostPorts.add(Address.fromParts(el.getHostName(), el.getPort())); 202 } 203 LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts +" to rsgroup " 204 + request.getTargetGroup()); 205 try { 206 if (master.getMasterCoprocessorHost() != null) { 207 master.getMasterCoprocessorHost().preMoveServers(hostPorts, request.getTargetGroup()); 208 } 209 checkPermission("moveServers"); 210 groupAdminServer.moveServers(hostPorts, request.getTargetGroup()); 211 if (master.getMasterCoprocessorHost() != null) { 212 master.getMasterCoprocessorHost().postMoveServers(hostPorts, request.getTargetGroup()); 213 } 214 } catch (IOException e) { 215 CoprocessorRpcUtils.setControllerException(controller, e); 216 } 217 done.run(builder.build()); 218 } 219 220 @Override 221 public void moveTables(RpcController controller, MoveTablesRequest request, 222 RpcCallback<MoveTablesResponse> done) { 223 MoveTablesResponse.Builder builder = MoveTablesResponse.newBuilder(); 224 Set<TableName> tables = new HashSet<>(request.getTableNameList().size()); 225 for (TableProtos.TableName tableName : request.getTableNameList()) { 226 tables.add(ProtobufUtil.toTableName(tableName)); 227 } 228 LOG.info(master.getClientIdAuditPrefix() + " move tables " + tables +" to rsgroup " 229 + request.getTargetGroup()); 230 try { 231 if (master.getMasterCoprocessorHost() != null) { 232 master.getMasterCoprocessorHost().preMoveTables(tables, request.getTargetGroup()); 233 } 234 checkPermission("moveTables"); 235 groupAdminServer.moveTables(tables, request.getTargetGroup()); 236 if (master.getMasterCoprocessorHost() != null) { 237 master.getMasterCoprocessorHost().postMoveTables(tables, request.getTargetGroup()); 238 } 239 } catch (IOException e) { 240 CoprocessorRpcUtils.setControllerException(controller, e); 241 } 242 done.run(builder.build()); 243 } 244 245 @Override 246 public void addRSGroup(RpcController controller, AddRSGroupRequest request, 247 RpcCallback<AddRSGroupResponse> done) { 248 AddRSGroupResponse.Builder builder = AddRSGroupResponse.newBuilder(); 249 LOG.info(master.getClientIdAuditPrefix() + " add rsgroup " + request.getRSGroupName()); 250 try { 251 if (master.getMasterCoprocessorHost() != null) { 252 master.getMasterCoprocessorHost().preAddRSGroup(request.getRSGroupName()); 253 } 254 checkPermission("addRSGroup"); 255 groupAdminServer.addRSGroup(request.getRSGroupName()); 256 if (master.getMasterCoprocessorHost() != null) { 257 master.getMasterCoprocessorHost().postAddRSGroup(request.getRSGroupName()); 258 } 259 } catch (IOException e) { 260 CoprocessorRpcUtils.setControllerException(controller, e); 261 } 262 done.run(builder.build()); 263 } 264 265 @Override 266 public void removeRSGroup(RpcController controller, 267 RemoveRSGroupRequest request, RpcCallback<RemoveRSGroupResponse> done) { 268 RemoveRSGroupResponse.Builder builder = 269 RemoveRSGroupResponse.newBuilder(); 270 LOG.info(master.getClientIdAuditPrefix() + " remove rsgroup " + request.getRSGroupName()); 271 try { 272 if (master.getMasterCoprocessorHost() != null) { 273 master.getMasterCoprocessorHost().preRemoveRSGroup(request.getRSGroupName()); 274 } 275 checkPermission("removeRSGroup"); 276 groupAdminServer.removeRSGroup(request.getRSGroupName()); 277 if (master.getMasterCoprocessorHost() != null) { 278 master.getMasterCoprocessorHost().postRemoveRSGroup(request.getRSGroupName()); 279 } 280 } catch (IOException e) { 281 CoprocessorRpcUtils.setControllerException(controller, e); 282 } 283 done.run(builder.build()); 284 } 285 286 @Override 287 public void balanceRSGroup(RpcController controller, 288 BalanceRSGroupRequest request, RpcCallback<BalanceRSGroupResponse> done) { 289 BalanceRSGroupResponse.Builder builder = BalanceRSGroupResponse.newBuilder(); 290 LOG.info(master.getClientIdAuditPrefix() + " balance rsgroup, group=" 291 + request.getRSGroupName()); 292 try { 293 if (master.getMasterCoprocessorHost() != null) { 294 master.getMasterCoprocessorHost().preBalanceRSGroup(request.getRSGroupName()); 295 } 296 checkPermission("balanceRSGroup"); 297 boolean balancerRan = groupAdminServer.balanceRSGroup(request.getRSGroupName()); 298 builder.setBalanceRan(balancerRan); 299 if (master.getMasterCoprocessorHost() != null) { 300 master.getMasterCoprocessorHost().postBalanceRSGroup(request.getRSGroupName(), 301 balancerRan); 302 } 303 } catch (IOException e) { 304 CoprocessorRpcUtils.setControllerException(controller, e); 305 builder.setBalanceRan(false); 306 } 307 done.run(builder.build()); 308 } 309 310 @Override 311 public void listRSGroupInfos(RpcController controller, 312 ListRSGroupInfosRequest request, RpcCallback<ListRSGroupInfosResponse> done) { 313 ListRSGroupInfosResponse.Builder builder = ListRSGroupInfosResponse.newBuilder(); 314 LOG.info(master.getClientIdAuditPrefix() + " list rsgroup"); 315 try { 316 checkPermission("listRSGroup"); 317 for (RSGroupInfo RSGroupInfo : groupAdminServer.listRSGroups()) { 318 builder.addRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(RSGroupInfo)); 319 } 320 } catch (IOException e) { 321 CoprocessorRpcUtils.setControllerException(controller, e); 322 } 323 done.run(builder.build()); 324 } 325 326 @Override 327 public void getRSGroupInfoOfServer(RpcController controller, 328 GetRSGroupInfoOfServerRequest request, RpcCallback<GetRSGroupInfoOfServerResponse> done) { 329 GetRSGroupInfoOfServerResponse.Builder builder = GetRSGroupInfoOfServerResponse.newBuilder(); 330 Address hp = Address.fromParts(request.getServer().getHostName(), 331 request.getServer().getPort()); 332 LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server=" 333 + hp); 334 try { 335 checkPermission("getRSGroupInfoOfServer"); 336 RSGroupInfo info = groupAdminServer.getRSGroupOfServer(hp); 337 if (info != null) { 338 builder.setRSGroupInfo(RSGroupProtobufUtil.toProtoGroupInfo(info)); 339 } 340 } catch (IOException e) { 341 CoprocessorRpcUtils.setControllerException(controller, e); 342 } 343 done.run(builder.build()); 344 } 345 346 @Override 347 public void moveServersAndTables(RpcController controller, 348 MoveServersAndTablesRequest request, RpcCallback<MoveServersAndTablesResponse> done) { 349 MoveServersAndTablesResponse.Builder builder = MoveServersAndTablesResponse.newBuilder(); 350 Set<Address> hostPorts = Sets.newHashSet(); 351 for (HBaseProtos.ServerName el : request.getServersList()) { 352 hostPorts.add(Address.fromParts(el.getHostName(), el.getPort())); 353 } 354 Set<TableName> tables = new HashSet<>(request.getTableNameList().size()); 355 for (TableProtos.TableName tableName : request.getTableNameList()) { 356 tables.add(ProtobufUtil.toTableName(tableName)); 357 } 358 LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts 359 + " and tables " + tables + " to rsgroup" + request.getTargetGroup()); 360 try { 361 if (master.getMasterCoprocessorHost() != null) { 362 master.getMasterCoprocessorHost().preMoveServersAndTables(hostPorts, tables, 363 request.getTargetGroup()); 364 } 365 checkPermission("moveServersAndTables"); 366 groupAdminServer.moveServersAndTables(hostPorts, tables, request.getTargetGroup()); 367 if (master.getMasterCoprocessorHost() != null) { 368 master.getMasterCoprocessorHost().postMoveServersAndTables(hostPorts, tables, 369 request.getTargetGroup()); 370 } 371 } catch (IOException e) { 372 CoprocessorRpcUtils.setControllerException(controller, e); 373 } 374 done.run(builder.build()); 375 } 376 377 @Override 378 public void removeServers(RpcController controller, 379 RemoveServersRequest request, 380 RpcCallback<RemoveServersResponse> done) { 381 RemoveServersResponse.Builder builder = 382 RemoveServersResponse.newBuilder(); 383 Set<Address> servers = Sets.newHashSet(); 384 for (HBaseProtos.ServerName el : request.getServersList()) { 385 servers.add(Address.fromParts(el.getHostName(), el.getPort())); 386 } 387 LOG.info(master.getClientIdAuditPrefix() 388 + " remove decommissioned servers from rsgroup: " + servers); 389 try { 390 if (master.getMasterCoprocessorHost() != null) { 391 master.getMasterCoprocessorHost().preRemoveServers(servers); 392 } 393 checkPermission("removeServers"); 394 groupAdminServer.removeServers(servers); 395 if (master.getMasterCoprocessorHost() != null) { 396 master.getMasterCoprocessorHost().postRemoveServers(servers); 397 } 398 } catch (IOException e) { 399 CoprocessorRpcUtils.setControllerException(controller, e); 400 } 401 done.run(builder.build()); 402 } 403 404 @Override 405 public void renameRSGroup(RpcController controller, 406 RenameRSGroupRequest request, 407 RpcCallback<RenameRSGroupResponse> done) { 408 String oldRSGroup = request.getOldRsgroupName(); 409 String newRSGroup = request.getNewRsgroupName(); 410 LOG.info("{} rename rsgroup from {} to {}", 411 master.getClientIdAuditPrefix(), oldRSGroup, newRSGroup); 412 413 RenameRSGroupResponse.Builder builder = RenameRSGroupResponse.newBuilder(); 414 try { 415 if (master.getMasterCoprocessorHost() != null) { 416 master.getMasterCoprocessorHost().preRenameRSGroup(oldRSGroup, newRSGroup); 417 } 418 checkPermission("renameRSGroup"); 419 groupAdminServer.renameRSGroup(oldRSGroup, newRSGroup); 420 if (master.getMasterCoprocessorHost() != null) { 421 master.getMasterCoprocessorHost().postRenameRSGroup(oldRSGroup, newRSGroup); 422 } 423 } catch (IOException e) { 424 CoprocessorRpcUtils.setControllerException(controller, e); 425 } 426 done.run(builder.build()); 427 } 428 } 429 430 boolean rsgroupHasServersOnline(TableDescriptor desc) throws IOException { 431 String groupName; 432 try { 433 groupName = 434 master.getClusterSchema().getNamespace(desc.getTableName().getNamespaceAsString()) 435 .getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); 436 if (groupName == null) { 437 groupName = RSGroupInfo.DEFAULT_GROUP; 438 } 439 } catch (MasterNotRunningException | PleaseHoldException e) { 440 LOG.info("Master has not initialized yet; temporarily using default RSGroup '" + 441 RSGroupInfo.DEFAULT_GROUP + "' for deploy of system table"); 442 groupName = RSGroupInfo.DEFAULT_GROUP; 443 } 444 445 RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName); 446 if (rsGroupInfo == null) { 447 throw new ConstraintException( 448 "Default RSGroup (" + groupName + ") for this table's " + "namespace does not exist."); 449 } 450 451 for (ServerName onlineServer : master.getServerManager().createDestinationServersList()) { 452 if (rsGroupInfo.getServers().contains(onlineServer.getAddress())) { 453 return true; 454 } 455 } 456 return false; 457 } 458 459 void assignTableToGroup(TableDescriptor desc) throws IOException { 460 RSGroupInfo rsGroupInfo = groupInfoManager.determineRSGroupInfoForTable(desc.getTableName()); 461 if (rsGroupInfo == null) { 462 throw new ConstraintException("Default RSGroup for this table " + desc.getTableName() 463 + " does not exist."); 464 } 465 if (!rsGroupInfo.containsTable(desc.getTableName())) { 466 LOG.debug("Pre-moving table " + desc.getTableName() + " to RSGroup " + rsGroupInfo.getName()); 467 groupAdminServer.moveTables(Sets.newHashSet(desc.getTableName()), rsGroupInfo.getName()); 468 } 469 } 470 471 ///////////////////////////////////////////////////////////////////////////// 472 // MasterObserver overrides 473 ///////////////////////////////////////////////////////////////////////////// 474 475 @Override 476 public void preCreateTableAction( 477 final ObserverContext<MasterCoprocessorEnvironment> ctx, 478 final TableDescriptor desc, 479 final RegionInfo[] regions) throws IOException { 480 if (desc.getTableName().isSystemTable()) { 481 return; 482 } 483 RSGroupInfo rsGroupInfo = groupInfoManager.determineRSGroupInfoForTable(desc.getTableName()); 484 if (rsGroupInfo == null) { 485 throw new ConstraintException("Default RSGroup for this table " + desc.getTableName() 486 + " does not exist."); 487 } 488 if (!RSGroupUtil.rsGroupHasOnlineServer(master, rsGroupInfo)) { 489 throw new HBaseIOException("No online servers in the rsgroup " + rsGroupInfo.getName() 490 + " which table " + desc.getTableName().getNameAsString() + " belongs to"); 491 } 492 synchronized (groupInfoManager) { 493 groupInfoManager.moveTables( 494 Collections.singleton(desc.getTableName()), rsGroupInfo.getName()); 495 } 496 } 497 498 // Remove table from its RSGroup. 499 @Override 500 public void postDeleteTable(ObserverContext<MasterCoprocessorEnvironment> ctx, 501 TableName tableName) throws IOException { 502 try { 503 RSGroupInfo group = groupAdminServer.getRSGroupInfoOfTable(tableName); 504 if (group != null) { 505 LOG.debug(String.format("Removing deleted table '%s' from rsgroup '%s'", tableName, 506 group.getName())); 507 groupAdminServer.moveTables(Sets.newHashSet(tableName), null); 508 } 509 } catch (IOException ex) { 510 LOG.debug("Failed to perform RSGroup information cleanup for table: " + tableName, ex); 511 } 512 } 513 514 @Override 515 public void preCreateNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, 516 NamespaceDescriptor ns) throws IOException { 517 String group = ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); 518 if(group != null && groupAdminServer.getRSGroupInfo(group) == null) { 519 throw new ConstraintException("Region server group " + group + " does not exist."); 520 } 521 } 522 523 @Override 524 public void preModifyNamespace(ObserverContext<MasterCoprocessorEnvironment> ctx, 525 NamespaceDescriptor ns) throws IOException { 526 preCreateNamespace(ctx, ns); 527 } 528 529 @Override 530 public void preCloneSnapshot(ObserverContext<MasterCoprocessorEnvironment> ctx, 531 SnapshotDescription snapshot, TableDescriptor desc) throws IOException { 532 assignTableToGroup(desc); 533 } 534 535 @Override 536 public void postClearDeadServers(ObserverContext<MasterCoprocessorEnvironment> ctx, 537 List<ServerName> servers, List<ServerName> notClearedServers) 538 throws IOException { 539 Set<Address> clearedServer = servers.stream(). 540 filter(server -> !notClearedServers.contains(server)). 541 map(ServerName::getAddress). 542 collect(Collectors.toSet()); 543 if(!clearedServer.isEmpty()) { 544 groupAdminServer.removeServers(clearedServer); 545 } 546 } 547 548 public void checkPermission(String request) throws IOException { 549 accessChecker.requirePermission(getActiveUser(), request, null, Action.ADMIN); 550 } 551 552 /** 553 * Returns the active user to which authorization checks should be applied. 554 * If we are in the context of an RPC call, the remote user is used, 555 * otherwise the currently logged in user is used. 556 */ 557 private User getActiveUser() throws IOException { 558 // for non-rpc handling, fallback to system user 559 Optional<User> optionalUser = RpcServer.getRequestUser(); 560 if (optionalUser.isPresent()) { 561 return optionalUser.get(); 562 } 563 return userProvider.getCurrent(); 564 } 565}