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.IOException;
23  import java.io.File;
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.HBaseConfiguration;
34  import org.apache.hadoop.hbase.HConstants;
35  import org.apache.hadoop.hbase.LocalHBaseCluster;
36  import org.apache.hadoop.hbase.MasterNotRunningException;
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.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.setTickTime(conf.getInt("hbase.zookeeper.property.tickTime", 3000));
125         zooKeeperCluster.setClientPort(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,
139                                                           LocalHMaster.class, HRegionServer.class);
140         ((LocalHMaster)cluster.getMaster()).setZKCluster(zooKeeperCluster);
141         cluster.startup();
142       } else {
143         HMaster master = HMaster.constructMaster(masterClass, conf);
144         if (master.getShutdownRequested().get()) {
145           LOG.info("Won't bring the Master up as a shutdown is requested");
146           return -1;
147         }
148         master.start();
149         master.join();
150       }
151     } catch (Throwable t) {
152       LOG.error("Failed to start master", t);
153       return -1;
154     }
155     return 0;
156   }
157 
158   private int stopMaster() {
159     HBaseAdmin adm = null;
160     try {
161       adm = new HBaseAdmin(getConf());
162     } catch (MasterNotRunningException e) {
163       LOG.error("Master not running");
164       return -1;
165     }
166     try {
167       adm.shutdown();
168     } catch (Throwable t) {
169       LOG.error("Failed to stop master", t);
170       return -1;
171     }
172     return 0;
173   }
174 
175   /*
176    * Version of master that will shutdown the passed zk cluster on its way out.
177    */
178   static class LocalHMaster extends HMaster {
179     private MiniZooKeeperCluster zkcluster = null;
180 
181     public LocalHMaster(Configuration conf)
182     throws IOException, KeeperException, InterruptedException {
183       super(conf);
184     }
185 
186     @Override
187     public void run() {
188       super.run();
189       if (this.zkcluster != null) {
190         try {
191           this.zkcluster.shutdown();
192         } catch (IOException e) {
193           e.printStackTrace();
194         }
195       }
196     }
197 
198     void setZKCluster(final MiniZooKeeperCluster zkcluster) {
199       this.zkcluster = zkcluster;
200     }
201   }
202 }