You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ol...@apache.org on 2016/04/25 18:39:09 UTC

[2/2] ambari git commit: AMBARI-15865. Add 'ambari-logsearch-solr-client' module for ambari (oleewere)

AMBARI-15865. Add 'ambari-logsearch-solr-client' module for ambari (oleewere)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/aa6a2a9c
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/aa6a2a9c
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/aa6a2a9c

Branch: refs/heads/trunk
Commit: aa6a2a9ceec8c8dae5c493debf12e6b6a69f0f1d
Parents: d917dd9
Author: oleewere <ol...@gmail.com>
Authored: Mon Apr 25 18:31:51 2016 +0200
Committer: oleewere <ol...@gmail.com>
Committed: Mon Apr 25 18:31:51 2016 +0200

----------------------------------------------------------------------
 .../libraries/functions/package_conditions.py   |   8 +-
 .../libraries/functions/solr_cloud_util.py      |  66 ++++
 .../ambari-logsearch-assembly/pom.xml           | 108 +++---
 .../src/main/package/deb/appender/control       |  22 --
 .../src/main/package/deb/appender/postinst      |  15 -
 .../src/main/package/deb/appender/postrm        |  15 -
 .../src/main/package/deb/appender/posttrm       |  15 -
 .../src/main/package/deb/appender/preinst       |  15 -
 .../src/main/package/deb/appender/prerm         |  15 -
 .../src/main/package/deb/solr-client/control    |  22 ++
 .../src/main/package/deb/solr-client/postinst   |  15 +
 .../src/main/package/deb/solr-client/postrm     |  15 +
 .../src/main/package/deb/solr-client/preinst    |  15 +
 .../src/main/package/deb/solr-client/prerm      |  15 +
 .../ambari-logsearch-solr-client/build.xml      |  56 ++++
 .../ambari-logsearch-solr-client/pom.xml        | 117 +++++++
 .../logsearch/solr/AmbariSolrCloudCLI.java      | 331 +++++++++++++++++++
 .../logsearch/solr/AmbariSolrCloudClient.java   | 221 +++++++++++++
 .../solr/AmbariSolrCloudClientBuilder.java      | 114 +++++++
 .../solr/AmbariSolrCloudClientException.java    |  28 ++
 .../solr/commands/AbstractRetryCommand.java     |  58 ++++
 .../solr/commands/AbstractSolrRetryCommand.java |  53 +++
 .../commands/AbstractZookeeperRetryCommand.java |  44 +++
 .../solr/commands/CheckConfigZkCommand.java     |  34 ++
 .../solr/commands/CreateCollectionCommand.java  |  60 ++++
 .../solr/commands/CreateShardCommand.java       |  51 +++
 .../solr/commands/DownloadConfigZkCommand.java  |  40 +++
 .../solr/commands/GetShardsCommand.java         |  39 +++
 .../solr/commands/ListCollectionCommand.java    |  49 +++
 .../solr/commands/UploadConfigZkCommand.java    |  40 +++
 .../ambari/logsearch/solr/util/ShardUtils.java  |  71 ++++
 .../src/main/resources/log4j.properties         |  40 +++
 .../src/main/resources/solrCloudCli.sh          |  20 ++
 .../solr/AmbariSolrCloudClientTest.java         | 134 ++++++++
 ambari-logsearch/pom.xml                        |   1 +
 .../0.5.0/configuration/logfeeder-env.xml       |  13 +
 .../0.5.0/configuration/logsearch-env.xml       |  10 +
 .../0.5.0/configuration/logsearch-solr-env.xml  |  19 ++
 .../LOGSEARCH/0.5.0/metainfo.xml                |  42 ++-
 .../0.5.0/package/scripts/logsearch_solr.py     |  71 ++++
 .../package/scripts/logsearch_solr_client.py    |  51 +++
 .../LOGSEARCH/0.5.0/package/scripts/params.py   |   3 +
 .../0.5.0/package/scripts/setup_logsearch.py    |  29 +-
 .../package/scripts/setup_logsearch_solr.py     | 103 ++++++
 .../0.5.0/package/scripts/setup_solr.py         |  70 ----
 .../LOGSEARCH/0.5.0/package/scripts/solr.py     |  71 ----
 .../templates/solr-client-log4j.properties.j2   |  38 +++
 .../services/LOGSEARCH/role_command_order.json  |   2 +-
 .../stacks/2.4/LOGSEARCH/test_logsearch.py      |  25 +-
 .../python/stacks/2.4/LOGSEARCH/test_solr.py    |  12 +-
 .../test/python/stacks/2.4/configs/default.json |   1 +
 ambari-web/app/data/HDP2/site_properties.js     |  19 +-
 52 files changed, 2199 insertions(+), 342 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-common/src/main/python/resource_management/libraries/functions/package_conditions.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/functions/package_conditions.py b/ambari-common/src/main/python/resource_management/libraries/functions/package_conditions.py
index 1544ffe..1ffbbde 100644
--- a/ambari-common/src/main/python/resource_management/libraries/functions/package_conditions.py
+++ b/ambari-common/src/main/python/resource_management/libraries/functions/package_conditions.py
@@ -48,7 +48,11 @@ def should_install_ams_grafana():
 
 def should_install_logsearch_solr():
   config = Script.get_config()
