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