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 getMiniHBaseCluster().shutdown();
102 }
103 }
104
105 /**
106 * Sets the configuration property to use a distributed cluster for the integration tests. Test drivers
107 * should use this to enforce cluster deployment.
108 */
109 public static void setUseDistributedCluster(Configuration conf) {
110 conf.setBoolean(IS_DISTRIBUTED_CLUSTER, true);
111 System.setProperty(IS_DISTRIBUTED_CLUSTER, "true");
112 }
113
114 /**
115 * @return whether we are interacting with a distributed cluster as opposed to and in-process mini
116 * cluster or a local cluster.
117 * @see IntegrationTestingUtility#setUseDistributedCluster(Configuration)
118 */
119 public boolean isDistributedCluster() {
120 Configuration conf = getConfiguration();
121 boolean isDistributedCluster = false;
122 isDistributedCluster = Boolean.parseBoolean(System.getProperty(IS_DISTRIBUTED_CLUSTER, "false"));
123 if (!isDistributedCluster) {
124 isDistributedCluster = conf.getBoolean(IS_DISTRIBUTED_CLUSTER, false);
125 }
126 return isDistributedCluster;
127 }
128
129 private void createDistributedHBaseCluster() throws IOException {
130 Configuration conf = getConfiguration();
131 Class<? extends ClusterManager> clusterManagerClass = conf.getClass(HBASE_CLUSTER_MANAGER_CLASS,
132 DEFAULT_HBASE_CLUSTER_MANAGER_CLASS, ClusterManager.class);
133 ClusterManager clusterManager = ReflectionUtils.newInstance(
134 clusterManagerClass, conf);
135 setHBaseCluster(new DistributedHBaseCluster(conf, clusterManager));
136 getHBaseAdmin();
137 }
138
139 }