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