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 }