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