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  
19  package org.apache.hadoop.hbase;
20  
21  import java.io.IOException;
22  
23  import org.apache.hadoop.conf.Configuration;
24  import org.apache.hadoop.util.ReflectionUtils;
25  
26  /**
27   * Facility for <strong>integration/system</strong> tests. This extends {@link HBaseTestingUtility}
28   * and adds-in the functionality needed by integration and system tests. This class understands
29   * distributed and pseudo-distributed/local cluster deployments, and abstracts those from the tests
30   * in this module.
31   * <p>
32   * IntegrationTestingUtility is constructed and used by the integration tests, but the tests
33   * themselves should not assume a particular deployment. They can rely on the methods in this
34   * class and HBaseCluster. Before the testing begins, the test should initialize the cluster by
35   * calling {@link #initializeCluster(int)}.
36   * <p>
37   * The cluster that is used defaults to a mini cluster, but it can be forced to use a distributed
38   * cluster by calling {@link #setUseDistributedCluster(Configuration)}. This method is invoked by
39   * test drivers (maven, IntegrationTestsDriver, etc) before initializing the cluster
40   * via {@link #initializeCluster(int)}. Individual tests should not directly call
41   * {@link #setUseDistributedCluster(Configuration)}.
42   */
43  public class IntegrationTestingUtility extends HBaseTestingUtility {
44  
45    public IntegrationTestingUtility() {
46      this(HBaseConfiguration.create());
47    }
48  
49    public IntegrationTestingUtility(Configuration conf) {
50      super(conf);
51    }
52  
53    /**
54     * Configuration that controls whether this utility assumes a running/deployed cluster.
55     * This is different than "hbase.cluster.distributed" since that parameter indicates whether the
56     * cluster is in an actual distributed environment, while this shows that there is a
57     * deployed (distributed or pseudo-distributed) cluster running, and we do not need to
58     * start a mini-cluster for tests.
59     */
60    public static final String IS_DISTRIBUTED_CLUSTER = "hbase.test.cluster.distributed";
61  
62    /** Config for pluggable hbase cluster manager */
63    private static final String HBASE_CLUSTER_MANAGER_CLASS = "hbase.it.clustermanager.class";
64    private static final Class<? extends ClusterManager> DEFAULT_HBASE_CLUSTER_MANAGER_CLASS = 
65      HBaseClusterManager.class;
66    
67    /**
68     * Initializes the state of the cluster. It starts a new in-process mini cluster, OR
69     * if we are given an already deployed distributed cluster it initializes the state.
70     * @param numSlaves Number of slaves to start up if we are booting a mini cluster. Otherwise
71     * we check whether this many nodes are available and throw an exception if not.
72     */
73    public void initializeCluster(int numSlaves) throws Exception {
74      if (isDistributedCluster()) {
75        createDistributedHBaseCluster();
76        checkNodeCount(numSlaves);
77      } else {
78        startMiniCluster(numSlaves);
79      }
80    }
81  
82    /**
83     * Checks whether we have more than numSlaves nodes. Throws an
84     * exception otherwise.
85     */
86    public void checkNodeCount(int numSlaves) throws Exception {
87      HBaseCluster cluster = getHBaseClusterInterface();
88      if (cluster.getClusterStatus().getServers().size() < numSlaves) {
89        throw new Exception("Cluster does not have enough nodes:" + numSlaves);
90      }
91    }
92  
93    /**
94     * Restores the cluster to the initial state if it is a distributed cluster, otherwise, shutdowns the
95     * mini cluster.
96     */
97    public void restoreCluster() throws IOException {
98      if (isDistributedCluster()) {
99        getHBaseClusterInterface().restoreInitialStatus();
100     } else {
101       try {
102         shutdownMiniCluster();
103       } catch (Exception e) {
104         // re-wrap into IOException
105         throw new IOException(e);
106       }
107     }
108   }
109 
110   /**
111    * Sets the configuration property to use a distributed cluster for the integration tests. Test drivers
112    * should use this to enforce cluster deployment.
113    */
114   public static void setUseDistributedCluster(Configuration conf) {
115     conf.setBoolean(IS_DISTRIBUTED_CLUSTER, true);
116     System.setProperty(IS_DISTRIBUTED_CLUSTER, "true");
117   }
118 
119   /**
120    * @return whether we are interacting with a distributed cluster as opposed to and in-process mini
121    * cluster or a local cluster.
122    * @see IntegrationTestingUtility#setUseDistributedCluster(Configuration)
123    */
124   public boolean isDistributedCluster() {
125     Configuration conf = getConfiguration();
126     boolean isDistributedCluster = false;
127     isDistributedCluster = Boolean.parseBoolean(System.getProperty(IS_DISTRIBUTED_CLUSTER, "false"));
128     if (!isDistributedCluster) {
129       isDistributedCluster = conf.getBoolean(IS_DISTRIBUTED_CLUSTER, false);
130     }
131     return isDistributedCluster;
132   }
133 
134   private void createDistributedHBaseCluster() throws IOException {
135     Configuration conf = getConfiguration();
136     Class<? extends ClusterManager> clusterManagerClass = conf.getClass(HBASE_CLUSTER_MANAGER_CLASS,
137       DEFAULT_HBASE_CLUSTER_MANAGER_CLASS, ClusterManager.class);
138     ClusterManager clusterManager = ReflectionUtils.newInstance(
139       clusterManagerClass, conf);
140     setHBaseCluster(new DistributedHBaseCluster(conf, clusterManager));
141     getHBaseAdmin();
142   }
143 
144 }