001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.rsgroup;
019
020import java.io.IOException;
021import java.util.ArrayList;
022import java.util.List;
023import java.util.Set;
024import org.apache.hadoop.hbase.TableName;
025import org.apache.hadoop.hbase.TableNotFoundException;
026import org.apache.hadoop.hbase.client.Admin;
027import org.apache.hadoop.hbase.client.BalanceRequest;
028import org.apache.hadoop.hbase.client.BalanceResponse;
029import org.apache.hadoop.hbase.client.Connection;
030import org.apache.hadoop.hbase.net.Address;
031import org.apache.yetus.audience.InterfaceAudience;
032
033import org.apache.hbase.thirdparty.com.google.common.collect.Sets;
034import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException;
035
036import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
037import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;
038import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.AddRSGroupRequest;
039import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.BalanceRSGroupRequest;
040import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerRequest;
041import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfServerResponse;
042import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableRequest;
043import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoOfTableResponse;
044import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoRequest;
045import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.GetRSGroupInfoResponse;
046import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.ListRSGroupInfosRequest;
047import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersAndTablesRequest;
048import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveServersRequest;
049import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.MoveTablesRequest;
050import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RSGroupAdminService;
051import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveRSGroupRequest;
052import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos.RemoveServersRequest;
053import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupProtos;
054
055/**
056 * Client used for managing region server group information.
057 * @deprecated Keep it here only for tests, using {@link Admin} instead.
058 */
059@Deprecated
060@InterfaceAudience.Private
061public class RSGroupAdminClient {
062  private RSGroupAdminService.BlockingInterface stub;
063  private Admin admin;
064
065  public RSGroupAdminClient(Connection conn) throws IOException {
066    admin = conn.getAdmin();
067    stub = RSGroupAdminService.newBlockingStub(admin.coprocessorService());
068  }
069
070  /**
071   * Gets {@code RSGroupInfo} for given group name.
072   */
073  public RSGroupInfo getRSGroupInfo(String groupName) throws IOException {
074    try {
075      GetRSGroupInfoResponse resp = stub.getRSGroupInfo(null,
076        GetRSGroupInfoRequest.newBuilder().setRSGroupName(groupName).build());
077      if (resp.hasRSGroupInfo()) {
078        return ProtobufUtil.toGroupInfo(resp.getRSGroupInfo());
079      }
080      return null;
081    } catch (ServiceException e) {
082      throw ProtobufUtil.handleRemoteException(e);
083    }
084  }
085
086  /**
087   * Gets {@code RSGroupInfo} for the given table's group.
088   */
089  public RSGroupInfo getRSGroupInfoOfTable(TableName tableName) throws IOException {
090    GetRSGroupInfoOfTableRequest request = GetRSGroupInfoOfTableRequest.newBuilder()
091      .setTableName(ProtobufUtil.toProtoTableName(tableName)).build();
092    try {
093      GetRSGroupInfoOfTableResponse resp = stub.getRSGroupInfoOfTable(null, request);
094      if (resp.hasRSGroupInfo()) {
095        return ProtobufUtil.toGroupInfo(resp.getRSGroupInfo());
096      }
097      return null;
098    } catch (ServiceException e) {
099      throw ProtobufUtil.handleRemoteException(e);
100    }
101  }
102
103  /**
104   * Move given set of servers to the specified target RegionServer group.
105   */
106  public void moveServers(Set<Address> servers, String targetGroup) throws IOException {
107    Set<HBaseProtos.ServerName> hostPorts = Sets.newHashSet();
108    for (Address el : servers) {
109      hostPorts.add(HBaseProtos.ServerName.newBuilder().setHostName(el.getHostname())
110        .setPort(el.getPort()).build());
111    }
112    MoveServersRequest request =
113      MoveServersRequest.newBuilder().setTargetGroup(targetGroup).addAllServers(hostPorts).build();
114    try {
115      stub.moveServers(null, request);
116    } catch (ServiceException e) {
117      throw ProtobufUtil.handleRemoteException(e);
118    }
119  }
120
121  /**
122   * Move given set of tables to the specified target RegionServer group. This will unassign all of
123   * a table's region so it can be reassigned to the correct group.
124   */
125  public void moveTables(Set<TableName> tables, String targetGroup) throws IOException {
126    MoveTablesRequest.Builder builder = MoveTablesRequest.newBuilder().setTargetGroup(targetGroup);
127    for (TableName tableName : tables) {
128      builder.addTableName(ProtobufUtil.toProtoTableName(tableName));
129      if (!admin.tableExists(tableName)) {
130        throw new TableNotFoundException(tableName);
131      }
132    }
133    try {
134      stub.moveTables(null, builder.build());
135    } catch (ServiceException e) {
136      throw ProtobufUtil.handleRemoteException(e);
137    }
138  }
139
140  /**
141   * Creates a new RegionServer group with the given name.
142   */
143  public void addRSGroup(String groupName) throws IOException {
144    AddRSGroupRequest request = AddRSGroupRequest.newBuilder().setRSGroupName(groupName).build();
145    try {
146      stub.addRSGroup(null, request);
147    } catch (ServiceException e) {
148      throw ProtobufUtil.handleRemoteException(e);
149    }
150  }
151
152  /**
153   * Removes RegionServer group associated with the given name.
154   */
155  public void removeRSGroup(String name) throws IOException {
156    RemoveRSGroupRequest request = RemoveRSGroupRequest.newBuilder().setRSGroupName(name).build();
157    try {
158      stub.removeRSGroup(null, request);
159    } catch (ServiceException e) {
160      throw ProtobufUtil.handleRemoteException(e);
161    }
162  }
163
164  /**
165   * Balance regions in the given RegionServer group.
166   * @return BalanceResponse details about the balancer run
167   */
168  public BalanceResponse balanceRSGroup(String groupName, BalanceRequest request)
169    throws IOException {
170    try {
171      BalanceRSGroupRequest req = ProtobufUtil.createBalanceRSGroupRequest(groupName, request);
172      return ProtobufUtil.toBalanceResponse(stub.balanceRSGroup(null, req));
173    } catch (ServiceException e) {
174      throw ProtobufUtil.handleRemoteException(e);
175    }
176  }
177
178  /**
179   * Lists current set of RegionServer groups.
180   */
181  public List<RSGroupInfo> listRSGroups() throws IOException {
182    try {
183      List<RSGroupProtos.RSGroupInfo> resp = stub
184        .listRSGroupInfos(null, ListRSGroupInfosRequest.getDefaultInstance()).getRSGroupInfoList();
185      List<RSGroupInfo> result = new ArrayList<>(resp.size());
186      for (RSGroupProtos.RSGroupInfo entry : resp) {
187        result.add(ProtobufUtil.toGroupInfo(entry));
188      }
189      return result;
190    } catch (ServiceException e) {
191      throw ProtobufUtil.handleRemoteException(e);
192    }
193  }
194
195  /**
196   * Retrieve the RSGroupInfo a server is affiliated to
197   * @param hostPort HostPort to get RSGroupInfo for
198   */
199  public RSGroupInfo getRSGroupOfServer(Address hostPort) throws IOException {
200    GetRSGroupInfoOfServerRequest request =
201      GetRSGroupInfoOfServerRequest.newBuilder().setServer(HBaseProtos.ServerName.newBuilder()
202        .setHostName(hostPort.getHostname()).setPort(hostPort.getPort()).build()).build();
203    try {
204      GetRSGroupInfoOfServerResponse resp = stub.getRSGroupInfoOfServer(null, request);
205      if (resp.hasRSGroupInfo()) {
206        return ProtobufUtil.toGroupInfo(resp.getRSGroupInfo());
207      }
208      return null;
209    } catch (ServiceException e) {
210      throw ProtobufUtil.handleRemoteException(e);
211    }
212  }
213
214  /**
215   * Move given set of servers and tables to the specified target RegionServer group.
216   * @param servers     set of servers to move
217   * @param tables      set of tables to move
218   * @param targetGroup the target group name
219   * @throws IOException if moving the server and tables fail
220   */
221  public void moveServersAndTables(Set<Address> servers, Set<TableName> tables, String targetGroup)
222    throws IOException {
223    MoveServersAndTablesRequest.Builder builder =
224      MoveServersAndTablesRequest.newBuilder().setTargetGroup(targetGroup);
225    for (Address el : servers) {
226      builder.addServers(HBaseProtos.ServerName.newBuilder().setHostName(el.getHostname())
227        .setPort(el.getPort()).build());
228    }
229    for (TableName tableName : tables) {
230      builder.addTableName(ProtobufUtil.toProtoTableName(tableName));
231      if (!admin.tableExists(tableName)) {
232        throw new TableNotFoundException(tableName);
233      }
234    }
235    try {
236      stub.moveServersAndTables(null, builder.build());
237    } catch (ServiceException e) {
238      throw ProtobufUtil.handleRemoteException(e);
239    }
240  }
241
242  /**
243   * Remove decommissioned servers from rsgroup. 1. Sometimes we may find the server aborted due to
244   * some hardware failure and we must offline the server for repairing. Or we need to move some
245   * servers to join other clusters. So we need to remove these servers from the rsgroup. 2.
246   * Dead/recovering/live servers will be disallowed.
247   * @param servers set of servers to remove
248   */
249  public void removeServers(Set<Address> servers) throws IOException {
250    Set<HBaseProtos.ServerName> hostPorts = Sets.newHashSet();
251    for (Address el : servers) {
252      hostPorts.add(HBaseProtos.ServerName.newBuilder().setHostName(el.getHostname())
253        .setPort(el.getPort()).build());
254    }
255    RemoveServersRequest request =
256      RemoveServersRequest.newBuilder().addAllServers(hostPorts).build();
257    try {
258      stub.removeServers(null, request);
259    } catch (ServiceException e) {
260      throw ProtobufUtil.handleRemoteException(e);
261    }
262  }
263}