blob: dad2d8319197f1e08c0661194f08c2339ed2ef90 [file] [log] [blame]
package org.apache.solr.cloud;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.solr.common.cloud.OnReconnect;
import org.apache.solr.common.cloud.SolrZkClient;
import org.apache.solr.core.ConfigSolr;
import org.apache.solr.core.SolrResourceLoader;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeoutException;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class ZkCLI {
private static final String MAKEPATH = "makepath";
private static final String PUT = "put";
private static final String DOWNCONFIG = "downconfig";
private static final String ZK_CLI_NAME = "ZkCLI";
private static final String HELP = "help";
private static final String LINKCONFIG = "linkconfig";
private static final String CONFDIR = "confdir";
private static final String CONFNAME = "confname";
private static final String REVERSE = "reverse";
private static final String ZKHOST = "zkhost";
private static final String RUNZK = "runzk";
private static final String SOLRHOME = "solrhome";
private static final String BOOTSTRAP = "bootstrap";
private static final String SOLR_XML = "solr.xml";
private static final String UPCONFIG = "upconfig";
private static final String COLLECTION = "collection";
private static final String CLEAR = "clear";
private static final String LIST = "list";
private static final String CMD = "cmd";
/**
* Allows you to perform a variety of zookeeper related tasks, such as:
*
* Bootstrap the current configs for all collections in solr.xml.
*
* Upload a named config set from a given directory.
*
* Link a named config set explicity to a collection.
*
* Clear ZooKeeper info.
*
* If you also pass a solrPort, it will be used to start an embedded zk useful
* for single machine, multi node tests.
*/
public static void main(String[] args) throws InterruptedException,
TimeoutException, IOException, ParserConfigurationException,
SAXException, KeeperException {
CommandLineParser parser = new PosixParser();
Options options = new Options();
options.addOption(OptionBuilder
.hasArg(true)
.withDescription(
"cmd to run: " + BOOTSTRAP + ", " + UPCONFIG + ", " + DOWNCONFIG
+ ", " + LINKCONFIG + ", " + MAKEPATH + ", "+ PUT + ", "+ LIST + ", " + CLEAR).create(CMD));
Option zkHostOption = new Option("z", ZKHOST, true,
"ZooKeeper host address");
options.addOption(zkHostOption);
Option solrHomeOption = new Option("s", SOLRHOME, true,
"for " + BOOTSTRAP + ", " + RUNZK + ": solrhome location");
options.addOption(zkHostOption);
options.addOption(solrHomeOption);
options.addOption("d", CONFDIR, true,
"for " + UPCONFIG + ": a directory of configuration files");
options.addOption("n", CONFNAME, true,
"for " + UPCONFIG + ", " + LINKCONFIG + ": name of the config set");
options.addOption("c", COLLECTION, true,
"for " + LINKCONFIG + ": name of the collection");
options
.addOption(
"r",
RUNZK,
true,
"run zk internally by passing the solr run port - only for clusters on one machine (tests, dev)");
options.addOption("h", HELP, false, "bring up this help page");
try {
// parse the command line arguments
CommandLine line = parser.parse(options, args);
if (line.hasOption(HELP) || !line.hasOption(ZKHOST)
|| !line.hasOption(CMD)) {
// automatically generate the help statement
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(ZK_CLI_NAME, options);
System.out.println("Examples:");
System.out.println("zkcli.sh -zkhost localhost:9983 -cmd " + BOOTSTRAP + " -" + SOLRHOME + " /opt/solr");
System.out.println("zkcli.sh -zkhost localhost:9983 -cmd " + UPCONFIG + " -" + CONFDIR + " /opt/solr/collection1/conf" + " -" + CONFNAME + " myconf");
System.out.println("zkcli.sh -zkhost localhost:9983 -cmd " + DOWNCONFIG + " -" + CONFDIR + " /opt/solr/collection1/conf" + " -" + CONFNAME + " myconf");
System.out.println("zkcli.sh -zkhost localhost:9983 -cmd " + LINKCONFIG + " -" + COLLECTION + " collection1" + " -" + CONFNAME + " myconf");
System.out.println("zkcli.sh -zkhost localhost:9983 -cmd " + MAKEPATH + " /apache/solr/data.txt 'config data'");
System.out.println("zkcli.sh -zkhost localhost:9983 -cmd " + PUT + " /solr.conf 'conf data'");
System.out.println("zkcli.sh -zkhost localhost:9983 -cmd " + CLEAR + " /solr");
System.out.println("zkcli.sh -zkhost localhost:9983 -cmd " + LIST);
return;
}
// start up a tmp zk server first
String zkServerAddress = line.getOptionValue(ZKHOST);
String solrHome = line.getOptionValue(SOLRHOME);
String solrPort = null;
if (line.hasOption(RUNZK)) {
if (!line.hasOption(SOLRHOME)) {
System.out
.println("-" + SOLRHOME + " is required for " + RUNZK);
System.exit(1);
}
solrPort = line.getOptionValue(RUNZK);
}
SolrZkServer zkServer = null;
if (solrPort != null) {
zkServer = new SolrZkServer("true", null, solrHome + "/zoo_data",
solrHome, solrPort);
zkServer.parseConfig();
zkServer.start();
}
SolrZkClient zkClient = null;
try {
zkClient = new SolrZkClient(zkServerAddress, 30000, 30000,
new OnReconnect() {
@Override
public void command() {}
});
if (line.getOptionValue(CMD).equals(BOOTSTRAP)) {
if (!line.hasOption(SOLRHOME)) {
System.out.println("-" + SOLRHOME
+ " is required for " + BOOTSTRAP);
System.exit(1);
}
SolrResourceLoader loader = new SolrResourceLoader(solrHome);
solrHome = loader.getInstanceDir();
ConfigSolr cfg = ConfigSolr.fromSolrHome(solrHome);
if(!ZkController.checkChrootPath(zkServerAddress, true)) {
System.out.println("A chroot was specified in zkHost but the znode doesn't exist. ");
System.exit(1);
}
ZkController.bootstrapConf(zkClient, cfg, solrHome);
} else if (line.getOptionValue(CMD).equals(UPCONFIG)) {
if (!line.hasOption(CONFDIR) || !line.hasOption(CONFNAME)) {
System.out.println("-" + CONFDIR + " and -" + CONFNAME
+ " are required for " + UPCONFIG);
System.exit(1);
}
String confDir = line.getOptionValue(CONFDIR);
String confName = line.getOptionValue(CONFNAME);
if(!ZkController.checkChrootPath(zkServerAddress, true)) {
System.out.println("A chroot was specified in zkHost but the znode doesn't exist. ");
System.exit(1);
}
ZkController.uploadConfigDir(zkClient, new File(confDir), confName);
} else if (line.getOptionValue(CMD).equals(DOWNCONFIG)) {
if (!line.hasOption(CONFDIR) || !line.hasOption(CONFNAME)) {
System.out.println("-" + CONFDIR + " and -" + CONFNAME
+ " are required for " + DOWNCONFIG);
System.exit(1);
}
String confDir = line.getOptionValue(CONFDIR);
String confName = line.getOptionValue(CONFNAME);
ZkController.downloadConfigDir(zkClient, confName, new File(confDir));
} else if (line.getOptionValue(CMD).equals(LINKCONFIG)) {
if (!line.hasOption(COLLECTION) || !line.hasOption(CONFNAME)) {
System.out.println("-" + CONFDIR + " and -" + CONFNAME
+ " are required for " + LINKCONFIG);
System.exit(1);
}
String collection = line.getOptionValue(COLLECTION);
String confName = line.getOptionValue(CONFNAME);
ZkController.linkConfSet(zkClient, collection, confName);
} else if (line.getOptionValue(CMD).equals(LIST)) {
zkClient.printLayoutToStdOut();
} else if (line.getOptionValue(CMD).equals(CLEAR)) {
List arglist = line.getArgList();
if (arglist.size() != 1) {
System.out.println("-" + CLEAR + " requires one arg - the path to clear");
System.exit(1);
}
zkClient.clean(arglist.get(0).toString());
} else if (line.getOptionValue(CMD).equals(MAKEPATH)) {
List arglist = line.getArgList();
if (arglist.size() != 1) {
System.out.println("-" + MAKEPATH + " requires one arg - the path to make");
System.exit(1);
}
zkClient.makePath(arglist.get(0).toString(), true);
} else if (line.getOptionValue(CMD).equals(PUT)) {
List<ACL> acl = ZooDefs.Ids.OPEN_ACL_UNSAFE;
List arglist = line.getArgList();
if (arglist.size() != 2) {
System.out.println("-" + PUT + " requires two args - the path to create and the data string");
System.exit(1);
}
zkClient.create(arglist.get(0).toString(), arglist.get(1).toString().getBytes("UTF-8"),
acl, CreateMode.PERSISTENT, true);
}
} finally {
if (solrPort != null) {
zkServer.stop();
}
if (zkClient != null) {
zkClient.close();
}
}
} catch (ParseException exp) {
System.out.println("Unexpected exception:" + exp.getMessage());
}
}
}