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