|
@@ -0,0 +1,331 @@
|
|
|
+/*
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+
|
|
|
+package org.apache.ambari.logsearch.solr;
|
|
|
+
|
|
|
+import org.apache.commons.cli.CommandLine;
|
|
|
+import org.apache.commons.cli.CommandLineParser;
|
|
|
+import org.apache.commons.cli.DefaultParser;
|
|
|
+import org.apache.commons.cli.HelpFormatter;
|
|
|
+import org.apache.commons.cli.Option;
|
|
|
+import org.apache.commons.cli.Options;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+public class AmbariSolrCloudCLI {
|
|
|
+
|
|
|
+ private static final Logger LOG = LoggerFactory.getLogger(AmbariSolrCloudCLI.class);
|
|
|
+
|
|
|
+ private static final int ZK_CLIENT_TIMEOUT = 10000;
|
|
|
+ private static final int ZK_CLIENT_CONNECT_TIMEOUT = 10000;
|
|
|
+ private static final String CREATE_COLLECTION_COMMAND = "create-collection";
|
|
|
+ private static final String UPLOAD_CONFIG_COMMAND = "upload-config";
|
|
|
+ private static final String DOWNLOAD_CONFIG_COMMAND = "download-config";
|
|
|
+ private static final String CONFIG_CHECK_COMMAND = "check-config";
|
|
|
+ private static final String CREATE_SHARD_COMMAND = "create-shard";
|
|
|
+ private static final String CMD_LINE_SYNTAX =
|
|
|
+ "\n./solrCloudCli.sh --create-collection -z host1:2181,host2:2181/ambari-solr -c collection -cs conf_set"
|
|
|
+ + "\n./solrCloudCli.sh --upload-config -z host1:2181,host2:2181/ambari-solr -d /tmp/myonfig_dir -cs config_set"
|
|
|
+ + "\n./solrCloudCli.sh --download-config -z host1:2181,host2:2181/ambari-solr -cs config_set -d /tmp/myonfig_dir"
|
|
|
+ + "\n./solrCloudCli.sh --check-config -z host1:2181,host2:2181/ambari-solr -cs config_set"
|
|
|
+ + "\n./solrCloudCli.sh --create-shard -z host1:2181,host2:2181/ambari-solr -c collection -sn myshard\n";
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ Options options = new Options();
|
|
|
+ HelpFormatter helpFormatter = new HelpFormatter();
|
|
|
+ helpFormatter.setDescPadding(10);
|
|
|
+ helpFormatter.setWidth(200);
|
|
|
+
|
|
|
+ final Option helpOption = Option.builder("h")
|
|
|
+ .longOpt("help")
|
|
|
+ .desc("Print commands")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option createCollectionOption = Option.builder("cc")
|
|
|
+ .longOpt(CREATE_COLLECTION_COMMAND)
|
|
|
+ .desc("Create collection in Solr (command)")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option uploadConfigurationOption = Option.builder("uc")
|
|
|
+ .longOpt(UPLOAD_CONFIG_COMMAND)
|
|
|
+ .desc("Upload configuration set to Zookeeper (command)")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option downloadConfigOption = Option.builder("dc")
|
|
|
+ .longOpt(DOWNLOAD_CONFIG_COMMAND)
|
|
|
+ .desc("Download configuration set from Zookeeper (command)")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option checkConfigOption = Option.builder("chc")
|
|
|
+ .longOpt(CONFIG_CHECK_COMMAND)
|
|
|
+ .desc("Check configuration exists in Zookeeper (command)")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option createShardOption = Option.builder("csh")
|
|
|
+ .longOpt(CREATE_SHARD_COMMAND)
|
|
|
+ .desc("Create shard in Solr (command)")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option shardNameOption = Option.builder("sn")
|
|
|
+ .longOpt("shard-name")
|
|
|
+ .desc("Name of the shard for create-shard command")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("my_new_shard")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option disableShardingOption = Option.builder("ns")
|
|
|
+ .longOpt("no-sharding")
|
|
|
+ .desc("Sharding not used when creating collection")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option zookeeperHostOption = Option.builder("z")
|
|
|
+ .longOpt("zookeeper-host")
|
|
|
+ .desc("Zookeeper quorum and Znode")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("host:port,host:port../ambari-solr")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option collectionOption = Option.builder("c")
|
|
|
+ .longOpt("collection")
|
|
|
+ .desc("Collection name")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("collection name")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option configSetOption = Option.builder("cs")
|
|
|
+ .longOpt("config-set")
|
|
|
+ .desc("Configuration set")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("config_set")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option configDirOption = Option.builder("d")
|
|
|
+ .longOpt("config-dir")
|
|
|
+ .desc("Configuration directory")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("config_dir")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option shardsOption = Option.builder("s")
|
|
|
+ .longOpt("shards")
|
|
|
+ .desc("Number of shards")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("shard number")
|
|
|
+ .type(Integer.class)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option replicationOption = Option.builder("r")
|
|
|
+ .longOpt("replication")
|
|
|
+ .desc("Replication factor")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("replication factor")
|
|
|
+ .type(Integer.class)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option retryOption = Option.builder("rt")
|
|
|
+ .longOpt("retry")
|
|
|
+ .desc("Number of retries for access Solr [default:10]")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("number of retries")
|
|
|
+ .type(Integer.class)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option intervalOption = Option.builder("i")
|
|
|
+ .longOpt("interval")
|
|
|
+ .desc("Interval for retry logic in sec [default:5]")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("interval")
|
|
|
+ .type(Integer.class)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option maxShardsOption = Option.builder("m")
|
|
|
+ .longOpt("max-shards")
|
|
|
+ .desc("Max number of shards per node (default: replication * shards)")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("max number of shards")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option routerNameOption = Option.builder("rn")
|
|
|
+ .longOpt("router-name")
|
|
|
+ .desc("Router name for collection [default:implicit]")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("router_name")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ final Option routerFieldOption = Option.builder("rf")
|
|
|
+ .longOpt("router-field")
|
|
|
+ .desc("Router field for collection [default:_router_field_]")
|
|
|
+ .numberOfArgs(1)
|
|
|
+ .argName("router_field")
|
|
|
+ .build();
|
|
|
+
|
|
|
+ options.addOption(helpOption);
|
|
|
+ options.addOption(retryOption);
|
|
|
+ options.addOption(intervalOption);
|
|
|
+ options.addOption(zookeeperHostOption);
|
|
|
+ options.addOption(configSetOption);
|
|
|
+ options.addOption(configDirOption);
|
|
|
+ options.addOption(collectionOption);
|
|
|
+ options.addOption(shardsOption);
|
|
|
+ options.addOption(replicationOption);
|
|
|
+ options.addOption(maxShardsOption);
|
|
|
+ options.addOption(routerNameOption);
|
|
|
+ options.addOption(routerFieldOption);
|
|
|
+ options.addOption(shardNameOption);
|
|
|
+ options.addOption(disableShardingOption);
|
|
|
+ options.addOption(createCollectionOption);
|
|
|
+ options.addOption(downloadConfigOption);
|
|
|
+ options.addOption(uploadConfigurationOption);
|
|
|
+ options.addOption(checkConfigOption);
|
|
|
+ options.addOption(createShardOption);
|
|
|
+
|
|
|
+
|
|
|
+ try {
|
|
|
+ CommandLineParser cmdLineParser = new DefaultParser();
|
|
|
+ CommandLine cli = cmdLineParser.parse(options, args);
|
|
|
+
|
|
|
+ if(cli.hasOption('h')) {
|
|
|
+ helpFormatter.printHelp("sample", options);
|
|
|
+ exit(0, null);
|
|
|
+ }
|
|
|
+ String command = "";
|
|
|
+ if (cli.hasOption("cc")) {
|
|
|
+ command = CREATE_COLLECTION_COMMAND;
|
|
|
+ validateRequiredOptions(cli, command, zookeeperHostOption, collectionOption, configSetOption);
|
|
|
+ } else if (cli.hasOption("uc")) {
|
|
|
+ command = UPLOAD_CONFIG_COMMAND;
|
|
|
+ validateRequiredOptions(cli, command, zookeeperHostOption, configSetOption, configDirOption);
|
|
|
+ } else if (cli.hasOption("dc")) {
|
|
|
+ command = DOWNLOAD_CONFIG_COMMAND;
|
|
|
+ validateRequiredOptions(cli, command, zookeeperHostOption, configSetOption, configDirOption);
|
|
|
+ } else if (cli.hasOption("csh")) {
|
|
|
+ command = CREATE_SHARD_COMMAND;
|
|
|
+ validateRequiredOptions(cli, command, zookeeperHostOption, collectionOption, shardNameOption);
|
|
|
+ } else if (cli.hasOption("chc")) {
|
|
|
+ command = CONFIG_CHECK_COMMAND;
|
|
|
+ validateRequiredOptions(cli, command, zookeeperHostOption, configSetOption);
|
|
|
+ } else {
|
|
|
+ List<String> commands = Arrays.asList(CREATE_COLLECTION_COMMAND, CREATE_SHARD_COMMAND, UPLOAD_CONFIG_COMMAND,
|
|
|
+ DOWNLOAD_CONFIG_COMMAND, CONFIG_CHECK_COMMAND);
|
|
|
+ helpFormatter.printHelp(CMD_LINE_SYNTAX, options);
|
|
|
+ exit(1, String.format("One of the supported commands is required (%s)", StringUtils.join(commands, "|")));
|
|
|
+ }
|
|
|
+
|
|
|
+ String zookeeperHosts = cli.getOptionValue('z');
|
|
|
+ String collection = cli.getOptionValue('c');
|
|
|
+ String configSet = cli.getOptionValue("cs");
|
|
|
+ String configDir = cli.getOptionValue("d");
|
|
|
+ int shards = cli.hasOption('s') ? Integer.parseInt(cli.getOptionValue('s')) : 1;
|
|
|
+ int replication = cli.hasOption('r') ? Integer.parseInt(cli.getOptionValue('r')) : 1;
|
|
|
+ int retry = cli.hasOption("rt") ? Integer.parseInt(cli.getOptionValue("rt")) : 5;
|
|
|
+ int interval = cli.hasOption('i') ? Integer.parseInt(cli.getOptionValue('i')) : 10;
|
|
|
+ int maxShards = cli.hasOption('m') ? Integer.parseInt(cli.getOptionValue('m')) : shards * replication;
|
|
|
+ String routerName = cli.hasOption("rn") ? cli.getOptionValue("rn") : "implicit";
|
|
|
+ String routerField = cli.hasOption("rn") ? cli.getOptionValue("rn") : "_router_field_";
|
|
|
+ String shardName = cli.hasOption("sn") ? cli.getOptionValue("sn") : null;
|
|
|
+ boolean isSplitting = !cli.hasOption("ns");
|
|
|
+
|
|
|
+
|
|
|
+ AmbariSolrCloudClientBuilder clientBuilder = new AmbariSolrCloudClientBuilder()
|
|
|
+ .withZookeeperHosts(zookeeperHosts)
|
|
|
+ .withCollection(collection)
|
|
|
+ .withConfigSet(configSet)
|
|
|
+ .withShards(shards)
|
|
|
+ .withReplication(replication)
|
|
|
+ .withMaxShardsPerNode(maxShards)
|
|
|
+ .withRetry(retry)
|
|
|
+ .withInterval(interval)
|
|
|
+ .withRouterName(routerName)
|
|
|
+ .withRouterField(routerField)
|
|
|
+ .withSplitting(isSplitting)
|
|
|
+ .withSolrZkClient(ZK_CLIENT_TIMEOUT, ZK_CLIENT_CONNECT_TIMEOUT);
|
|
|
+
|
|
|
+ AmbariSolrCloudClient solrCloudClient = null;
|
|
|
+ switch (command) {
|
|
|
+ case CREATE_COLLECTION_COMMAND:
|
|
|
+ solrCloudClient = clientBuilder
|
|
|
+ .withSolrCloudClient()
|
|
|
+ .build();
|
|
|
+ solrCloudClient.createCollection();
|
|
|
+ break;
|
|
|
+ case UPLOAD_CONFIG_COMMAND:
|
|
|
+ solrCloudClient = clientBuilder
|
|
|
+ .withConfigDir(configDir)
|
|
|
+ .build();
|
|
|
+ solrCloudClient.uploadConfiguration();
|
|
|
+ break;
|
|
|
+ case DOWNLOAD_CONFIG_COMMAND:
|
|
|
+ solrCloudClient = clientBuilder
|
|
|
+ .withConfigDir(configDir)
|
|
|
+ .build();
|
|
|
+ solrCloudClient.downloadConfiguration();
|
|
|
+ break;
|
|
|
+ case CONFIG_CHECK_COMMAND:
|
|
|
+ solrCloudClient = clientBuilder.build();
|
|
|
+ boolean configExists = solrCloudClient.configurationExists();
|
|
|
+ if (!configExists) {
|
|
|
+ exit(1, null);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case CREATE_SHARD_COMMAND:
|
|
|
+ solrCloudClient = clientBuilder
|
|
|
+ .withSolrCloudClient()
|
|
|
+ .withSolrZkClient(ZK_CLIENT_TIMEOUT, ZK_CLIENT_CONNECT_TIMEOUT)
|
|
|
+ .build();
|
|
|
+ solrCloudClient.createShard(shardName);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new AmbariSolrCloudClientException(String.format("Not found command: '%s'", command));
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ helpFormatter.printHelp(
|
|
|
+ CMD_LINE_SYNTAX, options);
|
|
|
+ exit(1, e.getMessage());
|
|
|
+ }
|
|
|
+ exit(0, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void validateRequiredOptions(CommandLine cli, String command, Option... optionsToValidate)
|
|
|
+ throws AmbariSolrCloudClientException {
|
|
|
+ List<String> requiredOptions = new ArrayList<>();
|
|
|
+ for (Option opt : optionsToValidate) {
|
|
|
+ if (!cli.hasOption(opt.getOpt())) {
|
|
|
+ requiredOptions.add(opt.getOpt());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!requiredOptions.isEmpty()) {
|
|
|
+ throw new AmbariSolrCloudClientException(
|
|
|
+ String.format("The following options required for '%s' : %s",
|
|
|
+ command, StringUtils.join(requiredOptions, ",")));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void exit(int exitCode, String message) {
|
|
|
+ if (message != null){
|
|
|
+ LOG.error(message);
|
|
|
+ }
|
|
|
+ LOG.info("Return code: {}", exitCode);
|
|
|
+ System.exit(exitCode);
|
|
|
+ }
|
|
|
+}
|