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