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";
65
66 private final Class<? extends HMaster> masterClass;
67
68 public HMasterCommandLine(Class<? extends HMaster> masterClass) {
69 this.masterClass = masterClass;
70 }
71
72 @Override
73 protected String getUsage() {
74 return USAGE;
75 }
76
77 @Override
78 public int run(String args[]) throws Exception {
79 Options opt = new Options();
80 opt.addOption("localRegionServers", true,
81 "RegionServers to start in master process when running standalone");
82 opt.addOption("masters", true, "Masters to start in this process");
83 opt.addOption("minRegionServers", true, "Minimum RegionServers needed to host user tables");
84 opt.addOption("backup", false, "Do not try to become HMaster until the primary fails");
85
86 CommandLine cmd;
87 try {
88 cmd = new GnuParser().parse(opt, args);
89 } catch (ParseException e) {
90 LOG.error("Could not parse: ", e);
91 usage(null);
92 return 1;
93 }
94
95
96 if (cmd.hasOption("minRegionServers")) {
97 String val = cmd.getOptionValue("minRegionServers");
98 getConf().setInt("hbase.regions.server.count.min", Integer.parseInt(val));
99 LOG.debug("minRegionServers set to " + val);
100 }
101
102
103 if (cmd.hasOption("minServers")) {
104 String val = cmd.getOptionValue("minServers");
105 getConf().setInt("hbase.regions.server.count.min", Integer.parseInt(val));
106 LOG.debug("minServers set to " + val);
107 }
108
109
110 if (cmd.hasOption("backup")) {
111 getConf().setBoolean(HConstants.MASTER_TYPE_BACKUP, true);
112 }
113
114
115
116 if (cmd.hasOption("localRegionServers")) {
117 String val = cmd.getOptionValue("localRegionServers");
118 getConf().setInt("hbase.regionservers", Integer.parseInt(val));
119 LOG.debug("localRegionServers set to " + val);
120 }
121
122 if (cmd.hasOption("masters")) {
123 String val = cmd.getOptionValue("masters");
124 getConf().setInt("hbase.masters", Integer.parseInt(val));
125 LOG.debug("masters set to " + val);
126 }
127
128 @SuppressWarnings("unchecked")
129 List<String> remainingArgs = cmd.getArgList();
130 if (remainingArgs.size() != 1) {
131 usage(null);
132 return 1;
133 }
134
135 String command = remainingArgs.get(0);
136
137 if ("start".equals(command)) {
138 return startMaster();
139 } else if ("stop".equals(command)) {
140 return stopMaster();
141 } else if ("clear".equals(command)) {
142 return (ZNodeClearer.clear(getConf()) ? 0 : 1);
143 } else {
144 usage("Invalid command: " + command);
145 return 1;
146 }
147 }
148
149 private int startMaster() {
150 Configuration conf = getConf();
151 try {
152
153
154 if (LocalHBaseCluster.isLocal(conf)) {
155 DefaultMetricsSystem.setMiniClusterMode(true);
156 final MiniZooKeeperCluster zooKeeperCluster = new MiniZooKeeperCluster(conf);
157 File zkDataPath = new File(conf.get(HConstants.ZOOKEEPER_DATA_DIR));
158
159
160 int zkClientPort = 0;
161
162
163 String zkserver = conf.get(HConstants.ZOOKEEPER_QUORUM);
164 if (zkserver != null) {
165 String[] zkservers = zkserver.split(",");
166
167 if (zkservers.length > 1) {
168
169
170 String errorMsg = "Could not start ZK with " + zkservers.length +
171 " ZK servers in local mode deployment. Aborting as clients (e.g. shell) will not "
172 + "be able to find this ZK quorum.";
173 System.err.println(errorMsg);
174 throw new IOException(errorMsg);
175 }
176
177 String[] parts = zkservers[0].split(":");
178
179 if (parts.length == 2) {
180
181 zkClientPort = Integer.parseInt(parts [1]);
182 }
183 }
184
185 if (zkClientPort == 0) {
186 zkClientPort = conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 0);
187
188 if (zkClientPort == 0) {
189 throw new IOException("No config value for " + HConstants.ZOOKEEPER_CLIENT_PORT);
190 }
191 }
192 zooKeeperCluster.setDefaultClientPort(zkClientPort);
193
194 int zkTickTime = conf.getInt(HConstants.ZOOKEEPER_TICK_TIME, 0);
195 if (zkTickTime > 0) {
196 zooKeeperCluster.setTickTime(zkTickTime);
197 }
198
199
200 ZKUtil.loginServer(conf, HConstants.ZK_SERVER_KEYTAB_FILE,
201 HConstants.ZK_SERVER_KERBEROS_PRINCIPAL, null);
202 int localZKClusterSessionTimeout =
203 conf.getInt(HConstants.ZK_SESSION_TIMEOUT + ".localHBaseCluster", 10*1000);
204 conf.setInt(HConstants.ZK_SESSION_TIMEOUT, localZKClusterSessionTimeout);
205 LOG.info("Starting a zookeeper cluster");
206 int clientPort = zooKeeperCluster.startup(zkDataPath);
207 if (clientPort != zkClientPort) {
208 String errorMsg = "Could not start ZK at requested port of " +
209 zkClientPort + ". ZK was started at port: " + clientPort +
210 ". Aborting as clients (e.g. shell) will not be able to find " +
211 "this ZK quorum.";
212 System.err.println(errorMsg);
213 throw new IOException(errorMsg);
214 }
215 conf.set(HConstants.ZOOKEEPER_CLIENT_PORT, Integer.toString(clientPort));
216
217
218
219 int mastersCount = conf.getInt("hbase.masters", 1);
220 int regionServersCount = conf.getInt("hbase.regionservers", 1);
221
222 conf.setIfUnset("hbase.master.start.timeout.localHBaseCluster", "300000");
223 LOG.info("Starting up instance of localHBaseCluster; master=" + mastersCount +
224 ", regionserversCount=" + regionServersCount);
225 LocalHBaseCluster cluster = new LocalHBaseCluster(conf, mastersCount, regionServersCount,
226 LocalHMaster.class, HRegionServer.class);
227 ((LocalHMaster)cluster.getMaster(0)).setZKCluster(zooKeeperCluster);
228 cluster.startup();
229 waitOnMasterThreads(cluster);
230 } else {
231 logProcessInfo(getConf());
232 CoordinatedStateManager csm =
233 CoordinatedStateManagerFactory.getCoordinatedStateManager(conf);
234 HMaster master = HMaster.constructMaster(masterClass, conf, csm);
235 if (master.isStopped()) {
236 LOG.info("Won't bring the Master up as a shutdown is requested");
237 return 1;
238 }
239 master.start();
240 master.join();
241 if(master.isAborted())
242 throw new RuntimeException("HMaster Aborted");
243 }
244 } catch (Throwable t) {
245 LOG.error("Master exiting", t);
246 return 1;
247 }
248 return 0;
249 }
250
251 @SuppressWarnings("resource")
252 private int stopMaster() {
253 Admin adm = null;
254 try {
255 Configuration conf = getConf();
256
257 conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
258 adm = new HBaseAdmin(getConf());
259 adm.shutdown();
260 } catch (MasterNotRunningException e) {
261 LOG.error("Master not running");
262 return 1;
263 } catch (ZooKeeperConnectionException e) {
264 LOG.error("ZooKeeper not available");
265 return 1;
266 } catch (IOException e) {
267 LOG.error("Got IOException: " +e.getMessage(), e);
268 return 1;
269 } catch (Throwable t) {
270 LOG.error("Failed to stop master", t);
271 return 1;
272 } finally {
273 if (adm != null) {
274 try {
275 adm.close();
276 } catch (Throwable t) {
277 LOG.error("Failed to close Admin", t);
278 return 1;
279 }
280 }
281 }
282 return 0;
283 }
284
285 private void waitOnMasterThreads(LocalHBaseCluster cluster) throws InterruptedException{
286 List<JVMClusterUtil.MasterThread> masters = cluster.getMasters();
287 List<JVMClusterUtil.RegionServerThread> regionservers = cluster.getRegionServers();
288
289 if (masters != null) {
290 for (JVMClusterUtil.MasterThread t : masters) {
291 t.join();
292 if(t.getMaster().isAborted()) {
293 closeAllRegionServerThreads(regionservers);
294 throw new RuntimeException("HMaster Aborted");
295 }
296 }
297 }
298 }
299
300 private static void closeAllRegionServerThreads(
301 List<JVMClusterUtil.RegionServerThread> regionservers) {
302 for(JVMClusterUtil.RegionServerThread t : regionservers){
303 t.getRegionServer().stop("HMaster Aborted; Bringing down regions servers");
304 }
305 }
306
307
308
309
310 public static class LocalHMaster extends HMaster {
311 private MiniZooKeeperCluster zkcluster = null;
312
313 public LocalHMaster(Configuration conf, CoordinatedStateManager csm)
314 throws IOException, KeeperException, InterruptedException {
315 super(conf, csm);
316 }
317
318 @Override
319 public void run() {
320 super.run();
321 if (this.zkcluster != null) {
322 try {
323 this.zkcluster.shutdown();
324 } catch (IOException e) {
325 e.printStackTrace();
326 }
327 }
328 }
329
330 void setZKCluster(final MiniZooKeeperCluster zkcluster) {
331 this.zkcluster = zkcluster;
332 }
333 }
334 }