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