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