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.util.Arrays; 021import java.util.List; 022import org.apache.commons.lang3.StringUtils; 023import org.apache.hadoop.hbase.master.HMaster; 024import org.apache.yetus.audience.InterfaceAudience; 025 026/** 027 * Options for starting up a mini cluster (including an hbase, dfs and zookeeper clusters) in test. 028 * The options include HDFS options to build mini dfs cluster, Zookeeper options to build mini zk 029 * cluster, and mostly HBase options to build mini hbase cluster. To create an object, use a 030 * {@link Builder}. Example usage: 031 * 032 * <pre> 033 * StartMiniClusterOption option = StartMiniClusterOption.builder(). 034 * .numMasters(3).rsClass(MyRegionServer.class).createWALDir(true).build(); 035 * </pre> 036 * 037 * Default values can be found in {@link Builder}. 038 */ 039@InterfaceAudience.Public 040public final class StartMiniClusterOption { 041 /** 042 * Number of masters to start up. We'll start this many hbase masters. If numMasters > 1, you can 043 * find the active/primary master with {@link MiniHBaseCluster#getMaster()}. 044 */ 045 private final int numMasters; 046 047 /** 048 * Number of masters that always remain standby. These set of masters never transition to active 049 * even if an active master does not exist. These are needed for testing scenarios where there are 050 * no active masters in the cluster but the cluster connection (backed by master registry) should 051 * still work. 052 */ 053 private final int numAlwaysStandByMasters; 054 /** 055 * The class to use as HMaster, or null for default. 056 */ 057 private final Class<? extends HMaster> masterClass; 058 059 /** 060 * Number of region servers to start up. If this value is > 1, then make sure config 061 * "hbase.regionserver.info.port" is -1 (i.e. no ui per regionserver) otherwise bind errors. 062 */ 063 private final int numRegionServers; 064 /** 065 * Ports that RegionServer should use. Pass ports if you want to test cluster restart where for 066 * sure the regionservers come up on same address+port (but just with different startcode); by 067 * default mini hbase clusters choose new arbitrary ports on each cluster start. 068 */ 069 private final List<Integer> rsPorts; 070 /** 071 * The class to use as HRegionServer, or null for default. 072 */ 073 private Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> rsClass; 074 075 /** 076 * Number of datanodes. Used to create mini DSF cluster. Surpassed by {@link #dataNodeHosts} size. 077 */ 078 private final int numDataNodes; 079 /** 080 * The hostnames of DataNodes to run on. This is useful if you want to run datanode on distinct 081 * hosts for things like HDFS block location verification. If you start MiniDFSCluster without 082 * host names, all instances of the datanodes will have the same host name. 083 */ 084 private final String[] dataNodeHosts; 085 086 /** 087 * Number of Zookeeper servers. 088 */ 089 private final int numZkServers; 090 091 /** 092 * Whether to create a new root or data directory path. If true, the newly created data directory 093 * will be configured as HBase rootdir. This will overwrite existing root directory config. 094 */ 095 private final boolean createRootDir; 096 097 /** 098 * Whether to create a new WAL directory. If true, the newly created directory will be configured 099 * as HBase wal.dir which is separate from HBase rootdir. 100 */ 101 private final boolean createWALDir; 102 103 /** 104 * Private constructor. Use {@link Builder#build()}. 105 */ 106 private StartMiniClusterOption(int numMasters, int numAlwaysStandByMasters, 107 Class<? extends HMaster> masterClass, int numRegionServers, List<Integer> rsPorts, 108 Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> rsClass, int numDataNodes, 109 String[] dataNodeHosts, int numZkServers, boolean createRootDir, boolean createWALDir) { 110 this.numMasters = numMasters; 111 this.numAlwaysStandByMasters = numAlwaysStandByMasters; 112 this.masterClass = masterClass; 113 this.numRegionServers = numRegionServers; 114 this.rsPorts = rsPorts; 115 this.rsClass = rsClass; 116 this.numDataNodes = numDataNodes; 117 this.dataNodeHosts = dataNodeHosts; 118 this.numZkServers = numZkServers; 119 this.createRootDir = createRootDir; 120 this.createWALDir = createWALDir; 121 } 122 123 public int getNumMasters() { 124 return numMasters; 125 } 126 127 public int getNumAlwaysStandByMasters() { 128 return numAlwaysStandByMasters; 129 } 130 131 public Class<? extends HMaster> getMasterClass() { 132 return masterClass; 133 } 134 135 public int getNumRegionServers() { 136 return numRegionServers; 137 } 138 139 public List<Integer> getRsPorts() { 140 return rsPorts; 141 } 142 143 public Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> getRsClass() { 144 return rsClass; 145 } 146 147 public int getNumDataNodes() { 148 return numDataNodes; 149 } 150 151 public String[] getDataNodeHosts() { 152 return dataNodeHosts; 153 } 154 155 public int getNumZkServers() { 156 return numZkServers; 157 } 158 159 public boolean isCreateRootDir() { 160 return createRootDir; 161 } 162 163 public boolean isCreateWALDir() { 164 return createWALDir; 165 } 166 167 @Override 168 public String toString() { 169 return "StartMiniClusterOption{" + "numMasters=" + numMasters + ", masterClass=" + masterClass 170 + ", numRegionServers=" + numRegionServers + ", rsPorts=" + StringUtils.join(rsPorts) 171 + ", rsClass=" + rsClass + ", numDataNodes=" + numDataNodes + ", dataNodeHosts=" 172 + Arrays.toString(dataNodeHosts) + ", numZkServers=" + numZkServers + ", createRootDir=" 173 + createRootDir + ", createWALDir=" + createWALDir + '}'; 174 } 175 176 /** Returns a new builder. */ 177 public static Builder builder() { 178 return new Builder(); 179 } 180 181 /** 182 * Builder pattern for creating an {@link StartMiniClusterOption}. The default values of its 183 * fields should be considered public and constant. Changing the default values may cause other 184 * tests fail. 185 */ 186 public static final class Builder { 187 private int numMasters = 1; 188 private int numAlwaysStandByMasters = 0; 189 private Class<? extends HMaster> masterClass = null; 190 private int numRegionServers = 1; 191 private List<Integer> rsPorts = null; 192 private Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> rsClass = null; 193 private int numDataNodes = 1; 194 private String[] dataNodeHosts = null; 195 private int numZkServers = 1; 196 private boolean createRootDir = false; 197 private boolean createWALDir = false; 198 199 private Builder() { 200 } 201 202 public StartMiniClusterOption build() { 203 if (dataNodeHosts != null && dataNodeHosts.length != 0) { 204 numDataNodes = dataNodeHosts.length; 205 } 206 return new StartMiniClusterOption(numMasters, numAlwaysStandByMasters, masterClass, 207 numRegionServers, rsPorts, rsClass, numDataNodes, dataNodeHosts, numZkServers, 208 createRootDir, createWALDir); 209 } 210 211 public Builder numMasters(int numMasters) { 212 this.numMasters = numMasters; 213 return this; 214 } 215 216 public Builder numAlwaysStandByMasters(int numAlwaysStandByMasters) { 217 this.numAlwaysStandByMasters = numAlwaysStandByMasters; 218 return this; 219 } 220 221 public Builder masterClass(Class<? extends HMaster> masterClass) { 222 this.masterClass = masterClass; 223 return this; 224 } 225 226 public Builder numRegionServers(int numRegionServers) { 227 this.numRegionServers = numRegionServers; 228 return this; 229 } 230 231 public Builder rsPorts(List<Integer> rsPorts) { 232 this.rsPorts = rsPorts; 233 return this; 234 } 235 236 public Builder rsClass(Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> rsClass) { 237 this.rsClass = rsClass; 238 return this; 239 } 240 241 public Builder numDataNodes(int numDataNodes) { 242 this.numDataNodes = numDataNodes; 243 return this; 244 } 245 246 public Builder dataNodeHosts(String[] dataNodeHosts) { 247 this.dataNodeHosts = dataNodeHosts; 248 return this; 249 } 250 251 public Builder numZkServers(int numZkServers) { 252 this.numZkServers = numZkServers; 253 return this; 254 } 255 256 public Builder numWorkers(int numWorkers) { 257 return numDataNodes(numWorkers).numRegionServers(numWorkers); 258 } 259 260 public Builder createRootDir(boolean createRootDir) { 261 this.createRootDir = createRootDir; 262 return this; 263 } 264 265 public Builder createWALDir(boolean createWALDir) { 266 this.createWALDir = createWALDir; 267 return this; 268 } 269 } 270 271}