1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.util.List;
24
25 import org.apache.commons.cli.CommandLine;
26 import org.apache.commons.cli.GnuParser;
27 import org.apache.commons.cli.Options;
28 import org.apache.commons.cli.ParseException;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.CoordinatedStateManager;
34 import org.apache.hadoop.hbase.CoordinatedStateManagerFactory;
35 import org.apache.hadoop.hbase.HConstants;
36 import org.apache.hadoop.hbase.LocalHBaseCluster;
37 import org.apache.hadoop.hbase.MasterNotRunningException;
38 import org.apache.hadoop.hbase.ZNodeClearer;
39 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
40 import org.apache.hadoop.hbase.client.Admin;
41 import org.apache.hadoop.hbase.client.HBaseAdmin;
42 import org.apache.hadoop.hbase.regionserver.HRegionServer;
43 import org.apache.hadoop.hbase.util.JVMClusterUtil;
44 import org.apache.hadoop.hbase.util.ServerCommandLine;
45 import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster;
46 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
47 import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
48 import org.apache.zookeeper.KeeperException;
49
50 @InterfaceAudience.Private
51 public class HMasterCommandLine extends ServerCommandLine {
52 private static final Log LOG = LogFactory.getLog(HMasterCommandLine.class);
53
54 private static final String USAGE =
55 "Usage: Master [opts] start|stop|clear\n" +
56 " start Start Master. If local mode, start Master and RegionServer in same JVM\n" +
57 " stop Start cluster shutdown; Master signals RegionServer shutdown\n" +
58 " clear Delete the master znode in ZooKeeper after a master crashes\n "+
59 " where [opts] are:\n" +
60 " --minRegionServers=<servers> Minimum RegionServers needed to host user tables.\n" +
61 " --localRegionServers=<servers> " +
62 "RegionServers to start in master process when in standalone mode.\n" +
63 " --masters=<servers> Masters to start in this process.\n" +
64 " --backup Master should start in backup mode\n" +
65 " --shutDownCluster " +
66 "Start Cluster shutdown; Master signals RegionServer shutdown";
67
68 private final Class<? extends HMaster> masterClass;
69
70 public HMasterCommandLine(Class<? extends HMaster> masterClass) {
71 this.masterClass = masterClass;
72 }
73
74 @Override
75 protected String getUsage() {
76 return USAGE;
77 }
78
79 @Override
80 public int run(String args[]) throws Exception {
81 boolean shutDownCluster = false;
82 Options opt = new Options();
83 opt.addOption("localRegionServers", true,
84 "RegionServers to start in master process when running standalone");
85 opt.addOption("masters", true, "Masters to start in this process");
86 opt.addOption("minRegionServers", true, "Minimum RegionServers needed to host user tables");
87 opt.addOption("backup", false, "Do not try to become HMaster until the primary fails");
88 opt.addOption("shutDownCluster", false, "`hbase master stop --shutDownCluster` shuts down cluster");
89
90 CommandLine cmd;
91 try {
92 cmd = new GnuParser().parse(opt, args);
93 } catch (ParseException e) {
94 LOG.error("Could not parse: ", e);
95 usage(null);
96 return 1;
97 }
98
99
100 if (cmd.hasOption("minRegionServers")) {
101 String val = cmd.getOptionValue("minRegionServers");
102 getConf().setInt("hbase.regions.server.count.min", Integer.parseInt(val));
103 LOG.debug("minRegionServers set to " + val);
104 }
105
106
107 if (cmd.hasOption("minServers")) {
108 String val = cmd.getOptionValue("minServers");
109 getConf().setInt("hbase.regions.server.count.min", Integer.parseInt(val));
110 LOG.debug("minServers set to " + val);
111 }
112
113
114 if (cmd.hasOption("backup")) {
115 getConf().setBoolean(HConstants.MASTER_TYPE_BACKUP, true);
116 }
117
118
119
120 if (cmd.hasOption("localRegionServers")) {
121 String val = cmd.getOptionValue("localRegionServers");
122 getConf().setInt("hbase.regionservers", Integer.parseInt(val));
123 LOG.debug("localRegionServers set to " + val);
124 }
125
126 if (cmd.hasOption("masters")) {
127 String val = cmd.getOptionValue("masters");
128 getConf().setInt("hbase.masters", Integer.parseInt(val));
129 LOG.debug("masters set to " + val);
130 }
131
132
133 if (cmd.hasOption("shutDownCluster")) {
134 shutDownCluster = true;
135 }
136
137 @SuppressWarnings("unchecked")
138 List<String> remainingArgs = cmd.getArgList();
139 if (remainingArgs.size() != 1) {
140 usage(null);
141 return 1;
142 }
143
144 String command = remainingArgs.get(0);
145
146 if ("start".equals(command)) {
147 return startMaster();
148 } else if ("stop".equals(command)) {
149 if (shutDownCluster) {
150 return stopMaster();
151 }
152 System.err.println(
153 "To shutdown the master run " +
154 "hbase-daemon.sh stop master or send a kill signal to " +
155 "the HMaster pid, " +
156 "and to stop HBase Cluster run \"stop-hbase.sh\" or \"hbase master stop --shutDownCluster\"");
157 return 1;
158 } else if ("clear".equals(command)) {
159 return (ZNodeClearer.clear(getConf()) ? 0 : 1);
160 } else {
161 usage("Invalid command: " + command);
162 return 1;
163 }
164 }
165
166 private int startMaster() {
167 Configuration conf = getConf();
168 try {
169
170
171 if (LocalHBaseCluster.isLocal(conf)) {
172 DefaultMetricsSystem.setMiniClusterMode(true);
173 final MiniZooKeeperCluster zooKeeperCluster = new MiniZooKeeperCluster(conf);
174 File zkDataPath = new File(conf.get(HConstants.ZOOKEEPER_DATA_DIR));
175
176
177 int zkClientPort = 0;
178
179
180 String zkserver = conf.get(HConstants.ZOOKEEPER_QUORUM);
181 if (zkserver != null) {
182 String[] zkservers = zkserver.split(",");
183
184 if (zkservers.length > 1) {
185
186
187 String errorMsg = "Could not start ZK with " + zkservers.length +
188 " ZK servers in local mode deployment. Aborting as clients (e.g. shell) will not "
189 + "be able to find this ZK quorum.";
190 System.err.println(errorMsg);
191 throw new IOException(errorMsg);
192 }
193
194 String[] parts = zkservers[0].split(":");
195
196 if (parts.length == 2) {
197
198 zkClientPort = Integer.parseInt(parts [1]);
199 }
200 }
201
202 if (zkClientPort == 0) {
203 zkClientPort = conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 0);
204
205 if (zkClientPort == 0) {
206 throw new IOException("No config value for " + HConstants.ZOOKEEPER_CLIENT_PORT);
207 }
208 }
209 zooKeeperCluster.setDefaultClientPort(zkClientPort);
210
211 int zkTickTime = conf.getInt(HConstants.ZOOKEEPER_TICK_TIME, 0);
212 if (zkTickTime > 0) {
213 zooKeeperCluster.setTickTime(zkTickTime);
214 }
215
216
217 ZKUtil.loginServer(conf, HConstants.ZK_SERVER_KEYTAB_FILE,
218 HConstants.ZK_SERVER_KERBEROS_PRINCIPAL, null);
219 int localZKClusterSessionTimeout =
220 conf.getInt(HConstants.ZK_SESSION_TIMEOUT + ".localHBaseCluster", 10*1000);
221 conf.setInt(HConstants.ZK_SESSION_TIMEOUT, localZKClusterSessionTimeout);
222 LOG.info("Starting a zookeeper cluster");
223 int clientPort = zooKeeperCluster.startup(zkDataPath);
224 if (clientPort != zkClientPort) {
225 String errorMsg = "Could not start ZK at requested port of " +
226 zkClientPort + ". ZK was started at port: " + clientPort +
227 ". Aborting as clients (e.g. shell) will not be able to find " +
228 "this ZK quorum.";
229 System.err.println(errorMsg);
230 throw new IOException(errorMsg);
231 }
232 conf.set(HConstants.ZOOKEEPER_CLIENT_PORT, Integer.toString(clientPort));
233
234
235
236 int mastersCount = conf.getInt("hbase.masters", 1);
237 int regionServersCount = conf.getInt("hbase.regionservers", 1);
238
239 conf.setIfUnset("hbase.master.start.timeout.localHBaseCluster", "300000");
240 LOG.info("Starting up instance of localHBaseCluster; master=" + mastersCount +
241 ", regionserversCount=" + regionServersCount);
242 LocalHBaseCluster cluster = new LocalHBaseCluster(conf, mastersCount, regionServersCount,
243 LocalHMaster.class, HRegionServer.class);
244 ((LocalHMaster)cluster.getMaster(0)).setZKCluster(zooKeeperCluster);
245 cluster.startup();
246 waitOnMasterThreads(cluster);
247 } else {
248 logProcessInfo(getConf());
249 CoordinatedStateManager csm =
250 CoordinatedStateManagerFactory.getCoordinatedStateManager(conf);
251 HMaster master = HMaster.constructMaster(masterClass, conf, csm);
252 if (master.isStopped()) {
253 LOG.info("Won't bring the Master up as a shutdown is requested");
254 return 1;
255 }
256 master.start();
257 master.join();
258 if(master.isAborted())
259 throw new RuntimeException("HMaster Aborted");
260 }
261 } catch (Throwable t) {
262 LOG.error("Master exiting", t);
263 return 1;
264 }
265 return 0;
266 }
267
268 @SuppressWarnings("resource")
269 private int stopMaster() {
270 Admin adm = null;
271 try {
272 Configuration conf = getConf();
273
274 conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
275 adm = new HBaseAdmin(getConf());
276 adm.shutdown();
277 } catch (MasterNotRunningException e) {
278 LOG.error("Master not running");
279 return 1;
280 } catch (ZooKeeperConnectionException e) {
281 LOG.error("ZooKeeper not available");
282 return 1;
283 } catch (IOException e) {
284 LOG.error("Got IOException: " +e.getMessage(), e);
285 return 1;
286 } catch (Throwable t) {
287 LOG.error("Failed to stop master", t);
288 return 1;
289 } finally {
290 if (adm != null) {
291 try {
292 adm.close();
293 } catch (Throwable t) {
294 LOG.error("Failed to close Admin", t);
295 return 1;
296 }
297 }
298 }
299 return 0;
300 }
301
302 private void waitOnMasterThreads(LocalHBaseCluster cluster) throws InterruptedException{
303 List<JVMClusterUtil.MasterThread> masters = cluster.getMasters();
304 List<JVMClusterUtil.RegionServerThread> regionservers = cluster.getRegionServers();
305
306 if (masters != null) {
307 for (JVMClusterUtil.MasterThread t : masters) {
308 t.join();
309 if(t.getMaster().isAborted()) {
310 closeAllRegionServerThreads(regionservers);
311 throw new RuntimeException("HMaster Aborted");
312 }
313 }
314 }
315 }
316
317 private static void closeAllRegionServerThreads(
318 List<JVMClusterUtil.RegionServerThread> regionservers) {
319 for(JVMClusterUtil.RegionServerThread t : regionservers){
320 t.getRegionServer().stop("HMaster Aborted; Bringing down regions servers");
321 }
322 }
323
324
325
326
327 public static class LocalHMaster extends HMaster {
328 private MiniZooKeeperCluster zkcluster = null;
329
330 public LocalHMaster(Configuration conf, CoordinatedStateManager csm)
331 throws IOException, KeeperException, InterruptedException {
332 super(conf, csm);
333 }
334
335 @Override
336 public void run() {
337 super.run();
338 if (this.zkcluster != null) {
339 try {
340 this.zkcluster.shutdown();
341 } catch (IOException e) {
342 e.printStackTrace();
343 }
344 }
345 }
346
347 void setZKCluster(final MiniZooKeeperCluster zkcluster) {
348 this.zkcluster = zkcluster;
349 }
350 }
351 }