001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.zookeeper; 019 020import java.io.Closeable; 021import java.io.IOException; 022import org.apache.hadoop.conf.Configuration; 023import org.apache.hadoop.hbase.HBaseConfiguration; 024import org.apache.hadoop.hbase.HBaseInterfaceAudience; 025import org.apache.hadoop.hbase.ZooKeeperConnectionException; 026import org.apache.yetus.audience.InterfaceAudience; 027import org.apache.zookeeper.ZooKeeperMain; 028import org.apache.zookeeper.cli.CliException; 029 030/** 031 * Tool for running ZookeeperMain from HBase by reading a ZooKeeper server from HBase XML 032 * configuration. 033 */ 034@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.TOOLS) 035public class ZKMainServer { 036 private static final String SERVER_ARG = "-server"; 037 038 public String parse(final Configuration c) { 039 return ZKConfig.getZKQuorumServersString(c); 040 } 041 042 /** 043 * ZooKeeper 3.4.6 broke being able to pass commands on command line. See ZOOKEEPER-1897, 044 * ZOOKEEPER-4804. This class is a hack to restore this faclity. 045 */ 046 private static class HACK_UNTIL_ZOOKEEPER_1897_ZooKeeperMain extends ZooKeeperMain 047 implements Closeable { 048 public HACK_UNTIL_ZOOKEEPER_1897_ZooKeeperMain(String[] args) 049 throws IOException, InterruptedException { 050 super(args); 051 // Make sure we are connected before we proceed. Can take a while on some systems. If we 052 // run the command without being connected, we get ConnectionLoss KeeperErrorConnection... 053 // Make it 30seconds. We dont' have a config in this context and zk doesn't have 054 // a timeout until after connection. 30000ms is default for zk. 055 try { 056 ZooKeeperHelper.ensureConnectedZooKeeper(this.zk, 30000); 057 } catch (ZooKeeperConnectionException e) { 058 this.zk.close(); 059 } 060 } 061 062 /** 063 * Run the command-line args passed. Calls System.exit when done. 064 * @throws IOException in case of a network failure 065 * @throws InterruptedException if the ZooKeeper client closes 066 * @throws CliException if the ZooKeeper exception happens in cli command 067 */ 068 void runCmdLine() throws IOException, InterruptedException, CliException { 069 processCmd(this.cl); 070 System.exit(0); 071 } 072 073 @Override 074 public void close() throws IOException { 075 try { 076 this.zk.close(); 077 } catch (InterruptedException e) { 078 Thread.currentThread().interrupt(); 079 } 080 } 081 } 082 083 /** 084 * @param args the arguments to check 085 * @return True if argument strings have a '-server' in them. 086 */ 087 private static boolean hasServer(final String[] args) { 088 return args.length > 0 && args[0].equals(SERVER_ARG); 089 } 090 091 /** 092 * @param args the arguments to check for command-line arguments 093 * @return True if command-line arguments were passed. 094 */ 095 private static boolean hasCommandLineArguments(final String[] args) { 096 if (hasServer(args)) { 097 if (args.length < 2) { 098 throw new IllegalStateException("-server param but no value"); 099 } 100 101 return args.length > 2; 102 } 103 104 return args.length > 0; 105 } 106 107 /** 108 * Run the tool. 109 * @param args Command line arguments. First arg is path to zookeepers file. 110 */ 111 public static void main(String[] args) throws Exception { 112 String[] newArgs = args; 113 if (!hasServer(args)) { 114 // Add the zk ensemble from configuration if none passed on command-line. 115 Configuration conf = HBaseConfiguration.create(); 116 String hostport = new ZKMainServer().parse(conf); 117 if (hostport != null && hostport.length() > 0) { 118 newArgs = new String[args.length + 2]; 119 System.arraycopy(args, 0, newArgs, 2, args.length); 120 newArgs[0] = "-server"; 121 newArgs[1] = hostport; 122 } 123 } 124 // If command-line arguments, run our hack so they are executed. 125 // ZOOKEEPER-1897 was committed to zookeeper-3.4.6 but elsewhere in this class we say 126 // 3.4.6 breaks command-processing; TODO. 127 if (hasCommandLineArguments(args)) { 128 try (HACK_UNTIL_ZOOKEEPER_1897_ZooKeeperMain zkm = 129 new HACK_UNTIL_ZOOKEEPER_1897_ZooKeeperMain(newArgs)) { 130 zkm.runCmdLine(); 131 } 132 } else { 133 ZooKeeperMain.main(newArgs); 134 } 135 } 136}