-  return 'role' in config and config['role'] != "LOGSEARCH_LOGFEEDER"
+  return 'role' in config and config['role'] == "LOGSEARCH_SOLR"
+
+def should_install_logsearch_solr_client():
+  config = Script.get_config()
+  return 'role' in config and config['role'] == "LOGSEARCH_SOLR_CLIENT"
 
 def should_install_logsearch_portal():
   config = Script.get_config()
@@ -82,4 +86,4 @@ def should_install_ranger_tagsync():
   ranger_tagsync_enabled = default('/configurations/ranger-tagsync-site/ranger.tagsync.enabled', False)
   has_ranger_tagsync = len(ranger_tagsync_hosts) > 0
 
-  return has_ranger_tagsync or ranger_tagsync_enabled
\ No newline at end of file
+  return has_ranger_tagsync or ranger_tagsync_enabled

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-common/src/main/python/resource_management/libraries/functions/solr_cloud_util.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/functions/solr_cloud_util.py b/ambari-common/src/main/python/resource_management/libraries/functions/solr_cloud_util.py
new file mode 100644
index 0000000..d661288
--- /dev/null
+++ b/ambari-common/src/main/python/resource_management/libraries/functions/solr_cloud_util.py
@@ -0,0 +1,66 @@
+"""
+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.
+
+"""
+from resource_management.libraries.functions.format import format
+from resource_management.core.resources.system import Execute
+
+__all__ = ["upload_configuration_to_zk", "create_collection"]
+
+def __create_solr_cloud_cli_prefix(zookeeper_quorum, solr_znode, java64_home):
+  solr_cli_prefix = format('export JAVA_HOME={java64_home} ; /usr/lib/ambari-logsearch-solr-client/solrCloudCli.sh ' \
+                           '-z {zookeeper_quorum}{solr_znode}')
+  return solr_cli_prefix
+
+def upload_configuration_to_zk(zookeeper_quorum, solr_znode, config_set, config_set_dir, tmp_config_set_dir,
+                         java64_home, user, group, retry = 5, interval = 10):
+  """
+  Upload configuration set to zookeeper with solrCloudCli.sh
+  At first, it tries to download configuration set if exists into a temporary location, then upload that one to
+  zookeeper. (if the configuration changed there, in that case the user wont redefine it)
+  If the configuration set does not exits in zookeeper then upload it based on the config_set_dir parameter.
+  """
+  solr_cli_prefix = __create_solr_cloud_cli_prefix(zookeeper_quorum, solr_znode, java64_home)
+  Execute(format('{solr_cli_prefix} --download-config -d {tmp_config_set_dir} -cs {config_set} -rt {retry} -i {interval}'),
+          only_if=format("{solr_cli_prefix} --check-config -cs {config_set} -rt {retry} -i {interval}"),
+          user=user,
+          group=group
+          )
+
+  Execute(format(
+    '{solr_cli_prefix} --upload-config -d {config_set_dir} -cs {config_set} -rt {retry} -i {interval}'),
+    not_if=format("test -d {tmp_config_set_dir}"),
+    user=user,
+    group=group
+  )
+
+def create_collection(zookeeper_quorum, solr_znode, collection, config_set, java64_home, user, group,
+                      shards = 1, replication_factor = 1, max_shards = 1, retry = 5, interval = 10):
+  """
+  Create Solr collection based on a configuration set in zookeeper.
+  If this method called again the with higher shard number (or max_shard number), then it will indicate
+  the cli tool to add new shards to the Solr collection. This can be useful after added a new Solr Cloud
+  instance to the cluster.
+  """
+  solr_cli_prefix = __create_solr_cloud_cli_prefix(zookeeper_quorum, solr_znode, java64_home)
+
+  if max_shards == 1: # if max shards is not specified use this strategy
+    max_shards = replication_factor * shards
+
+  Execute(format('{solr_cli_prefix} --create-collection -c {collection} -cs {config_set} -s {shards} -r {replication_factor} '\
+    '-m {max_shards} -rt {retry} -i {interval}'), user=user, group=group
+  )

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/pom.xml b/ambari-logsearch/ambari-logsearch-assembly/pom.xml
index 2db0608..90504e6 100644
--- a/ambari-logsearch/ambari-logsearch-assembly/pom.xml
+++ b/ambari-logsearch/ambari-logsearch-assembly/pom.xml
@@ -31,15 +31,15 @@
     <solr.tar>http://apache.mirrors.lucidnetworks.net/lucene/solr/${solr.version}/solr-${solr.version}.tgz</solr.tar>
     <solr.mapping.path>${mapping.base.path}/ambari-logsearch-solr</solr.mapping.path>
     <solr.package.name>ambari-logsearch-solr</solr.package.name>
