View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.master;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.util.List;
25  
26  import org.apache.commons.cli.CommandLine;
27  import org.apache.commons.cli.GnuParser;
28  import org.apache.commons.cli.Options;
29  import org.apache.commons.cli.ParseException;
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.hadoop.conf.Configuration;
33  import org.apache.hadoop.hbase.HConstants;
34  import org.apache.hadoop.hbase.LocalHBaseCluster;
35  import org.apache.hadoop.hbase.MasterNotRunningException;
36  import org.apache.hadoop.hbase.ZooKeeperConnectionException;
37  import org.apache.hadoop.hbase.client.HBaseAdmin;
38  import org.apache.hadoop.hbase.regionserver.HRegionServer;
39  import org.apache.hadoop.hbase.util.JVMClusterUtil;
40  import org.apache.hadoop.hbase.util.ServerCommandLine;
41  import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster;
42  import org.apache.hadoop.hbase.zookeeper.ZKUtil;
43  import org.apache.zookeeper.KeeperException;
44  
45  public class HMasterCommandLine extends ServerCommandLine {
46    private static final Log LOG = LogFactory.getLog(HMasterCommandLine.class);
47  
48    private static final String USAGE =
49      "Usage: Master [opts] start|stop\n" +
50      " start  Start Master. If local mode, start Master and RegionServer in same JVM\n" +
51      " stop   Start cluster shutdown; Master signals RegionServer shutdown\n" +
52      " where [opts] are:\n" +
53      "   --minServers=<servers>    Minimum RegionServers needed to host user tables.\n" +
54      "   --backup                  Master should start in backup mode";
55  
56    private final Class<? extends HMaster> masterClass;
57  
58    public HMasterCommandLine(Class<? extends HMaster> masterClass) {
59      this.masterClass = masterClass;
60    }
61  
62    protected String getUsage() {
63      return USAGE;
64    }
65  
66  
67    public int run(String args[]) throws Exception {
68      Options opt = new Options();
69      opt.addOption("minServers", true, "Minimum RegionServers needed to host user tables");
70      opt.addOption("backup", false, "Do not try to become HMaster until the primary fails");
71  
72  
73      CommandLine cmd;
74      try {
75        cmd = new GnuParser().parse(opt, args);
76      } catch (ParseException e) {
77        LOG.error("Could not parse: ", e);
78        usage(null);
79        return -1;
80      }
81  
82  
83      if (cmd.hasOption("minServers")) {
84        String val = cmd.getOptionValue("minServers");
85        getConf().setInt("hbase.regions.server.count.min",
86                    Integer.valueOf(val));
87        LOG.debug("minServers set to " + val);
88      }
89  
90      // check if we are the backup master - override the conf if so
91      if (cmd.hasOption("backup")) {
92        getConf().setBoolean(HConstants.MASTER_TYPE_BACKUP, true);
93      }
94  
95      List<String> remainingArgs = cmd.getArgList();
96      if (remainingArgs.size() != 1) {
97        usage(null);
98        return -1;
99      }
100 
101     String command = remainingArgs.get(0);
102 
103     if ("start".equals(command)) {
104       return startMaster();
105     } else if ("stop".equals(command)) {
106       return stopMaster();
107     } else {
108       usage("Invalid command: " + command);
109       return -1;
110     }
111   }
112 
113   private int startMaster() {
114     Configuration conf = getConf();
115     try {
116       // If 'local', defer to LocalHBaseCluster instance.  Starts master
117       // and regionserver both in the one JVM.
118       if (LocalHBaseCluster.isLocal(conf)) {
119         final MiniZooKeeperCluster zooKeeperCluster =
120           new MiniZooKeeperCluster();
121         File zkDataPath = new File(conf.get(HConstants.ZOOKEEPER_DATA_DIR));
122         int zkClientPort = conf.getInt(HConstants.ZOOKEEPER_CLIENT_PORT, 0);
123         if (zkClientPort == 0) {
124           throw new IOException("No config value for "
125               + HConstants.ZOOKEEPER_CLIENT_PORT);
126         }
127         zooKeeperCluster.setDefaultClientPort(zkClientPort);
128 
129         // login the zookeeper server principal (if using security)
130         ZKUtil.loginServer(conf, "hbase.zookeeper.server.keytab.file",
131           "hbase.zookeeper.server.kerberos.principal", null);
132 
133         int clientPort = zooKeeperCluster.startup(zkDataPath);
134         if (clientPort != zkClientPort) {
135           String errorMsg = "Could not start ZK at requested port of " +
136             zkClientPort + ".  ZK was started at port: " + clientPort +
137             ".  Aborting as clients (e.g. shell) will not be able to find " +
138             "this ZK quorum.";
139           System.err.println(errorMsg);
140           throw new IOException(errorMsg);
141         }
142         conf.set(HConstants.ZOOKEEPER_CLIENT_PORT,
143                  Integer.toString(clientPort));
144         // Need to have the zk cluster shutdown when master is shutdown.
145         // Run a subclass that does the zk cluster shutdown on its way out.
146         LocalHBaseCluster cluster = new LocalHBaseCluster(conf, 1, 1,
147                                                           LocalHMaster.class, HRegionServer.class);
148         ((LocalHMaster)cluster.getMaster(0)).setZKCluster(zooKeeperCluster);
149         cluster.startup();
150         waitOnMasterThreads(cluster);
151       } else {
152         HMaster master = HMaster.constructMaster(masterClass, conf);
153         if (master.isStopped()) {
154           LOG.info("Won't bring the Master up as a shutdown is requested");
155           return -1;
156         }
157         master.start();
158         master.join();
159         if(master.isAborted())
160           throw new RuntimeException("HMaster Aborted");
161       }
162     } catch (Throwable t) {
163       LOG.error("Failed to start master", t);
164       return -1;
165     }
166     return 0;
167   }
168 
169   private int stopMaster() {
170     HBaseAdmin adm = null;
171     try {
172       Configuration conf = getConf();
173       // Don't try more than once
174       conf.setInt("hbase.client.retries.number", 1);
175       adm = new HBaseAdmin(getConf());
176     } catch (MasterNotRunningException e) {
177       LOG.error("Master not running");
178       return -1;
179     } catch (ZooKeeperConnectionException e) {
180       LOG.error("ZooKeeper not available");
181       return -1;
182     }
183     try {
184       adm.shutdown();
185     } catch (Throwable t) {
186       LOG.error("Failed to stop master", t);
187       return -1;
188     }
189     return 0;
190   }
191 
192   private void waitOnMasterThreads(LocalHBaseCluster cluster) throws InterruptedException{
193     List<JVMClusterUtil.MasterThread> masters = cluster.getMasters();
194     List<JVMClusterUtil.RegionServerThread> regionservers = cluster.getRegionServers();
195 	  
196     if (masters != null) { 
197       for (JVMClusterUtil.MasterThread t : masters) {
198         t.join();
199         if(t.getMaster().isAborted()) {
200           closeAllRegionServerThreads(regionservers);
201           throw new RuntimeException("HMaster Aborted");
202         }
203       }
204     }
205   }
206 
207   private static void closeAllRegionServerThreads(List<JVMClusterUtil.RegionServerThread> regionservers) {
208     for(JVMClusterUtil.RegionServerThread t : regionservers){
209       t.getRegionServer().stop("HMaster Aborted; Bringing down regions servers");
210     }
211   }
212   
213   /*
214    * Version of master that will shutdown the passed zk cluster on its way out.
215    */
216   public static class LocalHMaster extends HMaster {
217     private MiniZooKeeperCluster zkcluster = null;
218 
219     public LocalHMaster(Configuration conf)
220     throws IOException, KeeperException, InterruptedException {
221       super(conf);
222     }
223 
224     @Override
225     public void run() {
226       super.run();
227       if (this.zkcluster != null) {
228         try {
229           this.zkcluster.shutdown();
230         } catch (IOException e) {
231           e.printStackTrace();
232         }
233       }
234     }
235 
236     void setZKCluster(final MiniZooKeeperCluster zkcluster) {
237       this.zkcluster = zkcluster;
238     }
239   }
240 }