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 * The class to use as HMaster, or null for default. 051 */ 052 private final Class<? extends HMaster> masterClass; 053 054 /** 055 * Number of region servers to start up. 056 * If this value is > 1, then make sure config "hbase.regionserver.info.port" is -1 057 * (i.e. no ui per regionserver) otherwise bind errors. 058 */ 059 private final int numRegionServers; 060 /** 061 * Ports that RegionServer should use. Pass ports if you want to test cluster restart where for 062 * sure the regionservers come up on same address+port (but just with different startcode); by 063 * default mini hbase clusters choose new arbitrary ports on each cluster start. 064 */ 065 private final List<Integer> rsPorts; 066 /** 067 * The class to use as HRegionServer, or null for default. 068 */ 069 private Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> rsClass; 070 071 /** 072 * Number of datanodes. Used to create mini DSF cluster. Surpassed by {@link #dataNodeHosts} size. 073 */ 074 private final int numDataNodes; 075 /** 076 * The hostnames of DataNodes to run on. This is useful if you want to run datanode on distinct 077 * hosts for things like HDFS block location verification. If you start MiniDFSCluster without 078 * host names, all instances of the datanodes will have the same host name. 079 */ 080 private final String[] dataNodeHosts; 081 082 /** 083 * Number of Zookeeper servers. 084 */ 085 private final int numZkServers; 086 087 /** 088 * Whether to create a new root or data directory path. If true, the newly created data directory 089 * will be configured as HBase rootdir. This will overwrite existing root directory config. 090 */ 091 private final boolean createRootDir; 092 093 /** 094 * Whether to create a new WAL directory. If true, the newly created directory will be configured 095 * as HBase wal.dir which is separate from HBase rootdir. 096 */ 097 private final boolean createWALDir; 098 099 /** 100 * Private constructor. Use {@link Builder#build()}. 101 */ 102 private StartMiniClusterOption(int numMasters, Class<? extends HMaster> masterClass, 103 int numRegionServers, List<Integer> rsPorts, 104 Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> rsClass, int numDataNodes, 105 String[] dataNodeHosts, int numZkServers, boolean createRootDir, boolean createWALDir) { 106 this.numMasters = numMasters; 107 this.masterClass = masterClass; 108 this.numRegionServers = numRegionServers; 109 this.rsPorts = rsPorts; 110 this.rsClass = rsClass; 111 this.numDataNodes = numDataNodes; 112 this.dataNodeHosts = dataNodeHosts; 113 this.numZkServers = numZkServers; 114 this.createRootDir = createRootDir; 115 this.createWALDir = createWALDir; 116 } 117 118 public int getNumMasters() { 119 return numMasters; 120 } 121 122 public Class<? extends HMaster> getMasterClass() { 123 return masterClass; 124 } 125 126 public int getNumRegionServers() { 127 return numRegionServers; 128 } 129 130 public List<Integer> getRsPorts() { 131 return rsPorts; 132 } 133 134 public Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> getRsClass() { 135 return rsClass; 136 } 137 138 public int getNumDataNodes() { 139 return numDataNodes; 140 } 141 142 public String[] getDataNodeHosts() { 143 return dataNodeHosts; 144 } 145 146 public int getNumZkServers() { 147 return numZkServers; 148 } 149 150 public boolean isCreateRootDir() { 151 return createRootDir; 152 } 153 154 public boolean isCreateWALDir() { 155 return createWALDir; 156 } 157 158 @Override 159 public String toString() { 160 return "StartMiniClusterOption{" + "numMasters=" + numMasters + ", masterClass=" + masterClass 161 + ", numRegionServers=" + numRegionServers + ", rsPorts=" + StringUtils.join(rsPorts) 162 + ", rsClass=" + rsClass + ", numDataNodes=" + numDataNodes 163 + ", dataNodeHosts=" + Arrays.toString(dataNodeHosts) + ", numZkServers=" + numZkServers 164 + ", createRootDir=" + createRootDir + ", createWALDir=" + createWALDir + '}'; 165 } 166 167 /** 168 * @return a new builder. 169 */ 170 public static Builder builder() { 171 return new Builder(); 172 } 173 174 /** 175 * Builder pattern for creating an {@link StartMiniClusterOption}. 176 * 177 * The default values of its fields should be considered public and constant. Changing the default 178 * values may cause other tests fail. 179 */ 180 public static final class Builder { 181 private int numMasters = 1; 182 private Class<? extends HMaster> masterClass = null; 183 private int numRegionServers = 1; 184 private List<Integer> rsPorts = null; 185 private Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> rsClass = null; 186 private int numDataNodes = 1; 187 private String[] dataNodeHosts = null; 188 private int numZkServers = 1; 189 private boolean createRootDir = false; 190 private boolean createWALDir = false; 191 192 private Builder() { 193 } 194 195 public StartMiniClusterOption build() { 196 if (dataNodeHosts != null && dataNodeHosts.length != 0) { 197 numDataNodes = dataNodeHosts.length; 198 } 199 return new StartMiniClusterOption(numMasters, masterClass, numRegionServers, rsPorts, rsClass, 200 numDataNodes, dataNodeHosts, numZkServers, createRootDir, createWALDir); 201 } 202 203 public Builder numMasters(int numMasters) { 204 this.numMasters = numMasters; 205 return this; 206 } 207 208 public Builder masterClass(Class<? extends HMaster> masterClass) { 209 this.masterClass = masterClass; 210 return this; 211 } 212 213 public Builder numRegionServers(int numRegionServers) { 214 this.numRegionServers = numRegionServers; 215 return this; 216 } 217 218 public Builder rsPorts(List<Integer> rsPorts) { 219 this.rsPorts = rsPorts; 220 return this; 221 } 222 223 public Builder rsClass(Class<? extends MiniHBaseCluster.MiniHBaseClusterRegionServer> rsClass) { 224 this.rsClass = rsClass; 225 return this; 226 } 227 228 public Builder numDataNodes(int numDataNodes) { 229 this.numDataNodes = numDataNodes; 230 return this; 231 } 232 233 public Builder dataNodeHosts(String[] dataNodeHosts) { 234 this.dataNodeHosts = dataNodeHosts; 235 return this; 236 } 237 238 public Builder numZkServers(int numZkServers) { 239 this.numZkServers = numZkServers; 240 return this; 241 } 242 243 public Builder createRootDir(boolean createRootDir) { 244 this.createRootDir = createRootDir; 245 return this; 246 } 247 248 public Builder createWALDir(boolean createWALDir) { 249 this.createWALDir = createWALDir; 250 return this; 251 } 252 } 253 254}