+    <solr.client.package.name>ambari-logsearch-solr-client</solr.client.package.name>
+    <solr.client.mapping.path>${mapping.base.path}/${solr.client.package.name}</solr.client.mapping.path>
+    <solr.client.dir>${project.basedir}/../ambari-logsearch-solr-client</solr.client.dir>
     <logsearch.portal.package.name>ambari-logsearch-portal</logsearch.portal.package.name>
     <logsearch.portal.mapping.path>${mapping.base.path}/ambari-logsearch-portal</logsearch.portal.mapping.path>
     <logsearch.portal.dir>${project.basedir}/../ambari-logsearch-portal</logsearch.portal.dir>
     <logsearch.logfeeder.package.name>ambari-logsearch-logfeeder</logsearch.logfeeder.package.name>
     <logsearch.logfeeder.mapping.path>${mapping.base.path}/ambari-logsearch-logfeeder</logsearch.logfeeder.mapping.path>
     <logsearch.logfeeder.dir>${project.basedir}/../ambari-logsearch-logfeeder</logsearch.logfeeder.dir>
-    <logsearch.appender.package.name>ambari-logsearch-appender</logsearch.appender.package.name>
-    <logsearch.appender.mapping.path>${mapping.base.path}/ambari-logsearch-appender</logsearch.appender.mapping.path>
-    <logsearch.appender.dir>${project.basedir}/../ambari-logsearch-appender</logsearch.appender.dir>
     <logsearch.portal.conf.mapping.path>/etc/${logsearch.portal.package.name}/conf</logsearch.portal.conf.mapping.path>
     <logsearch.logfeeder.conf.mapping.path>/etc/${logsearch.logfeeder.package.name}/conf
     </logsearch.logfeeder.conf.mapping.path>
@@ -100,6 +100,27 @@
                 </configuration>
               </execution>
               <execution>
+                <id>logsearch-solr-client</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>rpm</goal>
+                </goals>
+                <configuration>
+                  <group>Development</group>
+                  <name>${solr.client.package.name}</name>
+                  <mappings>
+                    <mapping>
+                      <directory>${solr.client.mapping.path}</directory>
+                      <sources>
+                        <source>
+                          <location>${solr.client.dir}/target/package</location>
+                        </source>
+                      </sources>
+                    </mapping>
+                  </mappings>
+                </configuration>
+              </execution>
+              <execution>
                 <id>logsearch-portal</id>
                 <phase>package</phase>
                 <goals>
@@ -186,27 +207,6 @@
                   </mappings>
                 </configuration>
               </execution>
-              <execution>
-                <id>logsearch-appender</id>
-                <phase>package</phase>
-                <goals>
-                  <goal>rpm</goal>
-                </goals>
-                <configuration>
-                  <group>Development</group>
-                  <name>${logsearch.appender.package.name}</name>
-                  <mappings>
-                    <mapping>
-                      <directory>${logsearch.appender.mapping.path}</directory>
-                      <sources>
-                        <source>
-                          <location>${logsearch.appender.dir}/target/package</location>
-                        </source>
-                      </sources>
-                    </mapping>
-                  </mappings>
-                </configuration>
-              </execution>
             </executions>
           </plugin>
           <plugin>
@@ -273,9 +273,9 @@
                       <directory>${project.basedir}/src/main/package/deb</directory>
                       <excludes>
                         <exclude>solr/postinst</exclude>
+                        <exclude>solr-client/postinst</exclude>
                         <exclude>portal/postinst</exclude>
                         <exclude>logfeeder/postinst</exclude>
-                        <exclude>appender/postinst</exclude>
                       </excludes>
                       <filtering>false</filtering>
                     </resource>
@@ -283,9 +283,9 @@
                       <directory>${project.basedir}/src/main/package/deb</directory>
                       <includes>
                         <include>solr/postinst</include>
+                        <include>solr-client/postinst</include>
                         <include>portal/postinst</include>
                         <include>logfeeder/postinst</include>
-                        <include>appender/postinst</include>
                       </includes>
                       <filtering>true</filtering>
                     </resource>
@@ -326,6 +326,32 @@
               </execution>
 
               <execution>
+                <phase>package</phase>
+                <id>jdeb-solr-client</id>
+                <goals>
+                  <goal>jdeb</goal>
+                </goals>
+                <configuration>
+                  <controlDir>${basedir}/src/main/package/deb/solr-client</controlDir>
+                  <deb>${basedir}/target/${solr.client.package.name}_${package-version}-${package-release}.deb</deb>
+                  <skip>false</skip>
+                  <skipPOMs>false</skipPOMs>
+                  <dataSet>
+                    <data>
+                      <src>${solr.client.dir}/target/ambari-logsearch-solr-client.tar.gz</src>
+                      <type>archive</type>
+                      <mapper>
+                        <type>perm</type>
+                        <user>root</user>
+                        <group>root</group>
+                        <prefix>${solr.client.mapping.path}</prefix>
+                      </mapper>
+                    </data>
+                  </dataSet>
+                </configuration>
+              </execution>
+
+              <execution>
                 <id>jdeb-portal</id>
                 <phase>package</phase>
                 <goals>
@@ -422,34 +448,6 @@
                   </dataSet>
                 </configuration>
               </execution>
