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