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; 019 020import java.io.IOException; 021import org.apache.hadoop.conf.Configuration; 022import org.apache.hadoop.util.ReflectionUtils; 023 024/** 025 * Facility for <strong>integration/system</strong> tests. This extends {@link HBaseTestingUtility} 026 * and adds-in the functionality needed by integration and system tests. This class understands 027 * distributed and pseudo-distributed/local cluster deployments, and abstracts those from the tests 028 * in this module. 029 * <p> 030 * IntegrationTestingUtility is constructed and used by the integration tests, but the tests 031 * themselves should not assume a particular deployment. They can rely on the methods in this class 032 * and HBaseCluster. Before the testing begins, the test should initialize the cluster by calling 033 * {@link #initializeCluster(int)}. 034 * <p> 035 * The cluster that is used defaults to a mini cluster, but it can be forced to use a distributed 036 * cluster by calling {@link #setUseDistributedCluster(Configuration)}. This method is invoked by 037 * test drivers (maven, IntegrationTestsDriver, etc) before initializing the cluster via 038 * {@link #initializeCluster(int)}. Individual tests should not directly call 039 * {@link #setUseDistributedCluster(Configuration)}. 040 */ 041public class IntegrationTestingUtility extends HBaseTestingUtility { 042 043 public IntegrationTestingUtility() { 044 this(HBaseConfiguration.create()); 045 } 046 047 public IntegrationTestingUtility(Configuration conf) { 048 super(conf); 049 } 050 051 /** 052 * Configuration that controls whether this utility assumes a running/deployed cluster. This is 053 * different than "hbase.cluster.distributed" since that parameter indicates whether the cluster 054 * is in an actual distributed environment, while this shows that there is a deployed (distributed 055 * or pseudo-distributed) cluster running, and we do not need to start a mini-cluster for tests. 056 */ 057 public static final String IS_DISTRIBUTED_CLUSTER = "hbase.test.cluster.distributed"; 058 059 /** 060 * Config for pluggable hbase cluster manager. Pass fully-qualified class name as property value. 061 * Drop the '.class' suffix. 062 */ 063 public static final String HBASE_CLUSTER_MANAGER_CLASS = "hbase.it.clustermanager.class"; 064 private static final Class<? extends ClusterManager> DEFAULT_HBASE_CLUSTER_MANAGER_CLASS = 065 HBaseClusterManager.class; 066 067 /** 068 * Initializes the state of the cluster. It starts a new in-process mini cluster, OR if we are 069 * given an already deployed distributed cluster it initializes the state. 070 * @param numSlaves Number of slaves to start up if we are booting a mini cluster. Otherwise we 071 * check whether this many nodes are available and throw an exception if not. 072 */ 073 public void initializeCluster(int numSlaves) throws Exception { 074 if (isDistributedCluster()) { 075 createDistributedHBaseCluster(); 076 checkNodeCount(numSlaves); 077 } else { 078 startMiniCluster(numSlaves); 079 } 080 } 081 082 /** 083 * Checks whether we have more than numSlaves nodes. Throws an exception otherwise. 084 */ 085 public void checkNodeCount(int numSlaves) throws Exception { 086 HBaseCluster cluster = getHBaseClusterInterface(); 087 if (cluster.getClusterMetrics().getLiveServerMetrics().size() < numSlaves) { 088 throw new Exception("Cluster does not have enough nodes:" + numSlaves); 089 } 090 } 091 092 /** 093 * Restores the cluster to the initial state if it is a distributed cluster, otherwise, shutdowns 094 * the mini cluster. 095 */ 096 public void restoreCluster() throws IOException { 097 if (isDistributedCluster()) { 098 getHBaseClusterInterface().restoreInitialStatus(); 099 } else { 100 try { 101 shutdownMiniCluster(); 102 } catch (Exception e) { 103 // re-wrap into IOException 104 throw new IOException(e); 105 } 106 } 107 } 108 109 /** 110 * Sets the configuration property to use a distributed cluster for the integration tests. Test 111 * drivers should use this to enforce cluster deployment. 112 */ 113 public static void setUseDistributedCluster(Configuration conf) { 114 conf.setBoolean(IS_DISTRIBUTED_CLUSTER, true); 115 System.setProperty(IS_DISTRIBUTED_CLUSTER, "true"); 116 } 117 118 /** 119 * Returns whether we are interacting with a distributed cluster as opposed to and in-process mini 120 * cluster or a local cluster. 121 * @see IntegrationTestingUtility#setUseDistributedCluster(Configuration) 122 */ 123 public boolean isDistributedCluster() { 124 Configuration conf = getConfiguration(); 125 boolean isDistributedCluster = 126 Boolean.parseBoolean(System.getProperty(IS_DISTRIBUTED_CLUSTER, "false")); 127 if (!isDistributedCluster) { 128 isDistributedCluster = conf.getBoolean(IS_DISTRIBUTED_CLUSTER, false); 129 } 130 return isDistributedCluster; 131 } 132 133 public void createDistributedHBaseCluster() throws IOException { 134 // if it is a distributed HBase cluster, use the conf provided by classpath 135 // to set hbase dir and fs.defaultFS. 136 // Since when the super class HBaseTestingUtility initializing, it will 137 // change hbase.rootdir to a local test dir. 138 // we use "original.defaultFS" and "original.hbase.dir" to restore them. 139 Configuration conf = getConfiguration(); 140 if (conf.get("original.defaultFS") != null) { 141 conf.set("fs.defaultFS", conf.get("original.defaultFS")); 142 } 143 if (conf.get("original.hbase.dir") != null) { 144 conf.set(HConstants.HBASE_DIR, conf.get("original.hbase.dir")); 145 } 146 LOG.debug("Setting {} to {} since it is a distributed cluster", HConstants.HBASE_DIR, 147 conf.get(HConstants.HBASE_DIR)); 148 Class<? extends ClusterManager> clusterManagerClass = conf.getClass(HBASE_CLUSTER_MANAGER_CLASS, 149 DEFAULT_HBASE_CLUSTER_MANAGER_CLASS, ClusterManager.class); 150 LOG.info("Instantiating {}", clusterManagerClass.getName()); 151 ClusterManager clusterManager = ReflectionUtils.newInstance(clusterManagerClass, conf); 152 setHBaseCluster(new DistributedHBaseCluster(conf, clusterManager)); 153 getAdmin(); 154 } 155}