-
-              <execution>
-                <id>jdeb-appender</id>
-                <phase>package</phase>
-                <goals>
-                  <goal>jdeb</goal>
-                </goals>
-                <configuration>
-                  <controlDir>${basedir}/src/main/package/deb/appender</controlDir>
-                  <deb>${basedir}/target/${logsearch.appender.package.name}_${package-version}-${package-release}.deb
-                  </deb>
-                  <skip>false</skip>
-                  <skipPOMs>false</skipPOMs>
-                  <dataSet>
-                    <data>
-                      <src>${logsearch.appender.dir}/target/ambari-logsearch-appender.tar.gz</src>
-                      <type>archive</type>
-                      <mapper>
-                        <prefix>${logsearch.appender.mapping.path}</prefix>
-                        <type>perm</type>
-                        <user>root</user>
-                        <group>root</group>
-                      </mapper>
-                    </data>
-                  </dataSet>
-                </configuration>
-              </execution>
-
             </executions>
           </plugin>
           <plugin>
@@ -502,7 +500,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.ambari</groupId>
-      <artifactId>ambari-logsearch-appender</artifactId>
+      <artifactId>ambari-logsearch-solr-client</artifactId>
       <version>${project.version}</version>
     </dependency>
   </dependencies>

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/control
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/control b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/control
deleted file mode 100644
index b853f13..0000000
--- a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/control
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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: [[logsearch.logfeeder.package.name]]
-Version: [[package-version]]-[[package-release]]
-Section: [[deb.section]]
-Priority: [[deb.priority]]
-Depends: [[deb.dependency.list]]
-Architecture: [[deb.architecture]]
-Description: [[description]]
-Maintainer: [[deb.publisher]]

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/postinst
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/postinst b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/postinst
deleted file mode 100644
index 21a01fa..0000000
--- a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/postinst
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/postrm
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/postrm b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/postrm
deleted file mode 100644
index 21a01fa..0000000
--- a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/postrm
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/posttrm
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/posttrm b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/posttrm
deleted file mode 100644
index 21a01fa..0000000
--- a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/posttrm
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/preinst
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/preinst b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/preinst
deleted file mode 100644
index 21a01fa..0000000
--- a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/preinst
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/prerm
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/prerm b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/prerm
deleted file mode 100644
index 21a01fa..0000000
--- a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/appender/prerm
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/control
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/control b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/control
new file mode 100644
index 0000000..88bafcb
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/control
@@ -0,0 +1,22 @@
+# 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: [[solr.client.package.name]]
+Version: [[package-version]]-[[package-release]]
+Section: [[deb.section]]
+Priority: [[deb.priority]]
+Depends: [[deb.dependency.list]]
+Architecture: [[deb.architecture]]
+Description: [[description]]
+Maintainer: [[deb.publisher]]

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/postinst
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/postinst b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/postinst
new file mode 100644
index 0000000..21a01fa
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/postinst
@@ -0,0 +1,15 @@
+#!/bin/bash
+# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/postrm
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/postrm b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/postrm
new file mode 100644
index 0000000..21a01fa
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/postrm
@@ -0,0 +1,15 @@
+#!/bin/bash
+# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/preinst
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/preinst b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/preinst
new file mode 100644
index 0000000..21a01fa
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/preinst
@@ -0,0 +1,15 @@
+#!/bin/bash
+# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/prerm
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/prerm b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/prerm
new file mode 100644
index 0000000..21a01fa
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-assembly/src/main/package/deb/solr-client/prerm
@@ -0,0 +1,15 @@
+#!/bin/bash
+# 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

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/build.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/build.xml b/ambari-logsearch/ambari-logsearch-solr-client/build.xml
new file mode 100644
index 0000000..4d1a9c7
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/build.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+   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.
+-->
+<project basedir="." default="build" name="logsearch">
+  <property environment="env"/>
+  <property name="debuglevel" value="source,lines,vars"/>
+  <dirname property="builddir" file="build.xml"/>
+  <property name="target" value="1.7"/>
+  <property name="source" value="1.7"/>
+  <target name="init">
+  </target>
+  <target name="build"/>
+
+  <target name="package">
+    <delete dir="target/package"/>
+    <copy todir="target/package/libs" includeEmptyDirs="no">
+      <fileset dir="target/libs"/>
+    </copy>
+    <copy todir="target/package/libs" includeEmptyDirs="no">
+      <fileset file="target/*.jar"/>
+    </copy>
+    <copy todir="target/package" includeEmptyDirs="no">
+      <fileset file="src/main/resources/solrCloudCli.sh"/>
+    </copy>
+    <copy todir="target/package" includeEmptyDirs="no">
+      <fileset file="src/main/resources/log4j.properties"/>
+    </copy>
+    <chmod file="target/package/*.sh" perm="755"/>
+    <tar compression="gzip" destfile="target/ambari-logsearch-solr-client.tar.gz">
+      <tarfileset mode="755" dir="target/package">
+        <include name="*.sh"/>
+      </tarfileset>
+      <tarfileset mode="664" dir="target/package">
+        <exclude name="*.sh"/>
+      </tarfileset>
+    </tar>
+
+  </target>
+
+  <target description="Build all projects which reference this project. Useful to propagate changes."
+          name="build-refprojects"/>
+</project>

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/pom.xml b/ambari-logsearch/ambari-logsearch-solr-client/pom.xml
new file mode 100644
index 0000000..b634928
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0"?>
+<!--
+   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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>ambari-logsearch</artifactId>
+    <groupId>org.apache.ambari</groupId>
+    <version>2.0.0.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <url>http://maven.apache.org</url>
+  <name>Ambari Logsearch Solr Client</name>
+
+  <artifactId>ambari-logsearch-solr-client</artifactId>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.solr</groupId>
+      <artifactId>solr-solrj</artifactId>
+      <version>${solr.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-cli</groupId>
+      <artifactId>commons-cli</artifactId>
+      <version>1.3.1</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>log4j</groupId>
+      <artifactId>log4j</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>3.4</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>2.8</version>
+        <executions>
+          <execution>
+            <id>copy-dependencies</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-dependencies</goal>
+            </goals>
+            <configuration>
+              <outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
+              <outputDirectory>${basedir}/target/libs</outputDirectory>
+              <overWriteReleases>false</overWriteReleases>
+              <overWriteSnapshots>false</overWriteSnapshots>
+              <overWriteIfNewer>true</overWriteIfNewer>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.7</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <configuration>
+              <target>
+                <ant antfile="build.xml">
+                  <target name="package"/>
+                </ant>
+              </target>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudCLI.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudCLI.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudCLI.java
new file mode 100644
index 0000000..74ea547
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudCLI.java
@@ -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);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClient.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClient.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClient.java
new file mode 100644
index 0000000..7cfed89
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClient.java
@@ -0,0 +1,221 @@
+/*
+ * 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.ambari.logsearch.solr.commands.CheckConfigZkCommand;
+import org.apache.ambari.logsearch.solr.commands.CreateCollectionCommand;
+import org.apache.ambari.logsearch.solr.commands.CreateShardCommand;
+import org.apache.ambari.logsearch.solr.commands.DownloadConfigZkCommand;
+import org.apache.ambari.logsearch.solr.commands.GetShardsCommand;
+import org.apache.ambari.logsearch.solr.commands.ListCollectionCommand;
+import org.apache.ambari.logsearch.solr.commands.UploadConfigZkCommand;
+import org.apache.ambari.logsearch.solr.util.ShardUtils;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.common.cloud.Replica;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.cloud.SolrZkClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Client for communicate with Solr (and Zookeeper)
+ */
+public class AmbariSolrCloudClient {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AmbariSolrCloudClient.class);
+
+  private final String zookeeperHosts;
+  private final String collection;
+  private final String configSet;
+  private final String configDir;
+  private final int shards;
+  private final int replication;
+  private final int retryTimes;
+  private final int interval;
+  private final CloudSolrClient solrCloudClient;
+  private final SolrZkClient solrZkClient;
+  private final int maxShardsPerNode;
+  private final String routerName;
+  private final String routerField;
+  private final boolean splitting;
+
+  public AmbariSolrCloudClient(AmbariSolrCloudClientBuilder builder) {
+    this.zookeeperHosts = builder.zookeeperHosts;
+    this.collection = builder.collection;
+    this.configSet = builder.configSet;
+    this.configDir = builder.configDir;
+    this.shards = builder.shards;
+    this.replication = builder.replication;
+    this.retryTimes = builder.retryTimes;
+    this.interval = builder.interval;
+    this.solrCloudClient = builder.solrCloudClient;
+    this.solrZkClient = builder.solrZkClient;
+    this.maxShardsPerNode = builder.maxShardsPerNode;
+    this.routerName = builder.routerName;
+    this.routerField = builder.routerField;
+    this.splitting = builder.splitting;
+  }
+
+  /**
+   * Get Solr collections
+   */
+  public List<String> listCollections() throws Exception {
+    return new ListCollectionCommand(getRetryTimes(), getInterval()).run(this);
+  }
+
+  /**
+   * Create Solr collection if exists
+   */
+  public String createCollection() throws Exception {
+    List <String> collections = listCollections();
+    if (!collections.contains(getCollection())) {
+      String collection = new CreateCollectionCommand(getRetryTimes(), getInterval()).run(this);
+      LOG.info("Collection '{}' created.", collection);
+    } else {
+      LOG.info("Collection '{}' already exits.", getCollection());
+      if (this.isSplitting()) {
+        createShard(null);
+      }
+    }
+    return getCollection();
+  }
+
+  /**
+   * Upload config set to zookeeper
+   */
+  public String uploadConfiguration() throws Exception {
+    String configSet = new UploadConfigZkCommand(getRetryTimes(), getInterval()).run(this);
+    LOG.info("'{}' is uploaded to zookeeper.", configSet);
+    return configSet;
+  }
+
+  /**
+   * Download config set from zookeeper
+   */
+  public String downloadConfiguration() throws Exception {
+    String configDir = new DownloadConfigZkCommand(getRetryTimes(), getInterval()).run(this);
+    LOG.info("Config set is download from zookeeper. ({})", configDir);
+    return configDir;
+  }
+
+  /**
+   * Get configuration if exists in zookeeper
+   */
+  public boolean configurationExists() throws Exception {
+    boolean configExits = new CheckConfigZkCommand(getRetryTimes(), getInterval()).run(this);
+    if (configExits) {
+      LOG.info("Config {} exits", configSet);
+    } else {
+      LOG.info("Configuration '{}' does not exist", configSet);
+    }
+    return configExits;
+  }
+
+  /**
+   * Create shard in collection - create a new one if shard name specified, if not create based on
+   * the number of shards logic (with shard_# suffix)
+   * @param shard name of the created shard
+   */
+  public Collection<String> createShard(String shard) throws Exception {
+    Collection<String> existingShards = getShardNames();
+    if (shard != null) {
+      new CreateShardCommand(shard, getRetryTimes(), getInterval()).run(this);
+      existingShards.add(shard);
+    } else {
+      List<String> shardList = ShardUtils.generateShardList(getMaxShardsPerNode());
+      for (String shardName : shardList) {
+        if (!existingShards.contains(shardName)) {
+          new CreateShardCommand(shardName, getRetryTimes(), getInterval()).run(this);
+          LOG.info("New shard added to collection '{}': {}", getCollection(), shardName);
+          existingShards.add(shardName);
+        }
+      }
+    }
+    return existingShards;
+  }
+
+  /**
+   * Get shard names
+   */
+  public Collection<String> getShardNames() throws Exception {
+    Collection<Slice> slices = new GetShardsCommand(getRetryTimes(), getInterval()).run(this);
+    return ShardUtils.getShardNamesFromSlices(slices, this.getCollection());
+  }
+
+  public String getZookeeperHosts() {
+    return zookeeperHosts;
+  }
+
+  public String getCollection() {
+    return collection;
+  }
+
+  public String getConfigSet() {
+    return configSet;
+  }
+
+  public String getConfigDir() {
+    return configDir;
+  }
+
+  public int getShards() {
+    return shards;
+  }
+
+  public int getReplication() {
+    return replication;
+  }
+
+  public int getRetryTimes() {
+    return retryTimes;
+  }
+
+  public int getInterval() {
+    return interval;
+  }
+
+  public CloudSolrClient getSolrCloudClient() {
+    return solrCloudClient;
+  }
+
+  public SolrZkClient getSolrZkClient() {
+    return solrZkClient;
+  }
+
+  public int getMaxShardsPerNode() {
+    return maxShardsPerNode;
+  }
+
+  public String getRouterName() {
+    return routerName;
+  }
+
+  public String getRouterField() {
+    return routerField;
+  }
+
+  public boolean isSplitting() {
+    return splitting;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClientBuilder.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClientBuilder.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClientBuilder.java
new file mode 100644
index 0000000..0813221
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClientBuilder.java
@@ -0,0 +1,114 @@
+/*
+ * 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.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.common.cloud.SolrZkClient;
+
+public class AmbariSolrCloudClientBuilder {
+  String zookeeperHosts;
+  String collection;
+  String configSet;
+  String configDir;
+  int shards = 1;
+  int replication = 1;
+  int retryTimes = 10;
+  int interval = 5;
+  int maxShardsPerNode = replication * shards;
+  String routerName = "implicit";
+  String routerField = "_router_field_";
+  CloudSolrClient solrCloudClient;
+  SolrZkClient solrZkClient;
+  boolean splitting;
+
+  public AmbariSolrCloudClient build() {
+    return new AmbariSolrCloudClient(this);
+  }
+
+  public AmbariSolrCloudClientBuilder withZookeeperHosts(String zookeeperHosts) {
+    this.zookeeperHosts = zookeeperHosts;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withCollection(String collection) {
+    this.collection = collection;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withConfigSet(String configSet) {
+    this.configSet = configSet;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withConfigDir(String configDir) {
+    this.configDir = configDir;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withShards(int shards) {
+    this.shards = shards;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withReplication(int replication) {
+    this.replication = replication;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withRetry(int retryTimes) {
+    this.retryTimes = retryTimes;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withInterval(int interval) {
+    this.interval = interval;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withMaxShardsPerNode(int maxShardsPerNode) {
+    this.maxShardsPerNode = maxShardsPerNode;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withRouterName(String routerName) {
+    this.routerName = routerName;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withRouterField(String routerField) {
+    this.routerField = routerField;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withSplitting(boolean splitting) {
+    this.splitting = splitting;
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withSolrCloudClient() {
+    this.solrCloudClient = new CloudSolrClient(this.zookeeperHosts);
+    return this;
+  }
+
+  public AmbariSolrCloudClientBuilder withSolrZkClient(int zkClientTimeout, int zkClientConnectTimeout) {
+    this.solrZkClient = new SolrZkClient(this.zookeeperHosts, zkClientTimeout, zkClientConnectTimeout);
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClientException.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClientException.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClientException.java
new file mode 100644
index 0000000..d03b779
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/AmbariSolrCloudClientException.java
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+public class AmbariSolrCloudClientException extends Exception{
+  public AmbariSolrCloudClientException(String message) {
+    super(message);
+  }
+  public AmbariSolrCloudClientException(String message, Throwable throwable) {
+    super(message, throwable);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractRetryCommand.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractRetryCommand.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractRetryCommand.java
new file mode 100644
index 0000000..cfe1e18
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractRetryCommand.java
@@ -0,0 +1,58 @@
+/*
+ * 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.commands;
+
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClient;
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClientException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractRetryCommand<RESPONSE> {
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractRetryCommand.class);
+
+  private final int interval;
+  private final int maxRetries;
+
+  public AbstractRetryCommand(int maxRetries, int interval) {
+    this.maxRetries = maxRetries;
+    this.interval = interval;
+  }
+
+  public abstract RESPONSE createAndProcessRequest(AmbariSolrCloudClient solrCloudClient) throws Exception;
+
+  public RESPONSE run(AmbariSolrCloudClient solrCloudClient) throws Exception {
+    return retry(0, solrCloudClient);
+  }
+
+  private RESPONSE retry(int tries, AmbariSolrCloudClient solrCloudClient) throws Exception {
+    try {
+      return createAndProcessRequest(solrCloudClient);
+    } catch (Exception ex) {
+      LOG.error(ex.getMessage(), ex);
+      tries++;
+      LOG.info("Command failed, tries again (tries: {})", tries);
+      if (maxRetries == tries) {
+        throw new AmbariSolrCloudClientException(String.format("Maximum retries exceeded: %d", tries), ex);
+      } else {
+        Thread.sleep(interval * 1000);
+        return retry(tries, solrCloudClient);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractSolrRetryCommand.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractSolrRetryCommand.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractSolrRetryCommand.java
new file mode 100644
index 0000000..e3d0696
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractSolrRetryCommand.java
@@ -0,0 +1,53 @@
+/*
+ * 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.commands;
+
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClient;
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClientException;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+import org.apache.solr.client.solrj.response.SolrResponseBase;
+
+public abstract class AbstractSolrRetryCommand<REQUEST extends CollectionAdminRequest, RESPONSE>
+  extends AbstractRetryCommand<RESPONSE> {
+
+  public AbstractSolrRetryCommand(int maxRetries, int interval) {
+    super(maxRetries, interval);
+  }
+
+  public abstract RESPONSE handleResponse(CollectionAdminResponse response, AmbariSolrCloudClient client) throws Exception;
+
+  public abstract REQUEST createRequest(AmbariSolrCloudClient client);
+
+  public abstract String errorMessage(AmbariSolrCloudClient client);
+
+  @Override
+  public RESPONSE createAndProcessRequest(AmbariSolrCloudClient client) throws Exception {
+    REQUEST request = createRequest(client);
+    CollectionAdminResponse response = (CollectionAdminResponse) request.process(client.getSolrCloudClient());
+    handleErrorIfExists(response, errorMessage(client));
+    return handleResponse(response, client);
+  }
+
+  private void handleErrorIfExists(SolrResponseBase response, String message) throws AmbariSolrCloudClientException {
+    if (response.getStatus() != 0) {
+      throw new AmbariSolrCloudClientException(message);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractZookeeperRetryCommand.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractZookeeperRetryCommand.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractZookeeperRetryCommand.java
new file mode 100644
index 0000000..c9e8558
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/AbstractZookeeperRetryCommand.java
@@ -0,0 +1,44 @@
+/*
+ * 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.commands;
+
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClient;
+import org.apache.solr.common.cloud.SolrZkClient;
+import org.apache.solr.common.cloud.ZkConfigManager;
+
+public abstract class AbstractZookeeperRetryCommand<RESPONSE> extends AbstractRetryCommand<RESPONSE> {
+
+  public AbstractZookeeperRetryCommand(int maxRetries, int interval) {
+    super(maxRetries, interval);
+  }
+
+  protected abstract RESPONSE executeZkCommand(ZkConfigManager zkConfigManager, AmbariSolrCloudClient client)
+    throws Exception;
+
+  @Override
+  public RESPONSE createAndProcessRequest(AmbariSolrCloudClient client) throws Exception {
+    SolrZkClient zkClient = client.getSolrZkClient();
+    ZkConfigManager zkConfigManager = createZkConfigManager(zkClient);
+    return executeZkCommand(zkConfigManager, client);
+  }
+
+  protected ZkConfigManager createZkConfigManager(SolrZkClient zkClient) {
+    return new ZkConfigManager(zkClient);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CheckConfigZkCommand.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CheckConfigZkCommand.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CheckConfigZkCommand.java
new file mode 100644
index 0000000..819395c
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CheckConfigZkCommand.java
@@ -0,0 +1,34 @@
+/*
+ * 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.commands;
+
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClient;
+import org.apache.solr.common.cloud.ZkConfigManager;
+
+public class CheckConfigZkCommand extends AbstractZookeeperRetryCommand<Boolean> {
+
+  public CheckConfigZkCommand(int maxRetries, int interval) {
+    super(maxRetries, interval);
+  }
+
+  @Override
+  protected Boolean executeZkCommand(ZkConfigManager zkConfigManager, AmbariSolrCloudClient client) throws Exception {
+    return zkConfigManager.configExists(client.getConfigSet());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CreateCollectionCommand.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CreateCollectionCommand.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CreateCollectionCommand.java
new file mode 100644
index 0000000..c888269
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CreateCollectionCommand.java
@@ -0,0 +1,60 @@
+/*
+ * 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.commands;
+
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClient;
+import org.apache.ambari.logsearch.solr.util.ShardUtils;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CreateCollectionCommand extends AbstractSolrRetryCommand<CollectionAdminRequest.Create ,String> {
+
+  public CreateCollectionCommand(int maxRetries, int interval) {
+    super(maxRetries, interval);
+  }
+
+  @Override
+  public String handleResponse(CollectionAdminResponse response, AmbariSolrCloudClient client) throws Exception {
+    return client.getCollection();
+  }
+
+  @Override
+  public CollectionAdminRequest.Create createRequest(AmbariSolrCloudClient client) {
+    CollectionAdminRequest.Create request = new CollectionAdminRequest.Create();
+    request.setConfigName(client.getConfigSet());
+    request.setCollectionName(client.getCollection());
+    request.setNumShards(client.getShards());
+    request.setReplicationFactor(client.getReplication());
+    request.setMaxShardsPerNode(client.getMaxShardsPerNode());
+    if (client.isSplitting()) {
+      request.setShards(ShardUtils.generateShardListStr(client.getMaxShardsPerNode()));
+      request.setRouterName(client.getRouterName());
+      request.setRouterField(client.getRouterField());
+    }
+    return request;
+  }
+
+  @Override
+  public String errorMessage(AmbariSolrCloudClient client) {
+    return String.format("Cannot create collection: '%s'", client.getCollection());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CreateShardCommand.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CreateShardCommand.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CreateShardCommand.java
new file mode 100644
index 0000000..343a498
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/CreateShardCommand.java
@@ -0,0 +1,51 @@
+/*
+ * 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.commands;
+
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+
+public class CreateShardCommand extends AbstractSolrRetryCommand<CollectionAdminRequest.CreateShard, String> {
+
+  private final String shardName;
+
+  public CreateShardCommand(String shardName, int maxRetries, int interval) {
+    super(maxRetries, interval);
+    this.shardName = shardName;
+  }
+
+  @Override
+  public String handleResponse(CollectionAdminResponse response, AmbariSolrCloudClient client) throws Exception {
+    return shardName;
+  }
+
+  @Override
+  public CollectionAdminRequest.CreateShard createRequest(AmbariSolrCloudClient client) {
+    CollectionAdminRequest.CreateShard createShardRequest = new CollectionAdminRequest.CreateShard();
+    createShardRequest.setCollectionName(client.getCollection());
+    createShardRequest.setShardName(shardName);
+    return createShardRequest;
+  }
+
+  @Override
+  public String errorMessage(AmbariSolrCloudClient client) {
+    return String.format("Cannot add shard to collection '%s'", client.getCollection());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/DownloadConfigZkCommand.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/DownloadConfigZkCommand.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/DownloadConfigZkCommand.java
new file mode 100644
index 0000000..2a0fa31
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/DownloadConfigZkCommand.java
@@ -0,0 +1,40 @@
+/*
+ * 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.commands;
+
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClient;
+import org.apache.solr.common.cloud.ZkConfigManager;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class DownloadConfigZkCommand extends AbstractZookeeperRetryCommand<String> {
+
+  public DownloadConfigZkCommand(int maxRetries, int interval) {
+    super(maxRetries, interval);
+  }
+
+  @Override
+  protected String executeZkCommand(ZkConfigManager zkConfigManager, AmbariSolrCloudClient client) throws Exception {
+    Path configDir = Paths.get(client.getConfigDir());
+    String configSet = client.getConfigSet();
+    zkConfigManager.downloadConfigDir(configSet, configDir);
+    return configDir.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/aa6a2a9c/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/GetShardsCommand.java
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/GetShardsCommand.java b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/GetShardsCommand.java
new file mode 100644
index 0000000..422878c
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-solr-client/src/main/java/org/apache/ambari/logsearch/solr/commands/GetShardsCommand.java
@@ -0,0 +1,39 @@
+/*
+ * 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.commands;
+
+import org.apache.ambari.logsearch.solr.AmbariSolrCloudClient;
+import org.apache.solr.common.cloud.Slice;
+import org.apache.solr.common.cloud.ZkStateReader;
+
+import java.util.Collection;
+
+public class GetShardsCommand extends AbstractRetryCommand<Collection<Slice>> {
+
+  public GetShardsCommand(int maxRetries, int interval) {
+    super(maxRetries, interval);
+  }
+
+  @Override
+  public Collection<Slice> createAndProcessRequest(AmbariSolrCloudClient solrCloudClient) throws Exception {
+    ZkStateReader zkReader = new ZkStateReader(solrCloudClient.getSolrZkClient());
+    zkReader.createClusterStateWatchersAndUpdate();
+    return zkReader.getClusterState().getSlices(solrCloudClient.getCollection());
+  }
+}