View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase;
19  
20  import java.io.Closeable;
21  import java.io.IOException;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.hadoop.classification.InterfaceAudience;
26  import org.apache.hadoop.conf.Configurable;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
29  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ClientService;
30  import org.apache.hadoop.hbase.protobuf.generated.MasterAdminProtos.MasterAdminService;
31  import org.apache.hadoop.hbase.protobuf.generated.MasterMonitorProtos.MasterMonitorService;
32  import org.apache.hadoop.hbase.util.Threads;
33  
34  /**
35   * This class defines methods that can help with managing HBase clusters
36   * from unit tests and system tests. There are 3 types of cluster deployments:
37   * <ul>
38   * <li><b>MiniHBaseCluster:</b> each server is run in the same JVM in separate threads,
39   * used by unit tests</li>
40   * <li><b>DistributedHBaseCluster:</b> the cluster is pre-deployed, system and integration tests can
41   * interact with the cluster. </li>
42   * <li><b>ProcessBasedLocalHBaseCluster:</b> each server is deployed locally but in separate
43   * JVMs. </li>
44   * </ul>
45   * <p>
46   * HBaseCluster unifies the way tests interact with the cluster, so that the same test can
47   * be run against a mini-cluster during unit test execution, or a distributed cluster having
48   * tens/hundreds of nodes during execution of integration tests.
49   *
50   * <p>
51   * HBaseCluster exposes client-side public interfaces to tests, so that tests does not assume
52   * running in a particular mode. Not all the tests are suitable to be run on an actual cluster,
53   * and some tests will still need to mock stuff and introspect internal state. For those use
54   * cases from unit tests, or if more control is needed, you can use the subclasses directly.
55   * In that sense, this class does not abstract away <strong>every</strong> interface that
56   * MiniHBaseCluster or DistributedHBaseCluster provide.
57   */
58  @InterfaceAudience.Private
59  public abstract class HBaseCluster implements Closeable, Configurable {
60    static final Log LOG = LogFactory.getLog(HBaseCluster.class.getName());
61    protected Configuration conf;
62  
63    /** the status of the cluster before we begin */
64    protected ClusterStatus initialClusterStatus;
65  
66    /**
67     * Construct an HBaseCluster
68     * @param conf Configuration to be used for cluster
69     */
70    public HBaseCluster(Configuration conf) {
71      setConf(conf);
72    }
73  
74    @Override
75    public void setConf(Configuration conf) {
76      this.conf = conf;
77    }
78  
79    @Override
80    public Configuration getConf() {
81      return conf;
82    }
83  
84    /**
85     * Returns a ClusterStatus for this HBase cluster.
86     * @see #getInitialClusterStatus()
87     */
88    public abstract ClusterStatus getClusterStatus() throws IOException;
89  
90    /**
91     * Returns a ClusterStatus for this HBase cluster as observed at the
92     * starting of the HBaseCluster
93     */
94    public ClusterStatus getInitialClusterStatus() throws IOException {
95      return initialClusterStatus;
96    }
97  
98    /**
99     * Returns an {@link MasterAdminService.BlockingInterface} to the active master
100    */
101   public abstract MasterAdminService.BlockingInterface getMasterAdmin()
102       throws IOException;
103 
104   /**
105    * Returns an {@link MasterMonitorService.BlockingInterface} to the active master
106    */
107   public abstract MasterMonitorService.BlockingInterface getMasterMonitor()
108   throws IOException;
109 
110   /**
111    * Returns an AdminProtocol interface to the regionserver
112    */
113   public abstract AdminService.BlockingInterface getAdminProtocol(ServerName serverName)
114   throws IOException;
115 
116   /**
117    * Returns a ClientProtocol interface to the regionserver
118    */
119   public abstract ClientService.BlockingInterface getClientProtocol(ServerName serverName)
120   throws IOException;
121 
122   /**
123    * Starts a new region server on the given hostname or if this is a mini/local cluster,
124    * starts a region server locally.
125    * @param hostname the hostname to start the regionserver on
126    * @throws IOException if something goes wrong
127    */
128   public abstract void startRegionServer(String hostname) throws IOException;
129 
130   /**
131    * Kills the region server process if this is a distributed cluster, otherwise
132    * this causes the region server to exit doing basic clean up only.
133    * @throws IOException if something goes wrong
134    */
135   public abstract void killRegionServer(ServerName serverName) throws IOException;
136 
137   /**
138    * Stops the given region server, by attempting a gradual stop.
139    * @return whether the operation finished with success
140    * @throws IOException if something goes wrong
141    */
142   public abstract void stopRegionServer(ServerName serverName) throws IOException;
143 
144   /**
145    * Wait for the specified region server to join the cluster
146    * @return whether the operation finished with success
147    * @throws IOException if something goes wrong or timeout occurs
148    */
149   public void waitForRegionServerToStart(String hostname, long timeout)
150       throws IOException {
151     long start = System.currentTimeMillis();
152     while ((System.currentTimeMillis() - start) < timeout) {
153       for (ServerName server : getClusterStatus().getServers()) {
154         if (server.getHostname().equals(hostname)) {
155           return;
156         }
157       }
158       Threads.sleep(100);
159     }
160     throw new IOException("did timeout waiting for region server to start:" + hostname);
161   }
162 
163   /**
164    * Wait for the specified region server to stop the thread / process.
165    * @return whether the operation finished with success
166    * @throws IOException if something goes wrong or timeout occurs
167    */
168   public abstract void waitForRegionServerToStop(ServerName serverName, long timeout)
169       throws IOException;
170 
171   /**
172    * Starts a new master on the given hostname or if this is a mini/local cluster,
173    * starts a master locally.
174    * @param hostname the hostname to start the master on
175    * @return whether the operation finished with success
176    * @throws IOException if something goes wrong
177    */
178   public abstract void startMaster(String hostname) throws IOException;
179 
180   /**
181    * Kills the master process if this is a distributed cluster, otherwise,
182    * this causes master to exit doing basic clean up only.
183    * @throws IOException if something goes wrong
184    */
185   public abstract void killMaster(ServerName serverName) throws IOException;
186 
187   /**
188    * Stops the given master, by attempting a gradual stop.
189    * @throws IOException if something goes wrong
190    */
191   public abstract void stopMaster(ServerName serverName) throws IOException;
192 
193   /**
194    * Wait for the specified master to stop the thread / process.
195    * @throws IOException if something goes wrong or timeout occurs
196    */
197   public abstract void waitForMasterToStop(ServerName serverName, long timeout)
198       throws IOException;
199 
200   /**
201    * Blocks until there is an active master and that master has completed
202    * initialization.
203    *
204    * @return true if an active master becomes available.  false if there are no
205    *         masters left.
206    * @throws IOException if something goes wrong or timeout occurs
207    */
208   public boolean waitForActiveAndReadyMaster()
209       throws IOException {
210     return waitForActiveAndReadyMaster(Long.MAX_VALUE);
211   }
212 
213   /**
214    * Blocks until there is an active master and that master has completed
215    * initialization.
216    * @param timeout the timeout limit in ms
217    * @return true if an active master becomes available.  false if there are no
218    *         masters left.
219    */
220   public abstract boolean waitForActiveAndReadyMaster(long timeout)
221       throws IOException;
222 
223   /**
224    * Wait for HBase Cluster to shut down.
225    */
226   public abstract void waitUntilShutDown() throws IOException;
227 
228   /**
229    * Shut down the HBase cluster
230    */
231   public abstract void shutdown() throws IOException;
232 
233   /**
234    * Restores the cluster to it's initial state if this is a real cluster,
235    * otherwise does nothing.
236    */
237   public void restoreInitialStatus() throws IOException {
238     restoreClusterStatus(getInitialClusterStatus());
239   }
240 
241   /**
242    * Restores the cluster to given state if this is a real cluster,
243    * otherwise does nothing.
244    */
245   public void restoreClusterStatus(ClusterStatus desiredStatus) throws IOException {
246   }
247 
248   /**
249    * Get the ServerName of region server serving ROOT region
250    */
251   public ServerName getServerHoldingRoot() throws IOException {
252     return getServerHoldingRegion(HRegionInfo.ROOT_REGIONINFO.getRegionName());
253   }
254 
255   /**
256    * Get the ServerName of region server serving the first META region
257    */
258   public ServerName getServerHoldingMeta() throws IOException {
259     return getServerHoldingRegion(HRegionInfo.FIRST_META_REGIONINFO.getRegionName());
260   }
261 
262   /**
263    * Get the ServerName of region server serving the specified region
264    * @param regionName Name of the region in bytes
265    * @return ServerName that hosts the region or null
266    */
267   public abstract ServerName getServerHoldingRegion(byte[] regionName) throws IOException;
268 
269   /**
270    * @return whether we are interacting with a distributed cluster as opposed to an
271    * in-process mini/local cluster.
272    */
273   public boolean isDistributedCluster() {
274     return false;
275   }
276 
277   /**
278    * Closes all the resources held open for this cluster. Note that this call does not shutdown
279    * the cluster.
280    * @see #shutdown()
281    */
282   @Override
283   public abstract void close() throws IOException;
284 
285   /**
286    * Wait for the namenode.
287    *
288    * @throws InterruptedException
289    */
290   public void waitForNamenodeAvailable() throws InterruptedException {
291   }
292 
293   public void waitForDatanodesRegistered(int nbDN) throws Exception {
294   }
295 }