diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java index c553a5656c16..a9a6c577aef4 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java @@ -45,6 +45,7 @@ import org.apache.hadoop.hbase.client.replication.TableCFs; import org.apache.hadoop.hbase.client.security.SecurityCapability; import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel; +import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.quotas.QuotaFilter; import org.apache.hadoop.hbase.quotas.QuotaSettings; import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshotView; @@ -53,6 +54,7 @@ import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; import org.apache.hadoop.hbase.security.access.GetUserPermissionsRequest; import org.apache.hadoop.hbase.security.access.Permission; import org.apache.hadoop.hbase.security.access.UserPermission; @@ -2232,4 +2234,66 @@ List hasUserPermissions(String userName, List permissions) default List hasUserPermissions(List permissions) throws IOException { return hasUserPermissions(null, permissions); } + + /** + * Gets group info for the given group name + * @param groupName the group name + * @return group info + * @throws IOException if a remote or network exception occurs + */ + RSGroupInfo getRSGroupInfo(String groupName) throws IOException; + + /** + * Move given set of servers to the specified target RegionServer group + * @param servers set of servers to move + * @param targetGroup the group to move servers to + * @throws IOException if a remote or network exception occurs + */ + void moveServers(Set
servers, String targetGroup) throws IOException; + + /** + * Creates a new RegionServer group with the given name + * @param groupName the name of the group + * @throws IOException if a remote or network exception occurs + */ + void addRSGroup(String groupName) throws IOException; + + /** + * Removes RegionServer group associated with the given name + * @param groupName the group name + * @throws IOException if a remote or network exception occurs + */ + void removeRSGroup(String groupName) throws IOException; + + /** + * Balance regions in the given RegionServer group + * @param groupName the group name + * @return boolean Whether balance ran or not + * @throws IOException if a remote or network exception occurs + */ + boolean balanceRSGroup(String groupName) throws IOException; + + /** + * Lists current set of RegionServer groups + * @throws IOException if a remote or network exception occurs + */ + List listRSGroups() throws IOException; + + /** + * Retrieve the RSGroupInfo a server is affiliated to + * @param hostPort HostPort to get RSGroupInfo for + * @throws IOException if a remote or network exception occurs + */ + RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException; + + /** + * Remove decommissioned servers from group + * 1. Sometimes we may find the server aborted due to some hardware failure and we must offline + * the server for repairing. Or we need to move some servers to join other clusters. + * So we need to remove these servers from the group. + * 2. Dead/recovering/live servers will be disallowed. + * @param servers set of servers to remove + * @throws IOException if a remote or network exception occurs + */ + void removeServers(Set
servers) throws IOException; } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java index 599e5d69f6e0..79c20481a3bd 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AdminOverAsyncAdmin.java @@ -49,6 +49,7 @@ import org.apache.hadoop.hbase.client.replication.TableCFs; import org.apache.hadoop.hbase.client.security.SecurityCapability; import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel; +import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.quotas.QuotaFilter; import org.apache.hadoop.hbase.quotas.QuotaSettings; import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshotView; @@ -56,6 +57,7 @@ import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; import org.apache.hadoop.hbase.security.access.GetUserPermissionsRequest; import org.apache.hadoop.hbase.security.access.Permission; import org.apache.hadoop.hbase.security.access.UserPermission; @@ -942,4 +944,46 @@ public List hasUserPermissions(String userName, List permis throws IOException { return get(admin.hasUserPermissions(userName, permissions)); } + + @Override + public RSGroupInfo getRSGroupInfo(String groupName) throws IOException { +// return get(admin.getRSGroupInfo()); + return null; + } + + @Override + public void moveServers(Set
servers, String targetGroup) throws IOException { + + } + + @Override + public void addRSGroup(String groupName) throws IOException { + + } + + @Override + public void removeRSGroup(String groupName) throws IOException { + + } + + @Override + public boolean balanceRSGroup(String groupName) throws IOException { + return false; + } + + @Override + public List listRSGroups() throws IOException { + return null; + } + + @Override + public RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException { + return null; + } + + @Override + public void removeServers(Set
servers) throws IOException { + + } + } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java index 75dc6d2a2185..7653c707c692 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java @@ -40,12 +40,14 @@ import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.replication.TableCFs; import org.apache.hadoop.hbase.client.security.SecurityCapability; +import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.quotas.QuotaFilter; import org.apache.hadoop.hbase.quotas.QuotaSettings; import org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshotView; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; import org.apache.hadoop.hbase.security.access.GetUserPermissionsRequest; import org.apache.hadoop.hbase.security.access.Permission; import org.apache.hadoop.hbase.security.access.UserPermission; @@ -1381,7 +1383,7 @@ default CompletableFuture> listDeadServers() { * @param newTableName name of the new table where the table will be created * @param preserveSplits True if the splits should be preserved */ - CompletableFuture cloneTableSchema(final TableName tableName, + CompletableFuture cloneTableSchema(final TableName tableName, final TableName newTableName, final boolean preserveSplits); /** @@ -1484,4 +1486,66 @@ CompletableFuture> hasUserPermissions(String userName, default CompletableFuture> hasUserPermissions(List permissions) { return hasUserPermissions(null, permissions); } + + /** + * Gets group info for the given group name + * @param groupName the group name + * @return group info + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture getRSGroupInfo(String groupName) throws IOException; + + /** + * Move given set of servers to the specified target RegionServer group + * @param servers set of servers to move + * @param targetGroup the group to move servers to + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture moveServers(Set
servers, String targetGroup) throws IOException; + + /** + * Creates a new RegionServer group with the given name + * @param groupName the name of the group + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture addRSGroup(String groupName) throws IOException; + + /** + * Removes RegionServer group associated with the given name + * @param groupName the group name + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture removeRSGroup(String groupName) throws IOException; + + /** + * Balance regions in the given RegionServer group + * @param groupName the group name + * @return boolean Whether balance ran or not + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture balanceRSGroup(String groupName) throws IOException; + + /** + * Lists current set of RegionServer groups + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture> listRSGroups() throws IOException; + + /** + * Retrieve the RSGroupInfo a server is affiliated to + * @param hostPort HostPort to get RSGroupInfo for + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture getRSGroupOfServer(Address hostPort) throws IOException; + + /** + * Remove decommissioned servers from group + * 1. Sometimes we may find the server aborted due to some hardware failure and we must offline + * the server for repairing. Or we need to move some servers to join other clusters. + * So we need to remove these servers from the group. + * 2. Dead/recovering/live servers will be disallowed. + * @param servers set of servers to remove + * @throws IOException if a remote or network exception occurs + */ + CompletableFuture removeServers(Set
servers) throws IOException; } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java index 7787f188331d..57cfde710380 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java @@ -826,4 +826,53 @@ public CompletableFuture> hasUserPermissions(String userName, List permissions) { return wrap(rawAdmin.hasUserPermissions(userName, permissions)); } + + @Override + public java.util.concurrent.CompletableFuture getRSGroupInfo( + String groupName) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.CompletableFuture moveServers( + java.util.Set servers, String targetGroup) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.CompletableFuture addRSGroup(String groupName) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.CompletableFuture removeRSGroup(String groupName) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.CompletableFuture balanceRSGroup(String groupName) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.CompletableFuture> listRSGroups() + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.CompletableFuture getRSGroupOfServer( + org.apache.hadoop.hbase.net.Address hostPort) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.CompletableFuture removeServers( + java.util.Set servers) throws java.io.IOException { + return null; + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java index 47a79022cb4d..c477f050afe1 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java @@ -78,6 +78,7 @@ import org.apache.hadoop.hbase.client.security.SecurityCapability; import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.ipc.HBaseRpcController; +import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.quotas.QuotaFilter; import org.apache.hadoop.hbase.quotas.QuotaSettings; import org.apache.hadoop.hbase.quotas.QuotaTableUtil; @@ -86,6 +87,7 @@ import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; import org.apache.hadoop.hbase.replication.SyncReplicationState; +import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; import org.apache.hadoop.hbase.security.access.GetUserPermissionsRequest; import org.apache.hadoop.hbase.security.access.Permission; import org.apache.hadoop.hbase.security.access.ShadedAccessControlUtil; @@ -297,6 +299,22 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.TransitReplicationPeerSyncReplicationStateResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.AddRSGroupRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.AddRSGroupResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos; /** @@ -3856,4 +3874,92 @@ public CompletableFuture> hasUserPermissions(String userName, resp -> resp.getHasUserPermissionList())) .call(); } + + @Override + public CompletableFuture getRSGroupInfo(String groupName) { + return this. newMasterCaller() + .action(((controller, stub) -> this. + call(controller, stub, + RequestConverter.buildGetRSGroupInfoRequest(groupName), + (s, c, req, done) -> s.getRSGroupInfo(c, req, done), + resp -> ProtobufUtil.toGroupInfo(resp.getRSGroupInfo())))) + .call(); + } + + @Override + public CompletableFuture moveServers(Set
servers, String targetGroup) { + return this. newMasterCaller() + .action((controller, stub) -> this. + call(controller, stub, + RequestConverter.buildMoveServersRequest(servers, targetGroup), + (s, c, req, done) -> s.moveServers(c, req, done), resp -> null)) + .call(); + } + + @Override + public CompletableFuture addRSGroup(String groupName) { + return this. newMasterCaller() + .action(((controller, stub) -> this. + call(controller, stub, + AddRSGroupRequest.newBuilder().setRSGroupName(groupName).build(), + (s, c, req, done) -> s.addRSGroup(c, req, done), resp -> null))) + .call(); + } + + @Override + public CompletableFuture removeRSGroup(String groupName) { + return this. newMasterCaller() + .action((controller, stub) -> this. + call(controller, stub, + RemoveRSGroupRequest.newBuilder().setRSGroupName(groupName).build(), + (s, c, req, done) -> s.removeRSGroup(c, req, done), resp -> null)) + .call(); + } + + @Override + public CompletableFuture balanceRSGroup(String groupName) { + return this. newMasterCaller() + .action((controller, stub) -> this. + call(controller, stub, + BalanceRSGroupRequest.newBuilder().setRSGroupName(groupName).build(), + (s, c, req, done) -> s.balanceRSGroup(c, req, done), + resp -> resp.getBalanceRan())) + .call(); + } + + @Override + public CompletableFuture> listRSGroups() { + return this.> newMasterCaller() + .action((controller, stub) -> this + .> call(controller, + stub, ListRSGroupInfosRequest.getDefaultInstance(), + (s, c, req, done) -> s.listRSGroupInfos(c, req, done), + resp -> resp.getRSGroupInfoList().stream() + .map(r -> ProtobufUtil.toGroupInfo(r)) + .collect(Collectors.toList()))) + .call(); + } + + @Override + public CompletableFuture getRSGroupOfServer(Address hostPort) { + return this. newMasterCaller() + .action((controller, stub) -> this. + call( + controller, stub, + RequestConverter.buildGetRSGroupInfoOfServerRequest(hostPort), + (s, c, req, done) -> s.getRSGroupInfoOfServer(c, req, done), + resp -> ProtobufUtil.toGroupInfo(resp.getRSGroupInfo()))) + .call(); + } + + @Override + public CompletableFuture removeServers(Set
servers) { + return this. newMasterCaller() + .action((controller, stub) -> this. + call(controller, stub, + RequestConverter.buildRemoveServersRequest(servers), + (s, c, req, done) -> s.removeServers(c, req, done), resp -> null)) + .call(); + } + } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java index 1bad6bd3e308..10cf592f2329 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java @@ -56,6 +56,7 @@ import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.filter.ByteArrayComparable; import org.apache.hadoop.hbase.io.TimeRange; +import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.SyncReplicationState; import org.apache.hadoop.hbase.util.Bytes; @@ -64,6 +65,7 @@ import org.apache.hadoop.security.token.Token; import org.apache.yetus.audience.InterfaceAudience; +import org.apache.hbase.thirdparty.com.google.common.collect.Sets; import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearCompactionQueuesRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearRegionBlockCacheRequest; @@ -153,6 +155,10 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.RemoveReplicationPeerRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.TransitReplicationPeerSyncReplicationStateRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest; /** * Helper utility to build protocol buffer requests, @@ -1900,4 +1906,48 @@ private static List toEncodedRegionNameRegionSpecifiers( map(r -> buildRegionSpecifier(RegionSpecifierType.ENCODED_REGION_NAME, Bytes.toBytes(r))). collect(Collectors.toList()); } + + public static GetRSGroupInfoRequest buildGetRSGroupInfoRequest(String groupName) { + GetRSGroupInfoRequest.Builder builder = GetRSGroupInfoRequest.newBuilder(); + if (groupName != null && !groupName.isEmpty()) { + builder.setRSGroupName(groupName); + } + return builder.build(); + } + + public static MoveServersRequest buildMoveServersRequest(Set
servers, + String targetGroup) { + Set hostPorts = Sets.newHashSet(); + for (Address el : servers) { + hostPorts.add( + HBaseProtos.ServerName.newBuilder().setHostName(el.getHostname()).setPort(el.getPort()) + .build()); + } + return MoveServersRequest.newBuilder().setTargetGroup(targetGroup).addAllServers(hostPorts) + .build(); + } + + public static GetRSGroupInfoOfServerRequest buildGetRSGroupInfoOfServerRequest(Address hostPort) { + return GetRSGroupInfoOfServerRequest.newBuilder() + .setServer(HBaseProtos.ServerName.newBuilder() + .setHostName(hostPort.getHostname()) + .setPort(hostPort.getPort()) + .build()) + .build(); + } + + public static RemoveServersRequest buildRemoveServersRequest(Set
servers) { + Set hostPorts = Sets.newHashSet(); + for(Address el: servers) { + hostPorts.add(HBaseProtos.ServerName.newBuilder() + .setHostName(el.getHostname()) + .setPort(el.getPort()) + .build()); + } + return RemoveServersRequest.newBuilder() + .addAllServers(hostPorts) + .build(); + } + + } diff --git a/hbase-protocol-shaded/src/main/protobuf/Master.proto b/hbase-protocol-shaded/src/main/protobuf/Master.proto index 3429d0343dcb..104a4ca1b9c3 100644 --- a/hbase-protocol-shaded/src/main/protobuf/Master.proto +++ b/hbase-protocol-shaded/src/main/protobuf/Master.proto @@ -37,6 +37,7 @@ import "Quota.proto"; import "Replication.proto"; import "Snapshot.proto"; import "AccessControl.proto"; +import "RSGroupAdmin.proto"; /* Column-level protobufs */ @@ -1053,6 +1054,30 @@ service MasterService { /** returns a list of namespace names */ rpc ListNamespaces(ListNamespacesRequest) returns(ListNamespacesResponse); + + rpc GetRSGroupInfo(GetRSGroupInfoRequest) + returns (GetRSGroupInfoResponse); + + rpc GetRSGroupInfoOfServer(GetRSGroupInfoOfServerRequest) + returns (GetRSGroupInfoOfServerResponse); + + rpc MoveServers(MoveServersRequest) + returns (MoveServersResponse); + + rpc AddRSGroup(AddRSGroupRequest) + returns (AddRSGroupResponse); + + rpc RemoveRSGroup(RemoveRSGroupRequest) + returns (RemoveRSGroupResponse); + + rpc BalanceRSGroup(BalanceRSGroupRequest) + returns (BalanceRSGroupResponse); + + rpc ListRSGroupInfos(ListRSGroupInfosRequest) + returns (ListRSGroupInfosResponse); + + rpc RemoveServers(RemoveServersRequest) + returns (RemoveServersResponse); } // HBCK Service definitions. diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java index cab3a64004ce..31541aaedfec 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java @@ -3409,12 +3409,6 @@ public void requestMobCompaction(TableName tableName, mobCompactThread.requestMobCompaction(conf, fs, tableName, columns, allFiles); } - /** - * Queries the state of the {@link LoadBalancerTracker}. If the balancer is not initialized, - * false is returned. - * - * @return The state of the load balancer, or false if the load balancer isn't defined. - */ public boolean isBalancerOn() { return !isInMaintenanceMode() && loadBalancerTracker != null diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index c8707f62ac65..1aaf45e521b3 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -39,6 +39,7 @@ import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.MetaTableAccessor; import org.apache.hadoop.hbase.NamespaceDescriptor; +import org.apache.hadoop.hbase.net.Address; import org.apache.hadoop.hbase.Server; import org.apache.hadoop.hbase.ServerMetrics; import org.apache.hadoop.hbase.ServerMetricsBuilder; @@ -92,6 +93,7 @@ import org.apache.hadoop.hbase.replication.ReplicationException; import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; import org.apache.hadoop.hbase.replication.ReplicationPeerDescription; +import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; import org.apache.hadoop.hbase.security.Superusers; import org.apache.hadoop.hbase.security.User; import org.apache.hadoop.hbase.security.access.AccessChecker; @@ -116,6 +118,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.apache.hbase.thirdparty.com.google.common.collect.Sets; import org.apache.hbase.thirdparty.com.google.protobuf.RpcController; import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; @@ -333,6 +336,30 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.TransitReplicationPeerSyncReplicationStateResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.ReplicationProtos.UpdateReplicationPeerConfigResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RSGroupAdminService; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.AddRSGroupRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.AddRSGroupResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersAndTablesRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersAndTablesResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveTablesRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveTablesResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse; +import org.apache.hadoop.hbase.rsgroup.RSGroupUtil; import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription; /** @@ -340,9 +367,10 @@ */ @InterfaceAudience.Private @SuppressWarnings("deprecation") -public class MasterRpcServices extends RSRpcServices - implements MasterService.BlockingInterface, RegionServerStatusService.BlockingInterface, - LockService.BlockingInterface, HbckService.BlockingInterface { +public class MasterRpcServices extends RSRpcServices implements MasterService.BlockingInterface, + RegionServerStatusService.BlockingInterface, + LockService.BlockingInterface, HbckService.BlockingInterface, + RSGroupAdminService.BlockingInterface{ private static final Logger LOG = LoggerFactory.getLogger(MasterRpcServices.class.getName()); private static final Logger AUDITLOG = LoggerFactory.getLogger("SecurityLogger."+MasterRpcServices.class.getName()); @@ -2776,4 +2804,223 @@ private boolean shouldSubmitSCP(ServerName serverName) { } return true; } + + + @Override + public GetRSGroupInfoResponse getRSGroupInfo(RpcController controller, + GetRSGroupInfoRequest request) throws ServiceException { + GetRSGroupInfoResponse.Builder builder = GetRSGroupInfoResponse.newBuilder(); + String groupName = request.getRSGroupName(); + LOG.info( + master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, group=" + groupName); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preGetRSGroupInfo(groupName); + } + RSGroupInfo rsGroupInfo = master.getRSRSGroupInfoManager().getRSGroup(groupName); + if (rsGroupInfo != null) { + builder.setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(fillTables(rsGroupInfo))); + } + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postGetRSGroupInfo(groupName); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } + + @Deprecated + @Override + public GetRSGroupInfoOfTableResponse getRSGroupInfoOfTable(RpcController controller, + GetRSGroupInfoOfTableRequest request) throws ServiceException { + return null; + } + + @Override + public GetRSGroupInfoOfServerResponse getRSGroupInfoOfServer(RpcController controller, + GetRSGroupInfoOfServerRequest request) throws ServiceException { + GetRSGroupInfoOfServerResponse.Builder builder = GetRSGroupInfoOfServerResponse.newBuilder(); + Address hp = Address.fromParts(request.getServer().getHostName(), + request.getServer().getPort()); + LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server=" + hp); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preGetRSGroupInfoOfServer(hp); + } + RSGroupInfo info = master.getRSRSGroupInfoManager().getRSGroupOfServer(hp); + if (info != null) { + builder.setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(fillTables(info))); + } + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postGetRSGroupInfoOfServer(hp); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } + + private RSGroupInfo fillTables(RSGroupInfo rsGroupInfo) throws IOException { + return RSGroupUtil.fillTables(rsGroupInfo, master.getTableDescriptors().getAll().values()); + } + + @Override + public MoveServersResponse moveServers(RpcController controller, MoveServersRequest request) + throws ServiceException { + Set
hostPorts = Sets.newHashSet(); + MoveServersResponse.Builder builder = MoveServersResponse.newBuilder(); + for (HBaseProtos.ServerName el : request.getServersList()) { + hostPorts.add(Address.fromParts(el.getHostName(), el.getPort())); + } + LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts + " to rsgroup " + + request.getTargetGroup()); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preMoveServers(hostPorts, request.getTargetGroup()); + } + master.getRSRSGroupInfoManager().moveServers(hostPorts, request.getTargetGroup()); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postMoveServers(hostPorts, request.getTargetGroup()); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } + + @Deprecated + @Override + public MoveTablesResponse moveTables(RpcController controller, MoveTablesRequest request) + throws ServiceException { + return null; + } + + @Override + public AddRSGroupResponse addRSGroup(RpcController controller, AddRSGroupRequest request) + throws ServiceException { + AddRSGroupResponse.Builder builder = AddRSGroupResponse.newBuilder(); + LOG.info(master.getClientIdAuditPrefix() + " add rsgroup " + request.getRSGroupName()); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preAddRSGroup(request.getRSGroupName()); + } + master.getRSRSGroupInfoManager().addRSGroup(new RSGroupInfo(request.getRSGroupName())); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postAddRSGroup(request.getRSGroupName()); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } + + @Override + public RemoveRSGroupResponse removeRSGroup(RpcController controller, RemoveRSGroupRequest request) + throws ServiceException { + RemoveRSGroupResponse.Builder builder = RemoveRSGroupResponse.newBuilder(); + LOG.info(master.getClientIdAuditPrefix() + " remove rsgroup " + request.getRSGroupName()); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preRemoveRSGroup(request.getRSGroupName()); + } + master.getRSRSGroupInfoManager().removeRSGroup(request.getRSGroupName()); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postRemoveRSGroup(request.getRSGroupName()); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } + + @Override + public BalanceRSGroupResponse balanceRSGroup(RpcController controller, + BalanceRSGroupRequest request) throws ServiceException { + BalanceRSGroupResponse.Builder builder = BalanceRSGroupResponse.newBuilder(); + LOG.info( + master.getClientIdAuditPrefix() + " balance rsgroup, group=" + request.getRSGroupName()); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preBalanceRSGroup(request.getRSGroupName()); + } + boolean balancerRan = + master.getRSRSGroupInfoManager().balanceRSGroup(request.getRSGroupName()); + builder.setBalanceRan(balancerRan); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postBalanceRSGroup(request.getRSGroupName(), balancerRan); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } + + @Override + public ListRSGroupInfosResponse listRSGroupInfos(RpcController controller, + ListRSGroupInfosRequest request) throws ServiceException { + ListRSGroupInfosResponse.Builder builder = ListRSGroupInfosResponse.newBuilder(); + LOG.info(master.getClientIdAuditPrefix() + " list rsgroup"); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preListRSGroups(); + } + List rsGroupInfos = master.getRSRSGroupInfoManager().listRSGroups().stream() + .map(RSGroupInfo::new).collect(Collectors.toList()); + Map name2Info = new HashMap<>(); + for (RSGroupInfo rsGroupInfo : rsGroupInfos) { + name2Info.put(rsGroupInfo.getName(), rsGroupInfo); + } + for (TableDescriptor td : master.getTableDescriptors().getAll().values()) { + String groupName = td.getRegionServerGroup().orElse(RSGroupInfo.DEFAULT_GROUP); + RSGroupInfo rsGroupInfo = name2Info.get(groupName); + if (rsGroupInfo != null) { + rsGroupInfo.addTable(td.getTableName()); + } + } + for (RSGroupInfo rsGroupInfo : rsGroupInfos) { + // TODO: this can be done at once outside this loop, do not need to scan all every time. + builder.addRSGroupInfo(ProtobufUtil.toProtoGroupInfo(rsGroupInfo)); + } + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postListRSGroups(); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } + + @Deprecated + @Override + public MoveServersAndTablesResponse moveServersAndTables(RpcController controller, + MoveServersAndTablesRequest request) throws ServiceException { + return null; + } + + @Override + public RemoveServersResponse removeServers(RpcController controller, RemoveServersRequest request) + throws ServiceException { + RemoveServersResponse.Builder builder = RemoveServersResponse.newBuilder(); + Set
servers = Sets.newHashSet(); + for (HBaseProtos.ServerName el : request.getServersList()) { + servers.add(Address.fromParts(el.getHostName(), el.getPort())); + } + LOG.info(master.getClientIdAuditPrefix() + + " remove decommissioned servers from rsgroup: " + servers); + try { + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().preRemoveServers(servers); + } + master.getRSRSGroupInfoManager().removeServers(servers); + if (master.getMasterCoprocessorHost() != null) { + master.getMasterCoprocessorHost().postRemoveServers(servers); + } + } catch (IOException e) { + throw new ServiceException(e); + } + return builder.build(); + } + + } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java index ead40b989d8f..9c90368be07e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java @@ -52,6 +52,7 @@ import org.apache.hadoop.hbase.rsgroup.RSGroupInfoManager; import org.apache.hadoop.hbase.security.access.AccessChecker; import org.apache.hadoop.hbase.security.access.ZKPermissionWatcher; +import org.apache.hadoop.hbase.zookeeper.LoadBalancerTracker; import org.apache.yetus.audience.InterfaceAudience; import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; @@ -540,4 +541,12 @@ default SplitWALManager getSplitWALManager(){ * @return the {@link RSGroupInfoManager} */ RSGroupInfoManager getRSRSGroupInfoManager(); + + /** + * Queries the state of the {@link LoadBalancerTracker}. If the balancer is not initialized, + * false is returned. + * + * @return The state of the load balancer, or false if the load balancer isn't defined. + */ + boolean isBalancerOn(); } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdmin.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdmin.java deleted file mode 100644 index 344d0b385366..000000000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdmin.java +++ /dev/null @@ -1,78 +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 java.io.IOException; -import java.util.List; -import java.util.Set; -import org.apache.hadoop.hbase.net.Address; -import org.apache.yetus.audience.InterfaceAudience; - -/** - * Group user API interface used between client and server. - */ -@InterfaceAudience.Private -public interface RSGroupAdmin { - /** - * Gets {@code RSGroupInfo} for given group name. - */ - RSGroupInfo getRSGroupInfo(String groupName) throws IOException; - - /** - * Move given set of servers to the specified target RegionServer group. - */ - void moveServers(Set
servers, String targetGroup) throws IOException; - - /** - * Creates a new RegionServer group with the given name. - */ - void addRSGroup(String groupName) throws IOException; - - /** - * Removes RegionServer group associated with the given name. - */ - void removeRSGroup(String groupName) throws IOException; - - /** - * Balance regions in the given RegionServer group. - * - * @return boolean Whether balance ran or not - */ - boolean balanceRSGroup(String groupName) throws IOException; - - /** - * Lists current set of RegionServer groups. - */ - List listRSGroups() throws IOException; - - /** - * Retrieve the RSGroupInfo a server is affiliated to - * @param hostPort HostPort to get RSGroupInfo for - */ - RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException; - - /** - * Remove decommissioned servers from rsgroup. - * 1. Sometimes we may find the server aborted due to some hardware failure and we must offline - * the server for repairing. Or we need to move some servers to join other clusters. - * So we need to remove these servers from the rsgroup. - * 2. Dead/recovering/live servers will be disallowed. - * @param servers set of servers to remove - */ - void removeServers(Set
servers) throws IOException; -} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminClient.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminClient.java deleted file mode 100644 index 07f0efdadbb4..000000000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminClient.java +++ /dev/null @@ -1,240 +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 com.google.protobuf.ServiceException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.TableNotFoundException; -import org.apache.hadoop.hbase.client.Admin; -import org.apache.hadoop.hbase.client.Connection; -import org.apache.hadoop.hbase.net.Address; -import org.apache.hadoop.hbase.protobuf.ProtobufUtil; -import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.AddRSGroupRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersAndTablesRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveTablesRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RSGroupAdminService; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupProtos; -import org.apache.yetus.audience.InterfaceAudience; - -import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; -import org.apache.hbase.thirdparty.com.google.common.collect.Sets; - -/** - * Client used for managing region server group information. - */ -@InterfaceAudience.Private -public class RSGroupAdminClient implements RSGroupAdmin { - private RSGroupAdminService.BlockingInterface stub; - private Admin admin; - - public RSGroupAdminClient(Connection conn) throws IOException { - admin = conn.getAdmin(); - stub = RSGroupAdminService.newBlockingStub(admin.coprocessorService()); - } - - // for writing UTs - @VisibleForTesting - protected RSGroupAdminClient() { - } - - @Override - public RSGroupInfo getRSGroupInfo(String groupName) throws IOException { - try { - GetRSGroupInfoResponse resp = stub.getRSGroupInfo(null, - GetRSGroupInfoRequest.newBuilder().setRSGroupName(groupName).build()); - if (resp.hasRSGroupInfo()) { - return ProtobufUtil.toGroupInfo(resp.getRSGroupInfo()); - } - return null; - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - public RSGroupInfo getRSGroupInfoOfTable(TableName tableName) throws IOException { - GetRSGroupInfoOfTableRequest request = GetRSGroupInfoOfTableRequest.newBuilder().setTableName( - ProtobufUtil.toProtoTableName(tableName)).build(); - try { - GetRSGroupInfoOfTableResponse resp = stub.getRSGroupInfoOfTable(null, request); - if (resp.hasRSGroupInfo()) { - return ProtobufUtil.toGroupInfo(resp.getRSGroupInfo()); - } - return null; - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - @Override - public void moveServers(Set
servers, String targetGroup) throws IOException { - Set hostPorts = Sets.newHashSet(); - for(Address el: servers) { - hostPorts.add(HBaseProtos.ServerName.newBuilder() - .setHostName(el.getHostname()) - .setPort(el.getPort()) - .build()); - } - MoveServersRequest request = MoveServersRequest.newBuilder() - .setTargetGroup(targetGroup) - .addAllServers(hostPorts) - .build(); - try { - stub.moveServers(null, request); - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - public void moveTables(Set tables, String targetGroup) throws IOException { - MoveTablesRequest.Builder builder = MoveTablesRequest.newBuilder().setTargetGroup(targetGroup); - for(TableName tableName: tables) { - builder.addTableName(ProtobufUtil.toProtoTableName(tableName)); - if (!admin.tableExists(tableName)) { - throw new TableNotFoundException(tableName); - } - } - try { - stub.moveTables(null, builder.build()); - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - @Override - public void addRSGroup(String groupName) throws IOException { - AddRSGroupRequest request = AddRSGroupRequest.newBuilder().setRSGroupName(groupName).build(); - try { - stub.addRSGroup(null, request); - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - @Override - public void removeRSGroup(String name) throws IOException { - RemoveRSGroupRequest request = RemoveRSGroupRequest.newBuilder().setRSGroupName(name).build(); - try { - stub.removeRSGroup(null, request); - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - @Override - public boolean balanceRSGroup(String groupName) throws IOException { - BalanceRSGroupRequest request = BalanceRSGroupRequest.newBuilder() - .setRSGroupName(groupName).build(); - try { - return stub.balanceRSGroup(null, request).getBalanceRan(); - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - @Override - public List listRSGroups() throws IOException { - try { - List resp = stub.listRSGroupInfos(null, - ListRSGroupInfosRequest.getDefaultInstance()).getRSGroupInfoList(); - List result = new ArrayList<>(resp.size()); - for(RSGroupProtos.RSGroupInfo entry : resp) { - result.add(ProtobufUtil.toGroupInfo(entry)); - } - return result; - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - @Override - public RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException { - GetRSGroupInfoOfServerRequest request = GetRSGroupInfoOfServerRequest.newBuilder() - .setServer(HBaseProtos.ServerName.newBuilder() - .setHostName(hostPort.getHostname()) - .setPort(hostPort.getPort()) - .build()) - .build(); - try { - GetRSGroupInfoOfServerResponse resp = stub.getRSGroupInfoOfServer(null, request); - if (resp.hasRSGroupInfo()) { - return ProtobufUtil.toGroupInfo(resp.getRSGroupInfo()); - } - return null; - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - public void moveServersAndTables(Set
servers, Set tables, String targetGroup) - throws IOException { - MoveServersAndTablesRequest.Builder builder = - MoveServersAndTablesRequest.newBuilder().setTargetGroup(targetGroup); - for(Address el: servers) { - builder.addServers(HBaseProtos.ServerName.newBuilder() - .setHostName(el.getHostname()) - .setPort(el.getPort()) - .build()); - } - for(TableName tableName: tables) { - builder.addTableName(ProtobufUtil.toProtoTableName(tableName)); - if (!admin.tableExists(tableName)) { - throw new TableNotFoundException(tableName); - } - } - try { - stub.moveServersAndTables(null, builder.build()); - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } - - @Override - public void removeServers(Set
servers) throws IOException { - Set hostPorts = Sets.newHashSet(); - for(Address el: servers) { - hostPorts.add(HBaseProtos.ServerName.newBuilder() - .setHostName(el.getHostname()) - .setPort(el.getPort()) - .build()); - } - RemoveServersRequest request = RemoveServersRequest.newBuilder() - .addAllServers(hostPorts) - .build(); - try { - stub.removeServers(null, request); - } catch (ServiceException e) { - throw ProtobufUtil.handleRemoteException(e); - } - } -} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java index 0bde67b77596..02ef13c1a232 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminEndpoint.java @@ -17,9 +17,7 @@ */ package org.apache.hadoop.hbase.rsgroup; -import com.google.protobuf.Service; import java.io.IOException; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -46,8 +44,6 @@ import org.apache.hadoop.hbase.security.access.AccessChecker; import org.apache.yetus.audience.InterfaceAudience; -import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; - // TODO: Encapsulate MasterObserver functions into separate subclass. @CoreCoprocessor @InterfaceAudience.Private @@ -55,9 +51,6 @@ public class RSGroupAdminEndpoint implements MasterCoprocessor, MasterObserver { // Only instance of RSGroupInfoManager. RSGroup aware load balancers ask for this instance on // their setup. private MasterServices master; - private RSGroupInfoManager groupInfoManager; - private RSGroupAdminServer groupAdminServer; - private RSGroupAdminServiceImpl groupAdminService = new RSGroupAdminServiceImpl(); @Override public void start(CoprocessorEnvironment env) throws IOException { @@ -66,41 +59,24 @@ public void start(CoprocessorEnvironment env) throws IOException { } master = ((HasMasterServices) env).getMasterServices(); - groupInfoManager = master.getRSRSGroupInfoManager(); - groupAdminServer = new RSGroupAdminServer(master, groupInfoManager); Class clazz = master.getConfiguration().getClass(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, null); if (!RSGroupableBalancer.class.isAssignableFrom(clazz)) { throw new IOException("Configured balancer does not support RegionServer groups."); } - AccessChecker accessChecker = ((HasMasterServices) env).getMasterServices().getAccessChecker(); - - // set the user-provider. - UserProvider userProvider = UserProvider.instantiate(env.getConfiguration()); - groupAdminService.initialize(master, groupAdminServer, accessChecker, userProvider); } @Override public void stop(CoprocessorEnvironment env) { } - @Override - public Iterable getServices() { - return Collections.singleton(groupAdminService); - } - @Override public Optional getMasterObserver() { return Optional.of(this); } RSGroupInfoManager getGroupInfoManager() { - return groupInfoManager; - } - - @VisibleForTesting - RSGroupAdminServiceImpl getGroupAdminService() { - return groupAdminService; + return master.getRSRSGroupInfoManager(); } ///////////////////////////////////////////////////////////////////////////// @@ -114,7 +90,7 @@ public void postClearDeadServers(ObserverContext c servers.stream().filter(server -> !notClearedServers.contains(server)) .map(ServerName::getAddress).collect(Collectors.toSet()); if (!clearedServer.isEmpty()) { - groupAdminServer.removeServers(clearedServer); + master.getRSRSGroupInfoManager().removeServers(clearedServer); } } @@ -122,7 +98,7 @@ private RSGroupInfo checkGroupExists(Optional optGroupName, Supplier servers) throws ConstraintException { - // This uglyness is because we only have Address, not ServerName. - // Online servers are keyed by ServerName. - Set
onlineServers = new HashSet<>(); - for(ServerName server: master.getServerManager().getOnlineServers().keySet()) { - onlineServers.add(server.getAddress()); - } - for (Address address: servers) { - if (!onlineServers.contains(address)) { - throw new ConstraintException( - "Server " + address + " is not an online server in 'default' RSGroup."); - } - } - } - - /** - * Check passed name. Fail if nulls or if corresponding RSGroupInfo not found. - * @return The RSGroupInfo named name - */ - private RSGroupInfo getAndCheckRSGroupInfo(String name) throws IOException { - if (StringUtils.isEmpty(name)) { - throw new ConstraintException("RSGroup cannot be null."); - } - RSGroupInfo rsGroupInfo = getRSGroupInfo(name); - if (rsGroupInfo == null) { - throw new ConstraintException("RSGroup does not exist: " + name); - } - return rsGroupInfo; - } - - /** - * @return List of Regions associated with this server. - */ - private List getRegions(final Address server) { - LinkedList regions = new LinkedList<>(); - for (Map.Entry el : - master.getAssignmentManager().getRegionStates().getRegionAssignments().entrySet()) { - if (el.getValue() == null) { - continue; - } - - if (el.getValue().getAddress().equals(server)) { - addRegion(regions, el.getKey()); - } - } - for (RegionStateNode state : master.getAssignmentManager().getRegionsInTransition()) { - if (state.getRegionLocation() != null && - state.getRegionLocation().getAddress().equals(server)) { - addRegion(regions, state.getRegionInfo()); - } - } - return regions; - } - - private void addRegion(final LinkedList regions, RegionInfo hri) { - // If meta, move it last otherwise other unassigns fail because meta is not - // online for them to update state in. This is dodgy. Needs to be made more - // robust. See TODO below. - if (hri.isMetaRegion()) { - regions.addLast(hri); - } else { - regions.addFirst(hri); - } - } - - /** - * Move every region from servers which are currently located on these servers, but should not be - * located there. - * @param servers the servers that will move to new group - * @param targetGroupName the target group name - * @throws IOException if moving the server and tables fail - */ - private void moveServerRegionsFromGroup(Set
servers, String targetGroupName) - throws IOException { - moveRegionsBetweenGroups(servers, targetGroupName, rs -> getRegions(rs), info -> { - try { - String groupName = RSGroupUtil.getRSGroupInfo(master, rsGroupInfoManager, info.getTable()) - .map(RSGroupInfo::getName).orElse(RSGroupInfo.DEFAULT_GROUP); - return groupName.equals(targetGroupName); - } catch (IOException e) { - LOG.warn("Failed to test group for region {} and target group {}", info, targetGroupName); - return false; - } - }, rs -> rs.getHostname()); - } - - private void moveRegionsBetweenGroups(Set regionsOwners, String targetGroupName, - Function> getRegionsInfo, Function validation, - Function getOwnerName) throws IOException { - boolean hasRegionsToMove; - int retry = 0; - Set allOwners = new HashSet<>(regionsOwners); - Set failedRegions = new HashSet<>(); - IOException toThrow = null; - do { - hasRegionsToMove = false; - for (Iterator iter = allOwners.iterator(); iter.hasNext(); ) { - T owner = iter.next(); - // Get regions that are associated with this server and filter regions by group tables. - for (RegionInfo region : getRegionsInfo.apply(owner)) { - if (!validation.apply(region)) { - LOG.info("Moving region {}, which do not belong to RSGroup {}", - region.getShortNameToLog(), targetGroupName); - try { - this.master.getAssignmentManager().move(region); - failedRegions.remove(region.getRegionNameAsString()); - } catch (IOException ioe) { - LOG.debug("Move region {} from group failed, will retry, current retry time is {}", - region.getShortNameToLog(), retry, ioe); - toThrow = ioe; - failedRegions.add(region.getRegionNameAsString()); - } - if (master.getAssignmentManager().getRegionStates(). - getRegionState(region).isFailedOpen()) { - continue; - } - hasRegionsToMove = true; - } - } - - if (!hasRegionsToMove) { - LOG.info("No more regions to move from {} to RSGroup", getOwnerName.apply(owner)); - iter.remove(); - } - } - - retry++; - try { - rsGroupInfoManager.wait(1000); - } catch (InterruptedException e) { - LOG.warn("Sleep interrupted", e); - Thread.currentThread().interrupt(); - } - } while (hasRegionsToMove && retry <= moveMaxRetry); - - //has up to max retry time or there are no more regions to move - if (hasRegionsToMove) { - // print failed moved regions, for later process conveniently - String msg = String - .format("move regions for group %s failed, failed regions: %s", targetGroupName, - failedRegions); - LOG.error(msg); - throw new DoNotRetryIOException( - msg + ", just record the last failed region's cause, more details in server log", - toThrow); - } - } - - @Override - public void moveServers(Set
servers, String targetGroupName) throws IOException { - if (servers == null) { - throw new ConstraintException("The list of servers to move cannot be null."); - } - if (servers.isEmpty()) { - // For some reason this difference between null servers and isEmpty is important distinction. - // TODO. Why? Stuff breaks if I equate them. - return; - } - //check target group - getAndCheckRSGroupInfo(targetGroupName); - - // Hold a lock on the manager instance while moving servers to prevent - // another writer changing our state while we are working. - synchronized (rsGroupInfoManager) { - // Presume first server's source group. Later ensure all servers are from this group. - Address firstServer = servers.iterator().next(); - RSGroupInfo srcGrp = rsGroupInfoManager.getRSGroupOfServer(firstServer); - if (srcGrp == null) { - // Be careful. This exception message is tested for in TestRSGroupsBase... - throw new ConstraintException("Source RSGroup for server " + firstServer - + " does not exist."); - } - // Only move online servers (when moving from 'default') or servers from other - // groups. This prevents bogus servers from entering groups - if (RSGroupInfo.DEFAULT_GROUP.equals(srcGrp.getName())) { - if (srcGrp.getServers().size() <= servers.size()) { - throw new ConstraintException(KEEP_ONE_SERVER_IN_DEFAULT_ERROR_MESSAGE); - } - checkOnlineServersOnly(servers); - } - // Ensure all servers are of same rsgroup. - for (Address server: servers) { - String tmpGroup = rsGroupInfoManager.getRSGroupOfServer(server).getName(); - if (!tmpGroup.equals(srcGrp.getName())) { - throw new ConstraintException("Move server request should only come from one source " + - "RSGroup. Expecting only " + srcGrp.getName() + " but contains " + tmpGroup); - } - } - if (srcGrp.getServers().size() <= servers.size()) { - // check if there are still tables reference this group - for (TableDescriptor td : master.getTableDescriptors().getAll().values()) { - Optional optGroupName = td.getRegionServerGroup(); - if (optGroupName.isPresent() && optGroupName.get().equals(srcGrp.getName())) { - throw new ConstraintException( - "Cannot leave a RSGroup " + srcGrp.getName() + " that contains tables('" + - td.getTableName() + "' at least) without servers to host them."); - } - } - } - - // MovedServers may be < passed in 'servers'. - Set
movedServers = rsGroupInfoManager.moveServers(servers, srcGrp.getName(), - targetGroupName); - moveServerRegionsFromGroup(movedServers, targetGroupName); - LOG.info("Move servers done: {} => {}", srcGrp.getName(), targetGroupName); - } - } - - @Override - public void addRSGroup(String name) throws IOException { - rsGroupInfoManager.addRSGroup(new RSGroupInfo(name)); - } - - @Override - public void removeRSGroup(String name) throws IOException { - // Hold a lock on the manager instance while moving servers to prevent - // another writer changing our state while we are working. - synchronized (rsGroupInfoManager) { - RSGroupInfo rsGroupInfo = rsGroupInfoManager.getRSGroup(name); - if (rsGroupInfo == null) { - throw new ConstraintException("RSGroup " + name + " does not exist"); - } - int serverCount = rsGroupInfo.getServers().size(); - if (serverCount > 0) { - throw new ConstraintException("RSGroup " + name + " has " + serverCount + - " servers; you must remove these servers from the RSGroup before" + - " the RSGroup can be removed."); - } - for (TableDescriptor td : master.getTableDescriptors().getAll().values()) { - if (td.getRegionServerGroup().map(name::equals).orElse(false)) { - throw new ConstraintException("RSGroup " + name + " is already referenced by " + - td.getTableName() + "; you must remove all the tables from the rsgroup before " + - "the rsgroup can be removed."); - } - } - for (NamespaceDescriptor ns : master.getClusterSchema().getNamespaces()) { - String nsGroup = ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); - if (nsGroup != null && nsGroup.equals(name)) { - throw new ConstraintException( - "RSGroup " + name + " is referenced by namespace: " + ns.getName()); - } - } - rsGroupInfoManager.removeRSGroup(name); - } - } - - @Override - public boolean balanceRSGroup(String groupName) throws IOException { - ServerManager serverManager = master.getServerManager(); - LoadBalancer balancer = master.getLoadBalancer(); - - synchronized (balancer) { - // If balance not true, don't run balancer. - if (!((HMaster) master).isBalancerOn()) { - return false; - } - - if (getRSGroupInfo(groupName) == null) { - throw new ConstraintException("RSGroup does not exist: " + groupName); - } - // Only allow one balance run at at time. - Map groupRIT = rsGroupGetRegionsInTransition(groupName); - if (groupRIT.size() > 0) { - LOG.debug("Not running balancer because {} region(s) in transition: {}", groupRIT.size(), - StringUtils.abbreviate( - master.getAssignmentManager().getRegionStates().getRegionsInTransition().toString(), - 256)); - return false; - } - if (serverManager.areDeadServersInProgress()) { - LOG.debug("Not running balancer because processing dead regionserver(s): {}", - serverManager.getDeadServers()); - return false; - } - - // We balance per group instead of per table - List plans = new ArrayList<>(); - Map>> assignmentsByTable = - getRSGroupAssignmentsByTable(groupName); - for (Map.Entry>> tableMap : assignmentsByTable - .entrySet()) { - LOG.info("Creating partial plan for table {} : {}", tableMap.getKey(), tableMap.getValue()); - List partialPlans = balancer.balanceCluster(tableMap.getValue()); - LOG.info("Partial plan for table {} : {}", tableMap.getKey(), partialPlans); - if (partialPlans != null) { - plans.addAll(partialPlans); - } - } - boolean balancerRan = !plans.isEmpty(); - if (balancerRan) { - LOG.info("RSGroup balance {} starting with plan count: {}", groupName, plans.size()); - master.executeRegionPlansWithThrottling(plans); - LOG.info("RSGroup balance " + groupName + " completed"); - } - return balancerRan; - } - } - - @Override - public List listRSGroups() throws IOException { - return rsGroupInfoManager.listRSGroups(); - } - - @Override - public RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException { - return rsGroupInfoManager.getRSGroupOfServer(hostPort); - } - - @Override - public void removeServers(Set
servers) throws IOException { - if (servers == null || servers.isEmpty()) { - throw new ConstraintException("The set of servers to remove cannot be null or empty."); - } - // Hold a lock on the manager instance while moving servers to prevent - // another writer changing our state while we are working. - synchronized (rsGroupInfoManager) { - // check the set of servers - checkForDeadOrOnlineServers(servers); - rsGroupInfoManager.removeServers(servers); - LOG.info("Remove decommissioned servers {} from RSGroup done", servers); - } - } - - private boolean isTableInGroup(TableName tableName, String groupName, - Set tablesInGroupCache) throws IOException { - if (tablesInGroupCache.contains(tableName)) { - return true; - } - if (RSGroupUtil.getRSGroupInfo(master, rsGroupInfoManager, tableName).map(RSGroupInfo::getName) - .orElse(RSGroupInfo.DEFAULT_GROUP).equals(groupName)) { - tablesInGroupCache.add(tableName); - return true; - } - return false; - } - - private Map rsGroupGetRegionsInTransition(String groupName) - throws IOException { - Map rit = Maps.newTreeMap(); - Set tablesInGroupCache = new HashSet<>(); - for (RegionStateNode regionNode : master.getAssignmentManager().getRegionsInTransition()) { - TableName tn = regionNode.getTable(); - if (isTableInGroup(tn, groupName, tablesInGroupCache)) { - rit.put(regionNode.getRegionInfo().getEncodedName(), regionNode.toRegionState()); - } - } - return rit; - } - - private Map>> - getRSGroupAssignmentsByTable(String groupName) throws IOException { - Map>> result = Maps.newHashMap(); - Set tablesInGroupCache = new HashSet<>(); - for (Map.Entry entry : master.getAssignmentManager().getRegionStates() - .getRegionAssignments().entrySet()) { - RegionInfo region = entry.getKey(); - TableName tn = region.getTable(); - ServerName server = entry.getValue(); - if (isTableInGroup(tn, groupName, tablesInGroupCache)) { - result.computeIfAbsent(tn, k -> new HashMap<>()) - .computeIfAbsent(server, k -> new ArrayList<>()).add(region); - } - } - RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName); - for (ServerName serverName : master.getServerManager().getOnlineServers().keySet()) { - if (rsGroupInfo.containsServer(serverName.getAddress())) { - for (Map> map : result.values()) { - map.computeIfAbsent(serverName, k -> Collections.emptyList()); - } - } - } - - return result; - } - - /** - * Check if the set of servers are belong to dead servers list or online servers list. - * @param servers servers to remove - */ - private void checkForDeadOrOnlineServers(Set
servers) throws ConstraintException { - // This uglyness is because we only have Address, not ServerName. - Set
onlineServers = new HashSet<>(); - List drainingServers = master.getServerManager().getDrainingServersList(); - for (ServerName server : master.getServerManager().getOnlineServers().keySet()) { - // Only online but not decommissioned servers are really online - if (!drainingServers.contains(server)) { - onlineServers.add(server.getAddress()); - } - } - - Set
deadServers = new HashSet<>(); - for(ServerName server: master.getServerManager().getDeadServers().copyServerNames()) { - deadServers.add(server.getAddress()); - } - - for (Address address: servers) { - if (onlineServers.contains(address)) { - throw new ConstraintException( - "Server " + address + " is an online server, not allowed to remove."); - } - if (deadServers.contains(address)) { - throw new ConstraintException( - "Server " + address + " is on the dead servers list," - + " Maybe it will come back again, not allowed to remove."); - } - } - } -} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServiceImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServiceImpl.java deleted file mode 100644 index 749d3536b1ae..000000000000 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupAdminServiceImpl.java +++ /dev/null @@ -1,437 +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 com.google.protobuf.RpcCallback; -import com.google.protobuf.RpcController; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import org.apache.hadoop.hbase.HConstants; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.client.TableDescriptor; -import org.apache.hadoop.hbase.client.TableDescriptorBuilder; -import org.apache.hadoop.hbase.ipc.CoprocessorRpcUtils; -import org.apache.hadoop.hbase.ipc.RpcServer; -import org.apache.hadoop.hbase.master.MasterServices; -import org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait; -import org.apache.hadoop.hbase.net.Address; -import org.apache.hadoop.hbase.procedure2.Procedure; -import org.apache.hadoop.hbase.protobuf.ProtobufUtil; -import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.AddRSGroupRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.AddRSGroupResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersAndTablesRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersAndTablesResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveServersResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveTablesRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.MoveTablesResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupResponse; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest; -import org.apache.hadoop.hbase.protobuf.generated.RSGroupAdminProtos.RemoveServersResponse; -import org.apache.hadoop.hbase.security.User; -import org.apache.hadoop.hbase.security.UserProvider; -import org.apache.hadoop.hbase.security.access.AccessChecker; -import org.apache.hadoop.hbase.security.access.Permission.Action; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting; -import org.apache.hbase.thirdparty.com.google.common.collect.Sets; - -/** - * Implementation of RSGroupAdminService defined in RSGroupAdmin.proto. This class calls - * {@link RSGroupAdminServer} for actual work, converts result to protocol buffer response, handles - * exceptions if any occurred and then calls the {@code RpcCallback} with the response. - */ -class RSGroupAdminServiceImpl extends RSGroupAdminProtos.RSGroupAdminService { - - private static final Logger LOG = LoggerFactory.getLogger(RSGroupAdminServiceImpl.class); - - private MasterServices master; - - private RSGroupAdminServer groupAdminServer; - - private AccessChecker accessChecker; - - /** Provider for mapping principal names to Users */ - private UserProvider userProvider; - - RSGroupAdminServiceImpl() { - } - - void initialize(MasterServices master, RSGroupAdminServer groupAdminServer, - AccessChecker accessChecker, UserProvider userProvider) { - this.master = master; - this.groupAdminServer = groupAdminServer; - this.accessChecker = accessChecker; - this.userProvider = userProvider; - } - - @VisibleForTesting - void checkPermission(String request) throws IOException { - accessChecker.requirePermission(getActiveUser(), request, null, Action.ADMIN); - } - - /** - * Returns the active user to which authorization checks should be applied. If we are in the - * context of an RPC call, the remote user is used, otherwise the currently logged in user is - * used. - */ - private User getActiveUser() throws IOException { - // for non-rpc handling, fallback to system user - Optional optionalUser = RpcServer.getRequestUser(); - if (optionalUser.isPresent()) { - return optionalUser.get(); - } - return userProvider.getCurrent(); - } - - // for backward compatible - private RSGroupInfo fillTables(RSGroupInfo rsGroupInfo) throws IOException { - return RSGroupUtil.fillTables(rsGroupInfo, master.getTableDescriptors().getAll().values()); - } - - @Override - public void getRSGroupInfo(RpcController controller, GetRSGroupInfoRequest request, - RpcCallback done) { - GetRSGroupInfoResponse.Builder builder = GetRSGroupInfoResponse.newBuilder(); - String groupName = request.getRSGroupName(); - LOG.info( - master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, group=" + groupName); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preGetRSGroupInfo(groupName); - } - checkPermission("getRSGroupInfo"); - RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(groupName); - if (rsGroupInfo != null) { - builder.setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(fillTables(rsGroupInfo))); - } - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postGetRSGroupInfo(groupName); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - @Override - public void getRSGroupInfoOfTable(RpcController controller, GetRSGroupInfoOfTableRequest request, - RpcCallback done) { - GetRSGroupInfoOfTableResponse.Builder builder = GetRSGroupInfoOfTableResponse.newBuilder(); - TableName tableName = ProtobufUtil.toTableName(request.getTableName()); - LOG.info( - master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, table=" + tableName); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preGetRSGroupInfoOfTable(tableName); - } - checkPermission("getRSGroupInfoOfTable"); - Optional optGroup = - RSGroupUtil.getRSGroupInfo(master, groupAdminServer.rsGroupInfoManager, tableName); - if (optGroup.isPresent()) { - builder.setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(fillTables(optGroup.get()))); - } else { - if (master.getTableStateManager().isTablePresent(tableName)) { - RSGroupInfo rsGroupInfo = groupAdminServer.getRSGroupInfo(RSGroupInfo.DEFAULT_GROUP); - builder.setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(fillTables(rsGroupInfo))); - } - } - - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postGetRSGroupInfoOfTable(tableName); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - @Override - public void moveServers(RpcController controller, MoveServersRequest request, - RpcCallback done) { - MoveServersResponse.Builder builder = MoveServersResponse.newBuilder(); - Set
hostPorts = Sets.newHashSet(); - for (HBaseProtos.ServerName el : request.getServersList()) { - hostPorts.add(Address.fromParts(el.getHostName(), el.getPort())); - } - LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts + " to rsgroup " + - request.getTargetGroup()); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preMoveServers(hostPorts, request.getTargetGroup()); - } - checkPermission("moveServers"); - groupAdminServer.moveServers(hostPorts, request.getTargetGroup()); - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postMoveServers(hostPorts, request.getTargetGroup()); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - private void moveTablesAndWait(Set tables, String targetGroup) throws IOException { - List procIds = new ArrayList(); - for (TableName tableName : tables) { - TableDescriptor oldTd = master.getTableDescriptors().get(tableName); - if (oldTd == null) { - continue; - } - TableDescriptor newTd = - TableDescriptorBuilder.newBuilder(oldTd).setRegionServerGroup(targetGroup).build(); - procIds.add(master.modifyTable(tableName, newTd, HConstants.NO_NONCE, HConstants.NO_NONCE)); - } - for (long procId : procIds) { - Procedure proc = master.getMasterProcedureExecutor().getProcedure(procId); - if (proc == null) { - continue; - } - ProcedureSyncWait.waitForProcedureToCompleteIOE(master.getMasterProcedureExecutor(), proc, - Long.MAX_VALUE); - } - } - - @Override - public void moveTables(RpcController controller, MoveTablesRequest request, - RpcCallback done) { - MoveTablesResponse.Builder builder = MoveTablesResponse.newBuilder(); - Set tables = new HashSet<>(request.getTableNameList().size()); - for (HBaseProtos.TableName tableName : request.getTableNameList()) { - tables.add(ProtobufUtil.toTableName(tableName)); - } - LOG.info(master.getClientIdAuditPrefix() + " move tables " + tables + " to rsgroup " + - request.getTargetGroup()); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preMoveTables(tables, request.getTargetGroup()); - } - checkPermission("moveTables"); - moveTablesAndWait(tables, request.getTargetGroup()); - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postMoveTables(tables, request.getTargetGroup()); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - @Override - public void addRSGroup(RpcController controller, AddRSGroupRequest request, - RpcCallback done) { - AddRSGroupResponse.Builder builder = AddRSGroupResponse.newBuilder(); - LOG.info(master.getClientIdAuditPrefix() + " add rsgroup " + request.getRSGroupName()); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preAddRSGroup(request.getRSGroupName()); - } - checkPermission("addRSGroup"); - groupAdminServer.addRSGroup(request.getRSGroupName()); - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postAddRSGroup(request.getRSGroupName()); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - @Override - public void removeRSGroup(RpcController controller, RemoveRSGroupRequest request, - RpcCallback done) { - RemoveRSGroupResponse.Builder builder = RemoveRSGroupResponse.newBuilder(); - LOG.info(master.getClientIdAuditPrefix() + " remove rsgroup " + request.getRSGroupName()); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preRemoveRSGroup(request.getRSGroupName()); - } - checkPermission("removeRSGroup"); - groupAdminServer.removeRSGroup(request.getRSGroupName()); - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postRemoveRSGroup(request.getRSGroupName()); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - @Override - public void balanceRSGroup(RpcController controller, BalanceRSGroupRequest request, - RpcCallback done) { - BalanceRSGroupResponse.Builder builder = BalanceRSGroupResponse.newBuilder(); - LOG.info( - master.getClientIdAuditPrefix() + " balance rsgroup, group=" + request.getRSGroupName()); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preBalanceRSGroup(request.getRSGroupName()); - } - checkPermission("balanceRSGroup"); - boolean balancerRan = groupAdminServer.balanceRSGroup(request.getRSGroupName()); - builder.setBalanceRan(balancerRan); - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postBalanceRSGroup(request.getRSGroupName(), balancerRan); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - builder.setBalanceRan(false); - } - done.run(builder.build()); - } - - @Override - public void listRSGroupInfos(RpcController controller, ListRSGroupInfosRequest request, - RpcCallback done) { - ListRSGroupInfosResponse.Builder builder = ListRSGroupInfosResponse.newBuilder(); - LOG.info(master.getClientIdAuditPrefix() + " list rsgroup"); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preListRSGroups(); - } - checkPermission("listRSGroup"); - List rsGroupInfos = groupAdminServer.listRSGroups().stream() - .map(RSGroupInfo::new).collect(Collectors.toList()); - Map name2Info = new HashMap<>(); - for (RSGroupInfo rsGroupInfo : rsGroupInfos) { - name2Info.put(rsGroupInfo.getName(), rsGroupInfo); - } - for (TableDescriptor td : master.getTableDescriptors().getAll().values()) { - String groupName = td.getRegionServerGroup().orElse(RSGroupInfo.DEFAULT_GROUP); - RSGroupInfo rsGroupInfo = name2Info.get(groupName); - if (rsGroupInfo != null) { - rsGroupInfo.addTable(td.getTableName()); - } - } - for (RSGroupInfo rsGroupInfo : rsGroupInfos) { - // TODO: this can be done at once outside this loop, do not need to scan all every time. - builder.addRSGroupInfo(ProtobufUtil.toProtoGroupInfo(rsGroupInfo)); - } - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postListRSGroups(); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - @Override - public void getRSGroupInfoOfServer(RpcController controller, - GetRSGroupInfoOfServerRequest request, RpcCallback done) { - GetRSGroupInfoOfServerResponse.Builder builder = GetRSGroupInfoOfServerResponse.newBuilder(); - Address hp = - Address.fromParts(request.getServer().getHostName(), request.getServer().getPort()); - LOG.info(master.getClientIdAuditPrefix() + " initiates rsgroup info retrieval, server=" + hp); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preGetRSGroupInfoOfServer(hp); - } - checkPermission("getRSGroupInfoOfServer"); - RSGroupInfo info = groupAdminServer.getRSGroupOfServer(hp); - if (info != null) { - builder.setRSGroupInfo(ProtobufUtil.toProtoGroupInfo(fillTables(info))); - } - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postGetRSGroupInfoOfServer(hp); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - @Override - public void moveServersAndTables(RpcController controller, MoveServersAndTablesRequest request, - RpcCallback done) { - MoveServersAndTablesResponse.Builder builder = MoveServersAndTablesResponse.newBuilder(); - Set
hostPorts = Sets.newHashSet(); - for (HBaseProtos.ServerName el : request.getServersList()) { - hostPorts.add(Address.fromParts(el.getHostName(), el.getPort())); - } - Set tables = new HashSet<>(request.getTableNameList().size()); - for (HBaseProtos.TableName tableName : request.getTableNameList()) { - tables.add(ProtobufUtil.toTableName(tableName)); - } - LOG.info(master.getClientIdAuditPrefix() + " move servers " + hostPorts + " and tables " + - tables + " to rsgroup" + request.getTargetGroup()); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preMoveServersAndTables(hostPorts, tables, - request.getTargetGroup()); - } - checkPermission("moveServersAndTables"); - groupAdminServer.moveServers(hostPorts, request.getTargetGroup()); - moveTablesAndWait(tables, request.getTargetGroup()); - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postMoveServersAndTables(hostPorts, tables, - request.getTargetGroup()); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } - - @Override - public void removeServers(RpcController controller, RemoveServersRequest request, - RpcCallback done) { - RemoveServersResponse.Builder builder = RemoveServersResponse.newBuilder(); - Set
servers = Sets.newHashSet(); - for (HBaseProtos.ServerName el : request.getServersList()) { - servers.add(Address.fromParts(el.getHostName(), el.getPort())); - } - LOG.info( - master.getClientIdAuditPrefix() + " remove decommissioned servers from rsgroup: " + servers); - try { - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().preRemoveServers(servers); - } - checkPermission("removeServers"); - groupAdminServer.removeServers(servers); - if (master.getMasterCoprocessorHost() != null) { - master.getMasterCoprocessorHost().postRemoveServers(servers); - } - } catch (IOException e) { - CoprocessorRpcUtils.setControllerException(controller, e); - } - done.run(builder.build()); - } -} \ No newline at end of file diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.java index a46fa4bcb1a2..e69ab01b4152 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.java @@ -47,12 +47,10 @@ public interface RSGroupInfoManager { /** * Move servers to a new group. * @param servers list of servers, must be part of the same group - * @param srcGroup groupName being moved from - * @param dstGroup groupName being moved to + * @param targetGroupName groupName being moved to * @return Set of servers moved (May be a subset of {@code servers}). */ - Set
moveServers(Set
servers, String srcGroup, String dstGroup) - throws IOException; + void moveServers(Set
servers, String targetGroupName) throws IOException; /** * Gets the group info of server. @@ -92,4 +90,12 @@ Set
moveServers(Set
servers, String srcGroup, String dstGroup) static RSGroupInfoManager create(MasterServices master) throws IOException { return RSGroupInfoManagerImpl.getInstance(master); } + + /** + * Balance a rs group + * @param groupName name of the group + * @return true if balancer run + * @throws IOException + */ + boolean balanceRSGroup(String groupName) throws IOException; } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.java index 67250669ea9b..e59a7bc9cf37 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.java @@ -25,9 +25,14 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Iterator; +import java.util.LinkedList; import java.util.Map; -import java.util.OptionalLong; +import java.util.Optional; import java.util.Set; +import java.util.function.Function; +import org.apache.commons.lang3.StringUtils; +import java.util.OptionalLong; import java.util.SortedSet; import java.util.TreeSet; import org.apache.hadoop.hbase.Coprocessor; @@ -44,6 +49,7 @@ import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.Mutation; import org.apache.hadoop.hbase.client.Put; +import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.TableDescriptor; @@ -51,8 +57,13 @@ import org.apache.hadoop.hbase.constraint.ConstraintException; import org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint; import org.apache.hadoop.hbase.exceptions.DeserializationException; +import org.apache.hadoop.hbase.master.assignment.RegionStateNode; +import org.apache.hadoop.hbase.master.LoadBalancer; import org.apache.hadoop.hbase.master.MasterServices; +import org.apache.hadoop.hbase.master.RegionPlan; +import org.apache.hadoop.hbase.master.RegionState; import org.apache.hadoop.hbase.master.ServerListener; +import org.apache.hadoop.hbase.master.ServerManager; import org.apache.hadoop.hbase.master.TableStateManager; import org.apache.hadoop.hbase.master.procedure.CreateTableProcedure; import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil; @@ -88,8 +99,7 @@ * persistence store for the group information. It also makes use of zookeeper to store group * information needed for bootstrapping during offline mode. *

Concurrency

RSGroup state is kept locally in Maps. There is a rsgroup name to cached - * RSGroupInfo Map at {@link #rsGroupMap} and a Map of tables to the name of the rsgroup they belong - * too (in {@link #tableMap}). These Maps are persisted to the hbase:rsgroup table (and cached in + * RSGroupInfo Map at {@link #rsGroupMap}. These Maps are persisted to the hbase:rsgroup table (and cached in * zk) on each modification. *

* Mutations on state are synchronized but reads can continue without having to wait on an instance @@ -112,6 +122,18 @@ final class RSGroupInfoManagerImpl implements RSGroupInfoManager { static final TableName RSGROUP_TABLE_NAME = TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "rsgroup"); + @VisibleForTesting + static final String KEEP_ONE_SERVER_IN_DEFAULT_ERROR_MESSAGE = "should keep at least " + + "one server in 'default' RSGroup."; + + /** Define the config key of retries threshold when movements failed */ + @VisibleForTesting + static final String FAILED_MOVE_MAX_RETRY = "hbase.rsgroup.move.max.retry"; + + /** Define the default number of retries */ + @VisibleForTesting + static final int DEFAULT_MAX_RETRY_VALUE = 50; + private static final String RS_GROUP_ZNODE = "rsgroup"; @VisibleForTesting @@ -177,14 +199,13 @@ private static final class RSGroupInfoHolder { private final ServerEventsListenerThread serverEventsListenerThread = new ServerEventsListenerThread(); - private RSGroupInfoManagerImpl(MasterServices masterServices) throws IOException { + private RSGroupInfoManagerImpl(MasterServices masterServices) { this.masterServices = masterServices; this.watcher = masterServices.getZooKeeper(); this.conn = masterServices.getAsyncClusterConnection(); this.rsGroupStartupWorker = new RSGroupStartupWorker(); } - private synchronized void init() throws IOException { refresh(false); serverEventsListenerThread.start(); @@ -192,8 +213,8 @@ private synchronized void init() throws IOException { migrate(); } - static RSGroupInfoManager getInstance(MasterServices master) throws IOException { - RSGroupInfoManagerImpl instance = new RSGroupInfoManagerImpl(master); + static RSGroupInfoManager getInstance(MasterServices masterServices) throws IOException { + RSGroupInfoManagerImpl instance = new RSGroupInfoManagerImpl(masterServices); instance.init(); return instance; } @@ -225,22 +246,21 @@ private RSGroupInfo getRSGroupInfo(final String groupName) throws DoNotRetryIOEx } /** - * @param master the master to get online servers for + * @param masterServices the masterServices to get online servers for * @return Set of online Servers named for their hostname and port (not ServerName). */ - private static Set

getOnlineServers(final MasterServices master) { + private static Set
getOnlineServers(final MasterServices masterServices) { Set
onlineServers = new HashSet
(); - if (master == null) { + if (masterServices == null) { return onlineServers; } - for (ServerName server : master.getServerManager().getOnlineServers().keySet()) { + for (ServerName server : masterServices.getServerManager().getOnlineServers().keySet()) { onlineServers.add(server.getAddress()); } return onlineServers; } - @Override public synchronized Set
moveServers(Set
servers, String srcGroup, String dstGroup) throws IOException { RSGroupInfo src = getRSGroupInfo(srcGroup); @@ -287,6 +307,27 @@ public RSGroupInfo getRSGroup(String groupName) { @Override public synchronized void removeRSGroup(String groupName) throws IOException { + RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName); + int serverCount = rsGroupInfo.getServers().size(); + if (serverCount > 0) { + throw new DoNotRetryIOException("RSGroup " + groupName + " has " + serverCount + + " servers; you must remove these servers from the RSGroup before" + + " the RSGroup can be removed."); + } + for (TableDescriptor td : masterServices.getTableDescriptors().getAll().values()) { + if (td.getRegionServerGroup().map(groupName::equals).orElse(false)) { + throw new DoNotRetryIOException("RSGroup " + groupName + " is already referenced by " + + td.getTableName() + "; you must remove all the tables from the rsgroup before " + + "the rsgroup can be removed."); + } + } + for (NamespaceDescriptor ns : masterServices.getClusterSchema().getNamespaces()) { + String nsGroup = ns.getConfigurationValue(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP); + if (nsGroup != null && nsGroup.equals(groupName)) { + throw new DoNotRetryIOException( + "RSGroup " + groupName + " is referenced by namespace: " + ns.getName()); + } + } Map rsGroupMap = holder.groupName2Group; if (!rsGroupMap.containsKey(groupName) || groupName.equals(RSGroupInfo.DEFAULT_GROUP)) { throw new DoNotRetryIOException( @@ -309,6 +350,13 @@ public boolean isOnline() { @Override public synchronized void removeServers(Set
servers) throws IOException { + if (servers == null || servers.isEmpty()) { + throw new DoNotRetryIOException("The set of servers to remove cannot be null or empty."); + } + + // check the set of servers + checkForDeadOrOnlineServers(servers); + Map rsGroupInfos = new HashMap(); for (Address el : servers) { RSGroupInfo rsGroupInfo = getRSGroupOfServer(el); @@ -331,6 +379,7 @@ public synchronized void removeServers(Set
servers) throws IOException newGroupMap.putAll(rsGroupInfos); flushConfig(newGroupMap); } + LOG.info("Remove decommissioned servers {} from RSGroup done", servers); } private List retrieveGroupListFromGroupTable() throws IOException { @@ -562,7 +611,6 @@ private synchronized void flushConfig(Map newGroupMap) thro // Make changes visible after having been persisted to the source of truth resetRSGroupMap(newGroupMap); saveRSGroupMapToZK(newGroupMap); - updateCacheOfRSGroups(newGroupMap.keySet()); } @@ -838,9 +886,341 @@ private void checkGroupName(String groupName) throws ConstraintException { } } - @Override public RSGroupInfo getRSGroupForTable(TableName tableName) throws IOException { return holder.tableName2Group.get(tableName); } + + + /** + * Check if the set of servers are belong to dead servers list or online servers list. + * @param servers servers to remove + */ + private void checkForDeadOrOnlineServers(Set
servers) throws IOException { + // This uglyness is because we only have Address, not ServerName. + Set
onlineServers = new HashSet<>(); + List drainingServers = masterServices.getServerManager().getDrainingServersList(); + for (ServerName server : masterServices.getServerManager().getOnlineServers().keySet()) { + // Only online but not decommissioned servers are really online + if (!drainingServers.contains(server)) { + onlineServers.add(server.getAddress()); + } + } + + Set
deadServers = new HashSet<>(); + for(ServerName server: masterServices.getServerManager().getDeadServers().copyServerNames()) { + deadServers.add(server.getAddress()); + } + + for (Address address: servers) { + if (onlineServers.contains(address)) { + throw new DoNotRetryIOException( + "Server " + address + " is an online server, not allowed to remove."); + } + if (deadServers.contains(address)) { + throw new DoNotRetryIOException( + "Server " + address + " is on the dead servers list," + + " Maybe it will come back again, not allowed to remove."); + } + } + } + + private void checkOnlineServersOnly(Set
servers) throws IOException { + // This uglyness is because we only have Address, not ServerName. + // Online servers are keyed by ServerName. + Set
onlineServers = new HashSet<>(); + for(ServerName server: masterServices.getServerManager().getOnlineServers().keySet()) { + onlineServers.add(server.getAddress()); + } + for (Address address: servers) { + if (!onlineServers.contains(address)) { + throw new DoNotRetryIOException("Server " + address + + " is not an online server in 'default' RSGroup."); + } + } + } + + /** + * @return List of Regions associated with this server. + */ + private List getRegions(final Address server) { + LinkedList regions = new LinkedList<>(); + for (Map.Entry el : + masterServices.getAssignmentManager().getRegionStates().getRegionAssignments().entrySet()) { + if (el.getValue() == null) { + continue; + } + + if (el.getValue().getAddress().equals(server)) { + addRegion(regions, el.getKey()); + } + } + for (RegionStateNode state : masterServices.getAssignmentManager().getRegionsInTransition()) { + if (state.getRegionLocation() != null && + state.getRegionLocation().getAddress().equals(server)) { + addRegion(regions, state.getRegionInfo()); + } + } + return regions; + } + + private void addRegion(final LinkedList regions, RegionInfo hri) { + // If meta, move it last otherwise other unassigns fail because meta is not + // online for them to update state in. This is dodgy. Needs to be made more + // robust. See TODO below. + if (hri.isMetaRegion()) { + regions.addLast(hri); + } else { + regions.addFirst(hri); + } + } + + /** + * Move every region from servers which are currently located on these servers, but should not be + * located there. + * @param servers the servers that will move to new group + * @param targetGroupName the target group name + * @throws IOException if moving the server and tables fail + */ + private void moveServerRegionsFromGroup(Set
servers, String targetGroupName) + throws IOException { + moveRegionsBetweenGroups(servers, targetGroupName, rs -> getRegions(rs), info -> { + try { + String groupName = RSGroupUtil.getRSGroupInfo(masterServices, this, info.getTable()) + .map(RSGroupInfo::getName).orElse(RSGroupInfo.DEFAULT_GROUP); + return groupName.equals(targetGroupName); + } catch (IOException e) { + LOG.warn("Failed to test group for region {} and target group {}", info, targetGroupName); + return false; + } + }, rs -> rs.getHostname()); + } + + private void moveRegionsBetweenGroups(Set regionsOwners, String targetGroupName, + Function> getRegionsInfo, Function validation, + Function getOwnerName) throws IOException { + boolean hasRegionsToMove; + int retry = 0; + Set allOwners = new HashSet<>(regionsOwners); + Set failedRegions = new HashSet<>(); + IOException toThrow = null; + do { + hasRegionsToMove = false; + for (Iterator iter = allOwners.iterator(); iter.hasNext(); ) { + T owner = iter.next(); + // Get regions that are associated with this server and filter regions by group tables. + for (RegionInfo region : getRegionsInfo.apply(owner)) { + if (!validation.apply(region)) { + LOG.info("Moving region {}, which do not belong to RSGroup {}", + region.getShortNameToLog(), targetGroupName); + try { + this.masterServices.getAssignmentManager().move(region); + failedRegions.remove(region.getRegionNameAsString()); + } catch (IOException ioe) { + LOG.debug("Move region {} from group failed, will retry, current retry time is {}", + region.getShortNameToLog(), retry, ioe); + toThrow = ioe; + failedRegions.add(region.getRegionNameAsString()); + } + if (masterServices.getAssignmentManager().getRegionStates(). + getRegionState(region).isFailedOpen()) { + continue; + } + hasRegionsToMove = true; + } + } + + if (!hasRegionsToMove) { + LOG.info("No more regions to move from {} to RSGroup", getOwnerName.apply(owner)); + iter.remove(); + } + } + + retry++; + try { + wait(1000); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted", e); + Thread.currentThread().interrupt(); + } + } while (hasRegionsToMove && retry <= masterServices.getConfiguration().getInt( + "hbase.rsgroup.move.max.retry", 50)); + + //has up to max retry time or there are no more regions to move + if (hasRegionsToMove) { + // print failed moved regions, for later process conveniently + String msg = String + .format("move regions for group %s failed, failed regions: %s", targetGroupName, + failedRegions); + LOG.error(msg); + throw new DoNotRetryIOException( + msg + ", just record the last failed region's cause, more details in server log", + toThrow); + } + } + + private boolean isTableInGroup(TableName tableName, String groupName, + Set tablesInGroupCache) throws IOException { + if (tablesInGroupCache.contains(tableName)) { + return true; + } + if (RSGroupUtil.getRSGroupInfo(masterServices, this, tableName).map(RSGroupInfo::getName) + .orElse(RSGroupInfo.DEFAULT_GROUP).equals(groupName)) { + tablesInGroupCache.add(tableName); + return true; + } + return false; + } + + private Map rsGroupGetRegionsInTransition(String groupName) + throws IOException { + Map rit = Maps.newTreeMap(); + Set tablesInGroupCache = new HashSet<>(); + for (RegionStateNode regionNode : masterServices.getAssignmentManager().getRegionsInTransition()) { + TableName tn = regionNode.getTable(); + if (isTableInGroup(tn, groupName, tablesInGroupCache)) { + rit.put(regionNode.getRegionInfo().getEncodedName(), regionNode.toRegionState()); + } + } + return rit; + } + + private Map>> + getRSGroupAssignmentsByTable(String groupName) throws IOException { + Map>> result = Maps.newHashMap(); + Set tablesInGroupCache = new HashSet<>(); + for (Map.Entry entry : masterServices.getAssignmentManager().getRegionStates() + .getRegionAssignments().entrySet()) { + RegionInfo region = entry.getKey(); + TableName tn = region.getTable(); + ServerName server = entry.getValue(); + if (isTableInGroup(tn, groupName, tablesInGroupCache)) { + result.computeIfAbsent(tn, k -> new HashMap<>()) + .computeIfAbsent(server, k -> new ArrayList<>()).add(region); + } + } + RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName); + for (ServerName serverName : masterServices.getServerManager().getOnlineServers().keySet()) { + if (rsGroupInfo.containsServer(serverName.getAddress())) { + for (Map> map : result.values()) { + map.computeIfAbsent(serverName, k -> Collections.emptyList()); + } + } + } + + return result; + } + + @Override + public boolean balanceRSGroup(String groupName) throws IOException { + ServerManager serverManager = masterServices.getServerManager(); + LoadBalancer balancer = masterServices.getLoadBalancer(); + getRSGroupInfo(groupName); + + synchronized (balancer) { + // If balance not true, don't run balancer. + if (!masterServices.isBalancerOn()) { + return false; + } + // Only allow one balance run at at time. + Map groupRIT = rsGroupGetRegionsInTransition(groupName); + if (groupRIT.size() > 0) { + LOG.debug("Not running balancer because {} region(s) in transition: {}", groupRIT.size(), + StringUtils.abbreviate( + masterServices.getAssignmentManager().getRegionStates().getRegionsInTransition().toString(), + 256)); + return false; + } + if (serverManager.areDeadServersInProgress()) { + LOG.debug("Not running balancer because processing dead regionserver(s): {}", + serverManager.getDeadServers()); + return false; + } + + // We balance per group instead of per table + List plans = new ArrayList<>(); + Map>> assignmentsByTable = + getRSGroupAssignmentsByTable(groupName); + for (Map.Entry>> tableMap : assignmentsByTable + .entrySet()) { + LOG.info("Creating partial plan for table {} : {}", tableMap.getKey(), tableMap.getValue()); + List partialPlans = balancer.balanceCluster(tableMap.getValue()); + LOG.info("Partial plan for table {} : {}", tableMap.getKey(), partialPlans); + if (partialPlans != null) { + plans.addAll(partialPlans); + } + } + boolean balancerRan = !plans.isEmpty(); + if (balancerRan) { + LOG.info("RSGroup balance {} starting with plan count: {}", groupName, plans.size()); + masterServices.executeRegionPlansWithThrottling(plans); + LOG.info("RSGroup balance " + groupName + " completed"); + } + return balancerRan; + } + } + + public void moveServers(Set
servers, String targetGroupName) throws IOException { + if (servers == null) { + throw new DoNotRetryIOException("The list of servers to move cannot be null."); + } + if (servers.isEmpty()) { + // For some reason this difference between null servers and isEmpty is important distinction. + // TODO. Why? Stuff breaks if I equate them. + return; + } + if (StringUtils.isEmpty(targetGroupName)) { + throw new DoNotRetryIOException("RSGroup cannot be null."); + } + getRSGroupInfo(targetGroupName); + + // Hold a lock on the manager instance while moving servers to prevent + // another writer changing our state while we are working. + synchronized (this) { + // Presume first server's source group. Later ensure all servers are from this group. + Address firstServer = servers.iterator().next(); + RSGroupInfo srcGrp = getRSGroupOfServer(firstServer); + if (srcGrp == null) { + // Be careful. This exception message is tested for in TestRSGroupsBase... + throw new DoNotRetryIOException("Source RSGroup for server " + firstServer + + " does not exist."); + } + + // Only move online servers (when moving from 'default') or servers from other + // groups. This prevents bogus servers from entering groups + if (RSGroupInfo.DEFAULT_GROUP.equals(srcGrp.getName())) { + if (srcGrp.getServers().size() <= servers.size()) { + throw new DoNotRetryIOException("should keep at least " + + "one server in 'default' RSGroup."); + } + checkOnlineServersOnly(servers); + } + // Ensure all servers are of same rsgroup. + for (Address server: servers) { + String tmpGroup = getRSGroupOfServer(server).getName(); + if (!tmpGroup.equals(srcGrp.getName())) { + throw new DoNotRetryIOException("Move server request should only come from one source " + + "RSGroup. Expecting only " + srcGrp.getName() + " but contains " + tmpGroup); + } + } + if (srcGrp.getServers().size() <= servers.size()) { + // check if there are still tables reference this group + for (TableDescriptor td : masterServices.getTableDescriptors().getAll().values()) { + Optional optGroupName = td.getRegionServerGroup(); + if (optGroupName.isPresent() && optGroupName.get().equals(srcGrp.getName())) { + throw new DoNotRetryIOException( + "Cannot leave a RSGroup " + srcGrp.getName() + " that contains tables('" + + td.getTableName() + "' at least) without servers to host them."); + } + } + } + + // MovedServers may be < passed in 'servers'. + Set
movedServers = moveServers(servers, srcGrp.getName(), + targetGroupName); + moveServerRegionsFromGroup(movedServers, targetGroupName); + LOG.info("Move servers done: {} => {}", srcGrp.getName(), targetGroupName); + } + } + } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupMajorCompactionTTL.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupMajorCompactionTTL.java index d1b375181ccb..a77d6b0588de 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupMajorCompactionTTL.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupMajorCompactionTTL.java @@ -21,6 +21,7 @@ import java.util.Arrays; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HBaseInterfaceAudience; import org.apache.hadoop.hbase.TableName; @@ -58,9 +59,9 @@ public int compactTTLRegionsOnGroup(Configuration conf, String rsgroup, int conc throws Exception { Connection conn = ConnectionFactory.createConnection(conf); - RSGroupAdmin rsGroupAdmin = new RSGroupAdminClient(conn); + Admin admin = conn.getAdmin(); - RSGroupInfo rsGroupInfo = rsGroupAdmin.getRSGroupInfo(rsgroup); + RSGroupInfo rsGroupInfo = admin.getRSGroupInfo(rsgroup); if (rsGroupInfo == null) { LOG.error("Invalid rsgroup specified: " + rsgroup); throw new IllegalArgumentException("Invalid rsgroup specified: " + rsgroup); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupUtil.java index af30049fd33d..1e6799cda0ab 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupUtil.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/rsgroup/RSGroupUtil.java @@ -27,7 +27,7 @@ * Helper class for RSGroup implementation */ @InterfaceAudience.Private -final class RSGroupUtil { +public final class RSGroupUtil { private static final Logger LOG = LoggerFactory.getLogger(RSGroupUtil.class); @@ -38,7 +38,7 @@ private RSGroupUtil() { * Will try to get the rsgroup from {@link TableDescriptor} first, and then try to get the rsgroup * from the {@link NamespaceDescriptor}. If still not present, return empty. */ - static Optional getRSGroupInfo(MasterServices master, RSGroupInfoManager manager, + public static Optional getRSGroupInfo(MasterServices master, RSGroupInfoManager manager, TableName tableName) throws IOException { TableDescriptor td = master.getTableDescriptors().get(tableName); if (td == null) { @@ -79,7 +79,7 @@ static Optional getRSGroupInfo(MasterServices master, RSGroupInfoMa * Fill the tables field for {@link RSGroupInfo}, for backward compatibility. */ @SuppressWarnings("deprecation") - static RSGroupInfo fillTables(RSGroupInfo rsGroupInfo, Collection tds) { + public static RSGroupInfo fillTables(RSGroupInfo rsGroupInfo, Collection tds) { RSGroupInfo newRsGroupInfo = new RSGroupInfo(rsGroupInfo); Predicate filter; if (rsGroupInfo.getName().equals(RSGroupInfo.DEFAULT_GROUP)) { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java index 26772ae94233..a095d900b429 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/MockNoopMasterServices.java @@ -496,4 +496,9 @@ public AsyncClusterConnection getAsyncClusterConnection() { public RSGroupInfoManager getRSRSGroupInfoManager() { return null; } + + @Override + public boolean isBalancerOn() { + return false; + } } \ No newline at end of file diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdminClient.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdminClient.java index 28131a9fee82..82c4b514df57 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdminClient.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/rsgroup/VerifyingRSGroupAdminClient.java @@ -54,14 +54,14 @@ import org.apache.hbase.thirdparty.com.google.common.collect.Sets; @InterfaceAudience.Private -public class VerifyingRSGroupAdminClient extends RSGroupAdminClient { +public class VerifyingRSGroupAdminClient implements Admin { private Connection conn; private ZKWatcher zkw; - private RSGroupAdminClient wrapped; + private Admin wrapped; - public VerifyingRSGroupAdminClient(RSGroupAdminClient RSGroupAdmin, Configuration conf) + public VerifyingRSGroupAdminClient(Admin admin, Configuration conf) throws IOException { - wrapped = RSGroupAdmin; + wrapped = admin; conn = ConnectionFactory.createConnection(conf); zkw = new ZKWatcher(conf, this.getClass().getSimpleName(), null); } @@ -73,24 +73,894 @@ public void addRSGroup(String groupName) throws IOException { } @Override - public RSGroupInfo getRSGroupInfo(String groupName) throws IOException { - return wrapped.getRSGroupInfo(groupName); + public int getOperationTimeout() { + return 0; } @Override - public RSGroupInfo getRSGroupInfoOfTable(TableName tableName) throws IOException { - return wrapped.getRSGroupInfoOfTable(tableName); + public int getSyncWaitTimeout() { + return 0; } @Override - public void moveServers(Set
servers, String targetGroup) throws IOException { - wrapped.moveServers(servers, targetGroup); - verify(); + public void abort(String why, Throwable e) { + + } + + @Override + public boolean isAborted() { + return false; + } + + @Override + public org.apache.hadoop.hbase.client.Connection getConnection() { + return null; + } + + @Override + public boolean tableExists(org.apache.hadoop.hbase.TableName tableName) + throws java.io.IOException { + return false; + } + + @Override + public java.util.List listTableDescriptors() + throws java.io.IOException { + return null; + } + + @Override + public java.util.List listTableDescriptors( + java.util.regex.Pattern pattern, boolean includeSysTables) throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.TableName[] listTableNames() throws java.io.IOException { + return new org.apache.hadoop.hbase.TableName[0]; + } + + @Override + public org.apache.hadoop.hbase.TableName[] listTableNames(java.util.regex.Pattern pattern, + boolean includeSysTables) throws java.io.IOException { + return new org.apache.hadoop.hbase.TableName[0]; + } + + @Override + public org.apache.hadoop.hbase.client.TableDescriptor getDescriptor( + org.apache.hadoop.hbase.TableName tableName) + throws org.apache.hadoop.hbase.TableNotFoundException, java.io.IOException { + return null; + } + + @Override + public void createTable(org.apache.hadoop.hbase.client.TableDescriptor desc, byte[] startKey, + byte[] endKey, int numRegions) throws java.io.IOException { + + } + + @Override + public java.util.concurrent.Future createTableAsync( + org.apache.hadoop.hbase.client.TableDescriptor desc) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future createTableAsync( + org.apache.hadoop.hbase.client.TableDescriptor desc, byte[][] splitKeys) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future deleteTableAsync( + org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future truncateTableAsync( + org.apache.hadoop.hbase.TableName tableName, boolean preserveSplits) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future enableTableAsync( + org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future disableTableAsync( + org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + return null; + } + + @Override + public boolean isTableEnabled(org.apache.hadoop.hbase.TableName tableName) + throws java.io.IOException { + return false; + } + + @Override + public boolean isTableDisabled(org.apache.hadoop.hbase.TableName tableName) + throws java.io.IOException { + return false; + } + + @Override + public boolean isTableAvailable(org.apache.hadoop.hbase.TableName tableName) + throws java.io.IOException { + return false; + } + + @Override + public java.util.concurrent.Future addColumnFamilyAsync( + org.apache.hadoop.hbase.TableName tableName, + org.apache.hadoop.hbase.client.ColumnFamilyDescriptor columnFamily) + throws java.io.IOException { + return null; } @Override - public void moveTables(Set tables, String targetGroup) throws IOException { - wrapped.moveTables(tables, targetGroup); + public java.util.concurrent.Future deleteColumnFamilyAsync( + org.apache.hadoop.hbase.TableName tableName, byte[] columnFamily) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future modifyColumnFamilyAsync( + org.apache.hadoop.hbase.TableName tableName, + org.apache.hadoop.hbase.client.ColumnFamilyDescriptor columnFamily) + throws java.io.IOException { + return null; + } + + @Override + public java.util.List getRegions( + org.apache.hadoop.hbase.ServerName serverName) throws java.io.IOException { + return null; + } + + @Override + public void flush(org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + + } + + @Override + public void flushRegion(byte[] regionName) throws java.io.IOException { + + } + + @Override + public void flushRegionServer(org.apache.hadoop.hbase.ServerName serverName) + throws java.io.IOException { + + } + + @Override + public void compact(org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + + } + + @Override + public void compactRegion(byte[] regionName) throws java.io.IOException { + + } + + @Override + public void compact(org.apache.hadoop.hbase.TableName tableName, byte[] columnFamily) + throws java.io.IOException { + + } + + @Override + public void compactRegion(byte[] regionName, byte[] columnFamily) throws java.io.IOException { + + } + + @Override + public void compact(org.apache.hadoop.hbase.TableName tableName, + org.apache.hadoop.hbase.client.CompactType compactType) + throws java.io.IOException, InterruptedException { + + } + + @Override + public void compact(org.apache.hadoop.hbase.TableName tableName, byte[] columnFamily, + org.apache.hadoop.hbase.client.CompactType compactType) + throws java.io.IOException, InterruptedException { + + } + + @Override + public void majorCompact(org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + + } + + @Override + public void majorCompactRegion(byte[] regionName) throws java.io.IOException { + + } + + @Override + public void majorCompact(org.apache.hadoop.hbase.TableName tableName, byte[] columnFamily) + throws java.io.IOException { + + } + + @Override + public void majorCompactRegion(byte[] regionName, byte[] columnFamily) + throws java.io.IOException { + + } + + @Override + public void majorCompact(org.apache.hadoop.hbase.TableName tableName, + org.apache.hadoop.hbase.client.CompactType compactType) + throws java.io.IOException, InterruptedException { + + } + + @Override + public void majorCompact(org.apache.hadoop.hbase.TableName tableName, byte[] columnFamily, + org.apache.hadoop.hbase.client.CompactType compactType) + throws java.io.IOException, InterruptedException { + + } + + @Override + public java.util.Map compactionSwitch( + boolean switchState, java.util.List serverNamesList) throws java.io.IOException { + return null; + } + + @Override + public void compactRegionServer(org.apache.hadoop.hbase.ServerName serverName) + throws java.io.IOException { + + } + + @Override + public void majorCompactRegionServer(org.apache.hadoop.hbase.ServerName serverName) + throws java.io.IOException { + + } + + @Override + public void move(byte[] encodedRegionName) throws java.io.IOException { + + } + + @Override + public void move(byte[] encodedRegionName, org.apache.hadoop.hbase.ServerName destServerName) + throws java.io.IOException { + + } + + @Override + public void assign(byte[] regionName) throws java.io.IOException { + + } + + @Override + public void unassign(byte[] regionName, boolean force) throws java.io.IOException { + + } + + @Override + public void offline(byte[] regionName) throws java.io.IOException { + + } + + @Override + public boolean balancerSwitch(boolean onOrOff, boolean synchronous) throws java.io.IOException { + return false; + } + + @Override + public boolean balance() throws java.io.IOException { + return false; + } + + @Override + public boolean balance(boolean force) throws java.io.IOException { + return false; + } + + @Override + public boolean isBalancerEnabled() throws java.io.IOException { + return false; + } + + @Override + public org.apache.hadoop.hbase.CacheEvictionStats clearBlockCache( + org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + return null; + } + + @Override + public boolean normalize() throws java.io.IOException { + return false; + } + + @Override + public boolean isNormalizerEnabled() throws java.io.IOException { + return false; + } + + @Override + public boolean normalizerSwitch(boolean on) throws java.io.IOException { + return false; + } + + @Override + public boolean catalogJanitorSwitch(boolean onOrOff) throws java.io.IOException { + return false; + } + + @Override + public int runCatalogJanitor() throws java.io.IOException { + return 0; + } + + @Override + public boolean isCatalogJanitorEnabled() throws java.io.IOException { + return false; + } + + @Override + public boolean cleanerChoreSwitch(boolean onOrOff) throws java.io.IOException { + return false; + } + + @Override + public boolean runCleanerChore() throws java.io.IOException { + return false; + } + + @Override + public boolean isCleanerChoreEnabled() throws java.io.IOException { + return false; + } + + @Override + public java.util.concurrent.Future mergeRegionsAsync(byte[][] nameofRegionsToMerge, + boolean forcible) throws java.io.IOException { + return null; + } + + @Override + public void split(org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + + } + + @Override + public void split(org.apache.hadoop.hbase.TableName tableName, byte[] splitPoint) + throws java.io.IOException { + + } + + @Override + public java.util.concurrent.Future splitRegionAsync(byte[] regionName) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future splitRegionAsync(byte[] regionName, byte[] splitPoint) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future modifyTableAsync( + org.apache.hadoop.hbase.client.TableDescriptor td) throws java.io.IOException { + return null; + } + + @Override + public void shutdown() throws java.io.IOException { + + } + + @Override + public void stopMaster() throws java.io.IOException { + + } + + @Override + public boolean isMasterInMaintenanceMode() throws java.io.IOException { + return false; + } + + @Override + public void stopRegionServer(String hostnamePort) throws java.io.IOException { + + } + + @Override + public org.apache.hadoop.hbase.ClusterMetrics getClusterMetrics( + java.util.EnumSet options) + throws java.io.IOException { + return null; + } + + @Override + public java.util.List getRegionMetrics( + org.apache.hadoop.hbase.ServerName serverName) throws java.io.IOException { + return null; + } + + @Override + public java.util.List getRegionMetrics( + org.apache.hadoop.hbase.ServerName serverName, org.apache.hadoop.hbase.TableName tableName) + throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.conf.Configuration getConfiguration() { + return null; + } + + @Override + public java.util.concurrent.Future createNamespaceAsync( + org.apache.hadoop.hbase.NamespaceDescriptor descriptor) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future modifyNamespaceAsync( + org.apache.hadoop.hbase.NamespaceDescriptor descriptor) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future deleteNamespaceAsync(String name) + throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.NamespaceDescriptor getNamespaceDescriptor(String name) + throws org.apache.hadoop.hbase.NamespaceNotFoundException, java.io.IOException { + return null; + } + + @Override + public String[] listNamespaces() throws java.io.IOException { + return new String[0]; + } + + @Override + public org.apache.hadoop.hbase.NamespaceDescriptor[] listNamespaceDescriptors() + throws java.io.IOException { + return new org.apache.hadoop.hbase.NamespaceDescriptor[0]; + } + + @Override + public java.util.List listTableDescriptorsByNamespace( + byte[] name) throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.TableName[] listTableNamesByNamespace(String name) + throws java.io.IOException { + return new org.apache.hadoop.hbase.TableName[0]; + } + + @Override + public java.util.List getRegions( + org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + return null; + } + + @Override + public void close() { + + } + + @Override + public java.util.List listTableDescriptors( + java.util.List tableNames) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future abortProcedureAsync(long procId, + boolean mayInterruptIfRunning) throws java.io.IOException { + return null; + } + + @Override + public String getProcedures() throws java.io.IOException { + return null; + } + + @Override + public String getLocks() throws java.io.IOException { + return null; + } + + @Override + public void rollWALWriter(org.apache.hadoop.hbase.ServerName serverName) + throws java.io.IOException, org.apache.hadoop.hbase.regionserver.wal.FailedLogCloseException { + + } + + @Override + public org.apache.hadoop.hbase.client.CompactionState getCompactionState( + org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.client.CompactionState getCompactionState( + org.apache.hadoop.hbase.TableName tableName, + org.apache.hadoop.hbase.client.CompactType compactType) throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.client.CompactionState getCompactionStateForRegion( + byte[] regionName) throws java.io.IOException { + return null; + } + + @Override + public long getLastMajorCompactionTimestamp(org.apache.hadoop.hbase.TableName tableName) + throws java.io.IOException { + return 0; + } + + @Override + public long getLastMajorCompactionTimestampForRegion(byte[] regionName) + throws java.io.IOException { + return 0; + } + + @Override + public void snapshot(org.apache.hadoop.hbase.client.SnapshotDescription snapshot) + throws java.io.IOException, org.apache.hadoop.hbase.snapshot.SnapshotCreationException, + IllegalArgumentException { + + } + + @Override + public java.util.concurrent.Future snapshotAsync( + org.apache.hadoop.hbase.client.SnapshotDescription snapshot) + throws java.io.IOException, org.apache.hadoop.hbase.snapshot.SnapshotCreationException { + return null; + } + + @Override + public boolean isSnapshotFinished(org.apache.hadoop.hbase.client.SnapshotDescription snapshot) + throws java.io.IOException, org.apache.hadoop.hbase.snapshot.HBaseSnapshotException, + org.apache.hadoop.hbase.snapshot.UnknownSnapshotException { + return false; + } + + @Override + public void restoreSnapshot(String snapshotName) + throws java.io.IOException, org.apache.hadoop.hbase.snapshot.RestoreSnapshotException { + + } + + @Override + public void restoreSnapshot(String snapshotName, boolean takeFailSafeSnapshot, boolean restoreAcl) + throws java.io.IOException, org.apache.hadoop.hbase.snapshot.RestoreSnapshotException { + + } + + @Override + public java.util.concurrent.Future cloneSnapshotAsync(String snapshotName, + org.apache.hadoop.hbase.TableName tableName, boolean restoreAcl) + throws java.io.IOException, org.apache.hadoop.hbase.TableExistsException, + org.apache.hadoop.hbase.snapshot.RestoreSnapshotException { + return null; + } + + @Override + public void execProcedure(String signature, String instance, java.util.Map props) + throws java.io.IOException { + + } + + @Override + public byte[] execProcedureWithReturn(String signature, String instance, + java.util.Map props) throws java.io.IOException { + return new byte[0]; + } + + @Override + public boolean isProcedureFinished(String signature, String instance, + java.util.Map props) throws java.io.IOException { + return false; + } + + @Override + public java.util.List listSnapshots() + throws java.io.IOException { + return null; + } + + @Override + public java.util.List listSnapshots( + java.util.regex.Pattern pattern) throws java.io.IOException { + return null; + } + + @Override + public java.util.List listTableSnapshots( + java.util.regex.Pattern tableNamePattern, java.util.regex.Pattern snapshotNamePattern) + throws java.io.IOException { + return null; + } + + @Override + public void deleteSnapshot(String snapshotName) throws java.io.IOException { + + } + + @Override + public void deleteSnapshots(java.util.regex.Pattern pattern) throws java.io.IOException { + + } + + @Override + public void deleteTableSnapshots(java.util.regex.Pattern tableNamePattern, + java.util.regex.Pattern snapshotNamePattern) throws java.io.IOException { + + } + + @Override + public void setQuota(org.apache.hadoop.hbase.quotas.QuotaSettings quota) + throws java.io.IOException { + + } + + @Override + public java.util.List getQuota( + org.apache.hadoop.hbase.quotas.QuotaFilter filter) throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel coprocessorService() { + return null; + } + + @Override + public org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel coprocessorService( + org.apache.hadoop.hbase.ServerName serverName) { + return null; + } + + @Override + public void updateConfiguration(org.apache.hadoop.hbase.ServerName server) + throws java.io.IOException { + + } + + @Override + public void updateConfiguration() throws java.io.IOException { + + } + + @Override + public java.util.List getSecurityCapabilities() + throws java.io.IOException { + return null; + } + + @Override + public boolean splitSwitch(boolean enabled, boolean synchronous) throws java.io.IOException { + return false; + } + + @Override + public boolean mergeSwitch(boolean enabled, boolean synchronous) throws java.io.IOException { + return false; + } + + @Override + public boolean isSplitEnabled() throws java.io.IOException { + return false; + } + + @Override + public boolean isMergeEnabled() throws java.io.IOException { + return false; + } + + @Override + public java.util.concurrent.Future addReplicationPeerAsync(String peerId, + org.apache.hadoop.hbase.replication.ReplicationPeerConfig peerConfig, boolean enabled) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future removeReplicationPeerAsync(String peerId) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future enableReplicationPeerAsync(String peerId) + throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future disableReplicationPeerAsync(String peerId) + throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.replication.ReplicationPeerConfig getReplicationPeerConfig( + String peerId) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future updateReplicationPeerConfigAsync(String peerId, + org.apache.hadoop.hbase.replication.ReplicationPeerConfig peerConfig) + throws java.io.IOException { + return null; + } + + @Override + public java.util.List listReplicationPeers() + throws java.io.IOException { + return null; + } + + @Override + public java.util.List listReplicationPeers( + java.util.regex.Pattern pattern) throws java.io.IOException { + return null; + } + + @Override + public java.util.concurrent.Future transitReplicationPeerSyncReplicationStateAsync( + String peerId, org.apache.hadoop.hbase.replication.SyncReplicationState state) + throws java.io.IOException { + return null; + } + + @Override + public void decommissionRegionServers(java.util.List servers, + boolean offload) throws java.io.IOException { + + } + + @Override + public java.util.List listDecommissionedRegionServers() + throws java.io.IOException { + return null; + } + + @Override + public void recommissionRegionServer(org.apache.hadoop.hbase.ServerName server, + java.util.List encodedRegionNames) throws java.io.IOException { + + } + + @Override + public java.util.List listReplicatedTableCFs() + throws java.io.IOException { + return null; + } + + @Override + public void enableTableReplication(org.apache.hadoop.hbase.TableName tableName) + throws java.io.IOException { + + } + + @Override + public void disableTableReplication(org.apache.hadoop.hbase.TableName tableName) + throws java.io.IOException { + + } + + @Override + public void clearCompactionQueues(org.apache.hadoop.hbase.ServerName serverName, + java.util.Set queues) throws java.io.IOException, InterruptedException { + + } + + @Override + public java.util.List clearDeadServers( + java.util.List servers) throws java.io.IOException { + return null; + } + + @Override + public void cloneTableSchema(org.apache.hadoop.hbase.TableName tableName, + org.apache.hadoop.hbase.TableName newTableName, boolean preserveSplits) + throws java.io.IOException { + + } + + @Override + public boolean switchRpcThrottle(boolean enable) throws java.io.IOException { + return false; + } + + @Override + public boolean isRpcThrottleEnabled() throws java.io.IOException { + return false; + } + + @Override + public boolean exceedThrottleQuotaSwitch(boolean enable) throws java.io.IOException { + return false; + } + + @Override + public java.util.Map getSpaceQuotaTableSizes() + throws java.io.IOException { + return null; + } + + @Override + public java.util.Map getRegionServerSpaceQuotaSnapshots( + org.apache.hadoop.hbase.ServerName serverName) throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshotView getCurrentSpaceQuotaSnapshot( + String namespace) throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.quotas.SpaceQuotaSnapshotView getCurrentSpaceQuotaSnapshot( + org.apache.hadoop.hbase.TableName tableName) throws java.io.IOException { + return null; + } + + @Override + public void grant(org.apache.hadoop.hbase.security.access.UserPermission userPermission, + boolean mergeExistingPermissions) throws java.io.IOException { + + } + + @Override + public void revoke(org.apache.hadoop.hbase.security.access.UserPermission userPermission) + throws java.io.IOException { + + } + + @Override + public java.util.List getUserPermissions( + org.apache.hadoop.hbase.security.access.GetUserPermissionsRequest getUserPermissionsRequest) + throws java.io.IOException { + return null; + } + + @Override + public java.util.List hasUserPermissions(String userName, + java.util.List permissions) + throws java.io.IOException { + return null; + } + + @Override + public RSGroupInfo getRSGroupInfo(String groupName) throws IOException { + return wrapped.getRSGroupInfo(groupName); + } + + @Override + public void moveServers(Set
servers, String targetGroup) throws IOException { + wrapped.moveServers(servers, targetGroup); verify(); } @@ -115,13 +985,6 @@ public RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException { return wrapped.getRSGroupOfServer(hostPort); } - @Override - public void moveServersAndTables(Set
servers, Set tables, String targetGroup) - throws IOException { - wrapped.moveServersAndTables(servers, tables, targetGroup); - verify(); - } - @Override public void removeServers(Set
servers) throws IOException { wrapped.removeServers(servers); diff --git a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java index d7aea33f991b..1e51fbf5ce48 100644 --- a/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java +++ b/hbase-thrift/src/main/java/org/apache/hadoop/hbase/thrift2/client/ThriftAdmin.java @@ -1142,6 +1142,51 @@ public List hasUserPermissions(String userName, List permis throw new NotImplementedException("hasUserPermissions not supported in ThriftAdmin"); } + @Override + public org.apache.hadoop.hbase.rsgroup.RSGroupInfo getRSGroupInfo(String groupName) + throws java.io.IOException { + return null; + } + + @Override + public void moveServers(java.util.Set servers, + String targetGroup) throws java.io.IOException { + + } + + @Override + public void addRSGroup(String groupName) throws java.io.IOException { + + } + + @Override + public void removeRSGroup(String groupName) throws java.io.IOException { + + } + + @Override + public boolean balanceRSGroup(String groupName) throws java.io.IOException { + return false; + } + + @Override + public java.util.List listRSGroups() + throws java.io.IOException { + return null; + } + + @Override + public org.apache.hadoop.hbase.rsgroup.RSGroupInfo getRSGroupOfServer( + org.apache.hadoop.hbase.net.Address hostPort) throws java.io.IOException { + return null; + } + + @Override + public void removeServers(java.util.Set servers) + throws java.io.IOException { + + } + @Override public Future splitRegionAsync(byte[] regionName) throws IOException { return splitRegionAsync(regionName, null);