You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2017/06/14 21:19:43 UTC

[12/26] ambari git commit: AMBARI-20853. Service Advisor - Allow Service to define its Advisor Type as Python or Java (alejandro)

AMBARI-20853. Service Advisor - Allow Service to define its Advisor Type as Python or Java (alejandro)


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

Branch: refs/heads/branch-feature-AMBARI-20859
Commit: f1ca09c03a2fe316129aa5623c675b62d3177112
Parents: acc12fb
Author: Alejandro Fernandez <af...@hortonworks.com>
Authored: Mon Jun 5 15:24:49 2017 -0700
Committer: Alejandro Fernandez <af...@hortonworks.com>
Committed: Mon Jun 12 13:02:59 2017 -0700

----------------------------------------------------------------------
 ambari-client/groovy-client/pom.xml             |   2 +
 ambari-funtest/pom.xml                          |   2 +
 ambari-infra/ambari-infra-solr-client/pom.xml   |   2 +
 .../ambari-logsearch-config-api/pom.xml         |   2 +-
 .../ambari-logsearch-config-zookeeper/pom.xml   |   2 +-
 ambari-logsearch/ambari-logsearch-it/pom.xml    |   4 +-
 .../ambari-logsearch-logfeeder/pom.xml          |   4 +-
 .../ambari-metrics-timelineservice/pom.xml      |   4 +-
 ambari-project/pom.xml                          |   4 +-
 ambari-server/checkstyle.xml                    |   4 +
 ambari-server/pom.xml                           |  25 ++-
 .../stackadvisor/StackAdvisorHelper.java        |  74 +++++--
 .../stackadvisor/StackAdvisorRunner.java        | 207 ++++++++++++-------
 .../ComponentLayoutRecommendationCommand.java   |   5 +-
 .../ComponentLayoutValidationCommand.java       |  11 +-
 ...rationDependenciesRecommendationCommand.java |  11 +-
 .../ConfigurationRecommendationCommand.java     |  11 +-
 .../ConfigurationValidationCommand.java         |  11 +-
 .../commands/StackAdvisorCommand.java           |  15 +-
 .../ambari/server/stack/ServiceModule.java      |   4 +
 .../apache/ambari/server/state/ServiceInfo.java |  26 ++-
 .../stackadvisor/StackAdvisorHelperTest.java    |  63 ++++--
 .../stackadvisor/StackAdvisorRunnerTest.java    |  10 +-
 .../ConfigurationRecommendationCommandTest.java |   3 +-
 .../commands/StackAdvisorCommandTest.java       |  47 ++---
 .../ambari/server/stack/ServiceModuleTest.java  |  31 +++
 ambari-views/examples/weather-view/pom.xml      |   2 +-
 contrib/views/hawq/pom.xml                      |   2 +-
 contrib/views/hive-next/pom.xml                 |   4 +-
 contrib/views/hive20/pom.xml                    |   4 +-
 contrib/views/pig/pom.xml                       |   2 +-
 contrib/views/tez/pom.xml                       |   3 +-
 contrib/views/wfmanager/pom.xml                 |   1 +
 pom.xml                                         |  17 +-
 serviceadvisor/pom.xml                          | 103 +++++++++
 .../ambari/serviceadvisor/ServiceAdvisor.java   | 147 +++++++++++++
 .../ServiceAdvisorCommandType.java              |  63 ++++++
 37 files changed, 756 insertions(+), 176 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-client/groovy-client/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-client/groovy-client/pom.xml b/ambari-client/groovy-client/pom.xml
index fa89a73..8fafdec 100644
--- a/ambari-client/groovy-client/pom.xml
+++ b/ambari-client/groovy-client/pom.xml
@@ -29,10 +29,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.groovy</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-funtest/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-funtest/pom.xml b/ambari-funtest/pom.xml
index 66678c2..3738106 100644
--- a/ambari-funtest/pom.xml
+++ b/ambari-funtest/pom.xml
@@ -266,10 +266,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>log4j</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-infra/ambari-infra-solr-client/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-infra/ambari-infra-solr-client/pom.xml b/ambari-infra/ambari-infra-solr-client/pom.xml
index 8cb2248..d103003 100644
--- a/ambari-infra/ambari-infra-solr-client/pom.xml
+++ b/ambari-infra/ambari-infra-solr-client/pom.xml
@@ -60,10 +60,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>log4j</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-logsearch/ambari-logsearch-config-api/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-config-api/pom.xml b/ambari-logsearch/ambari-logsearch-config-api/pom.xml
index 5355906..59286a6 100644
--- a/ambari-logsearch/ambari-logsearch-config-api/pom.xml
+++ b/ambari-logsearch/ambari-logsearch-config-api/pom.xml
@@ -43,7 +43,7 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.7</version>
+      <version>1.7.20</version>
     </dependency>
   </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-logsearch/ambari-logsearch-config-zookeeper/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-config-zookeeper/pom.xml b/ambari-logsearch/ambari-logsearch-config-zookeeper/pom.xml
index 7ecda60..4e9964c 100644
--- a/ambari-logsearch/ambari-logsearch-config-zookeeper/pom.xml
+++ b/ambari-logsearch/ambari-logsearch-config-zookeeper/pom.xml
@@ -73,7 +73,7 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.7</version>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>com.google.code.gson</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-logsearch/ambari-logsearch-it/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-it/pom.xml b/ambari-logsearch/ambari-logsearch-it/pom.xml
index 81af9e8..db3e09f 100644
--- a/ambari-logsearch/ambari-logsearch-it/pom.xml
+++ b/ambari-logsearch/ambari-logsearch-it/pom.xml
@@ -81,12 +81,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.7</version>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
-      <version>1.7.10</version>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>com.flipkart.zjsonpatch</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-logsearch/ambari-logsearch-logfeeder/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-logfeeder/pom.xml b/ambari-logsearch/ambari-logsearch-logfeeder/pom.xml
index ddef52f..ce784cb 100644
--- a/ambari-logsearch/ambari-logsearch-logfeeder/pom.xml
+++ b/ambari-logsearch/ambari-logsearch-logfeeder/pom.xml
@@ -99,12 +99,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.7</version>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
-      <version>1.7.10</version>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.apache.commons</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-metrics/ambari-metrics-timelineservice/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-metrics/ambari-metrics-timelineservice/pom.xml b/ambari-metrics/ambari-metrics-timelineservice/pom.xml
index f9d7e19..3419f16 100644
--- a/ambari-metrics/ambari-metrics-timelineservice/pom.xml
+++ b/ambari-metrics/ambari-metrics-timelineservice/pom.xml
@@ -568,13 +568,13 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.2</version>
+      <version>1.7.20</version>
     </dependency>
 
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
-      <version>1.7.2</version>
+      <version>1.7.20</version>
     </dependency>
 
     <dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-project/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-project/pom.xml b/ambari-project/pom.xml
index 64d1416..9bb2e26 100644
--- a/ambari-project/pom.xml
+++ b/ambari-project/pom.xml
@@ -210,12 +210,12 @@
       <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
-        <version>1.7.2</version>
+        <version>1.7.20</version>
       </dependency>
       <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-log4j12</artifactId>
-        <version>1.7.2</version>
+        <version>1.7.20</version>
       </dependency>
       <dependency>
         <groupId>org.eclipse.persistence</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/checkstyle.xml
----------------------------------------------------------------------
diff --git a/ambari-server/checkstyle.xml b/ambari-server/checkstyle.xml
index 6b4824a..97fdc2a 100644
--- a/ambari-server/checkstyle.xml
+++ b/ambari-server/checkstyle.xml
@@ -11,6 +11,10 @@
   "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
   "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
 <module name="Checker">
+  <!-- Checkstyle binds to phase "validate" by default.
+  Run independently as, cd ambari-server ; mvn checkstyle:checkstyle
+  Or can skip as, mvn ... -Dcheckstyle.skip
+  -->
   <module name="TreeWalker">
     <module name="AvoidTransactionalOnPrivateMethodsCheck"/>
     <!-- <module name="UndocumentedRestApiOperationCheck"/> Swagger - uncomment when API documentation is done -->

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index d2b65af..a1cd239 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -837,6 +837,10 @@
         <artifactId>jetty-maven-plugin</artifactId>
         <version>${jetty.version}</version>
       </plugin>
+      <!-- Checkstyle binds to phase "validate" by default.
+      Run independently as, cd ambari-server ; mvn checkstyle:checkstyle
+      Or can skip as, mvn ... -Dcheckstyle.skip
+      -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-checkstyle-plugin</artifactId>
@@ -1287,10 +1291,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>log4j</groupId>
@@ -1354,6 +1360,12 @@
     <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
+      <version>2.6</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-lang3</artifactId>
+      <version>3.1</version>
     </dependency>
     <dependency>
       <groupId>commons-net</groupId>
@@ -1641,7 +1653,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>jul-to-slf4j</artifactId>
-      <version>1.7.2</version>
+      <version>1.7.20</version>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>io.dropwizard.metrics</groupId>
@@ -1653,6 +1670,12 @@
       <artifactId>metrics-jvm</artifactId>
       <version>3.1.0</version>
     </dependency>
+    
+    <dependency>
+      <groupId>serviceadvisor</groupId>
+      <artifactId>serviceadvisor</artifactId>
+      <version>1.0.0.0-SNAPSHOT</version>
+    </dependency>
 
     <!-- Dependency in order to annotate unit tests with a category. -->
     <dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
index 3083d9f..3e5599c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
@@ -21,6 +21,7 @@ package org.apache.ambari.server.api.services.stackadvisor;
 import java.io.File;
 import java.io.IOException;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestType;
 import org.apache.ambari.server.api.services.stackadvisor.commands.ComponentLayoutRecommendationCommand;
@@ -33,16 +34,23 @@ import org.apache.ambari.server.api.services.stackadvisor.recommendations.Recomm
 import org.apache.ambari.server.api.services.stackadvisor.validations.ValidationResponse;
 import org.apache.ambari.server.configuration.Configuration;
 
+import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
+
 @Singleton
 public class StackAdvisorHelper {
 
+  protected static Log LOG = LogFactory.getLog(StackAdvisorHelper.class);
+
   private File recommendationsDir;
   private String recommendationsArtifactsLifetime;
   private int recommendationsArtifactsRolloverMax;
-  private String stackAdvisorScript;
+  public static String pythonStackAdvisorScript;
   private final AmbariMetaInfo metaInfo;
 
   /* Monotonically increasing requestid */
@@ -55,7 +63,8 @@ public class StackAdvisorHelper {
     this.recommendationsDir = conf.getRecommendationsDir();
     this.recommendationsArtifactsLifetime = conf.getRecommendationsArtifactsLifetime();
     this.recommendationsArtifactsRolloverMax = conf.getRecommendationsArtifactsRolloverMax();
-    this.stackAdvisorScript = conf.getStackAdvisorScript();
+
+    this.pythonStackAdvisorScript = conf.getStackAdvisorScript();
     this.saRunner = saRunner;
     this.metaInfo = metaInfo;
   }
@@ -72,20 +81,26 @@ public class StackAdvisorHelper {
       throws StackAdvisorException {
       requestId = generateRequestId();
 
-    StackAdvisorCommand<ValidationResponse> command = createValidationCommand(request
-        .getRequestType());
+    // TODO, need frontend to pass the Service Name that was modified.
+    // For now, hardcode.
+    // Once fixed, change StackAdvisorHelperTest.java to use the actual service name.
+    String serviceName = "ZOOKEEPER";
+    ServiceInfo.ServiceAdvisorType serviceAdvisorType = getServiceAdvisorType(request.getStackName(), request.getStackVersion(), serviceName);
+    StackAdvisorCommand<ValidationResponse> command = createValidationCommand(serviceName, request);
 
-    return command.invoke(request);
+    return command.invoke(request, serviceAdvisorType);
   }
 
-  StackAdvisorCommand<ValidationResponse> createValidationCommand(
-      StackAdvisorRequestType requestType) throws StackAdvisorException {
+  StackAdvisorCommand<ValidationResponse> createValidationCommand(String serviceName, StackAdvisorRequest request) throws StackAdvisorException {
+    StackAdvisorRequestType requestType = request.getRequestType();
+    ServiceInfo.ServiceAdvisorType serviceAdvisorType = getServiceAdvisorType(request.getStackName(), request.getStackVersion(), serviceName);
+
     StackAdvisorCommand<ValidationResponse> command;
     if (requestType == StackAdvisorRequestType.HOST_GROUPS) {
-      command = new ComponentLayoutValidationCommand(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript,
+      command = new ComponentLayoutValidationCommand(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType,
           requestId, saRunner, metaInfo);
     } else if (requestType == StackAdvisorRequestType.CONFIGURATIONS) {
-      command = new ConfigurationValidationCommand(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript,
+      command = new ConfigurationValidationCommand(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType,
           requestId, saRunner, metaInfo);
     } else {
       throw new StackAdvisorRequestException(String.format("Unsupported request type, type=%s",
@@ -107,23 +122,29 @@ public class StackAdvisorHelper {
       throws StackAdvisorException {
       requestId = generateRequestId();
 
-      StackAdvisorCommand<RecommendationResponse> command = createRecommendationCommand(request
-        .getRequestType());
+    // TODO, need to pass the service Name that was modified.
+    // For now, hardcode
+    String serviceName = "ZOOKEEPER";
+
+    ServiceInfo.ServiceAdvisorType serviceAdvisorType = getServiceAdvisorType(request.getStackName(), request.getStackVersion(), serviceName);
+    StackAdvisorCommand<RecommendationResponse> command = createRecommendationCommand(serviceName, request);
 
-    return command.invoke(request);
+    return command.invoke(request, serviceAdvisorType);
   }
 
-  StackAdvisorCommand<RecommendationResponse> createRecommendationCommand(
-      StackAdvisorRequestType requestType) throws StackAdvisorException {
+  StackAdvisorCommand<RecommendationResponse> createRecommendationCommand(String serviceName, StackAdvisorRequest request) throws StackAdvisorException {
+    StackAdvisorRequestType requestType = request.getRequestType();
+    ServiceInfo.ServiceAdvisorType serviceAdvisorType = getServiceAdvisorType(request.getStackName(), request.getStackVersion(), serviceName);
+
     StackAdvisorCommand<RecommendationResponse> command;
     if (requestType == StackAdvisorRequestType.HOST_GROUPS) {
-      command = new ComponentLayoutRecommendationCommand(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript,
+      command = new ComponentLayoutRecommendationCommand(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType,
           requestId, saRunner, metaInfo);
     } else if (requestType == StackAdvisorRequestType.CONFIGURATIONS) {
-      command = new ConfigurationRecommendationCommand(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript,
+      command = new ConfigurationRecommendationCommand(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType,
           requestId, saRunner, metaInfo);
     } else if (requestType == StackAdvisorRequestType.CONFIGURATION_DEPENDENCIES) {
-      command = new ConfigurationDependenciesRecommendationCommand(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript,
+      command = new ConfigurationDependenciesRecommendationCommand(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType,
           requestId, saRunner, metaInfo);
     } else {
       throw new StackAdvisorRequestException(String.format("Unsupported request type, type=%s",
@@ -134,6 +155,25 @@ public class StackAdvisorHelper {
   }
 
   /**
+   * Get the Service Advisor type that the service defines for the specified stack and version. If an error, return null.
+   * @param stackName Stack Name
+   * @param stackVersion Stack Version
+   * @param serviceName Service Name
+   * @return Service Advisor type for that Stack, Version, and Service
+   */
+  private ServiceInfo.ServiceAdvisorType getServiceAdvisorType(String stackName, String stackVersion, String serviceName) {
+    try {
+      ServiceInfo service = metaInfo.getService(stackName, stackVersion, serviceName);
+      ServiceInfo.ServiceAdvisorType serviceAdvisorType = service.getServiceAdvisorType();
+
+      return serviceAdvisorType;
+    } catch (AmbariException e) {
+      ;
+    }
+    return null;
+  }
+
+  /**
    * Returns an incremented requestId. Rollsover back to 0 in case the requestId >= recommendationsArtifactsrollovermax
    * @return {int requestId}
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java
index a4b7915..90b95b3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunner.java
@@ -24,123 +24,190 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommandType;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
+
 @Singleton
 public class StackAdvisorRunner {
 
   private final static Logger LOG = LoggerFactory.getLogger(StackAdvisorRunner.class);
 
+  @Inject
+  private Configuration configs;
+
   /**
    * Runs stack_advisor.py script in the specified {@code actionDirectory}.
    *
-   * @param script stack advisor script
+   * @param serviceAdvisorType PYTHON or JAVA
    * @param saCommandType {@link StackAdvisorCommandType} to run.
    * @param actionDirectory directory for the action
    */
-  public void runScript(String script, StackAdvisorCommandType saCommandType, File actionDirectory)
+  public void runScript(ServiceInfo.ServiceAdvisorType serviceAdvisorType, StackAdvisorCommandType saCommandType, File actionDirectory)
       throws StackAdvisorException {
-    LOG.info(String.format("Script=%s, actionDirectory=%s, command=%s", script, actionDirectory,
+    LOG.info(String.format("StackAdvisorRunner. serviceAdvisorType=%s, actionDirectory=%s, command=%s", serviceAdvisorType.toString(), actionDirectory,
         saCommandType));
 
     String outputFile = actionDirectory + File.separator + "stackadvisor.out";
     String errorFile = actionDirectory + File.separator + "stackadvisor.err";
 
-    ProcessBuilder builder = prepareShellCommand(script, saCommandType,
-        actionDirectory, outputFile,
-        errorFile);
+    String hostsFile = actionDirectory + File.separator + "hosts.json";
+    String servicesFile = actionDirectory + File.separator + "services.json";
+
+    LOG.info("StackAdvisorRunner. Expected files: hosts.json={}, services.json={}, output={}, error={}", hostsFile, servicesFile, outputFile, errorFile);
+
+    int stackAdvisorReturnCode = -1;
+
+    switch (serviceAdvisorType) {
+      case JAVA:
+        org.apache.ambari.serviceadvisor.ServiceAdvisor serviceAdvisor = new org.apache.ambari.serviceadvisor.ServiceAdvisor();
+
+        LOG.info("StackAdvisorRunner.runScript(): Calling Java ServiceAdvisor's run method.");
+        stackAdvisorReturnCode = serviceAdvisor.run(saCommandType.toString(), hostsFile, servicesFile, outputFile, errorFile);
+        LOG.info(String.format("StackAdvisorRunner.runScript(): Java ServiceAdvisor's return code: %d", stackAdvisorReturnCode));
+        break;
+      case PYTHON:
+        LOG.info("StackAdvisorRunner.runScript(): Calling Python Stack Advisor.");
+        ProcessBuilder builder = prepareShellCommand(ServiceInfo.ServiceAdvisorType.PYTHON, StackAdvisorHelper.pythonStackAdvisorScript, saCommandType,
+            actionDirectory, outputFile,
+            errorFile);
+        stackAdvisorReturnCode = launchProcess(builder);
+        break;
+    }
+
+    // For both Python and Java, need to process log files for now.
+    processLogs(stackAdvisorReturnCode, outputFile, errorFile);
+  }
 
+  /**
+   * Launch a process, wait for it to finish, and return its exit code.
+   * @param builder Process Builder
+   * @return
+   * @throws StackAdvisorException
+   */
+  private int launchProcess(ProcessBuilder builder) throws StackAdvisorException {
+    int exitCode = -1;
+    Process process = null;
     try {
-      Process process = builder.start();
-
-      try {
-        LOG.info("Stack-advisor output={}, error={}", outputFile, errorFile);
-
-        int exitCode = process.waitFor();
-        String outMessage;
-        String errMessage = null;
-        try {
-          outMessage = FileUtils.readFileToString(new File(outputFile)).trim();
-          errMessage = FileUtils.readFileToString(new File(errorFile)).trim();
-          LOG.info("Stack advisor output files");
-          LOG.info("    advisor script stdout: {}", outMessage);
-          LOG.info("    advisor script stderr: {}", errMessage);
-        } catch (IOException io) {
-          LOG.error("Error in reading script log files", io);
-        }
-        if (exitCode > 0) {
-          String errorMessage;
-          if (errMessage != null) {
-            // We want to get the last line.
-            int index = errMessage.lastIndexOf("\n");
-            if (index > 0 && index == (errMessage.length() - 1)) {
-              index = errMessage.lastIndexOf("\n", index - 1); // sentence ended with newline
-            }
-            if (index > -1) {
-              errMessage = errMessage.substring(index + 1).trim();
-            }
-            errorMessage = "Stack Advisor reported an error: " + errMessage;
-          } else {
-            errorMessage = "Error occurred during stack advisor execution";
+      process = builder.start();
+      exitCode = process.waitFor();
+    } catch (Exception ioe) {
+      String message = "Error executing Stack Advisor: ";
+      LOG.error(message, ioe);
+      throw new StackAdvisorException(message + ioe.getMessage());
+    } finally {
+      if (process != null) {
+        process.destroy();
+      }
+    }
+    return exitCode;
+  }
+
+  /**
+   * Process the exit code and logs. If non-zero then parse the log files and raise the appropriate exception.
+   * @param exitCode Process exit code
+   * @param outputFile Path to output file
+   * @param errorFile Path to error file
+   * @throws StackAdvisorException
+   */
+  private void processLogs(int exitCode, String outputFile, String errorFile) throws StackAdvisorException {
+    String outMessage = printMessage("stdout", outputFile);
+    String errMessage = printMessage("stderr", errorFile);
+
+    try {
+      if (exitCode != 0) {
+        String errorMessage;
+        if (errMessage != null) {
+          // We want to get the last line.
+          int index = errMessage.lastIndexOf("\n");
+          if (index > 0 && index == (errMessage.length() - 1)) {
+            index = errMessage.lastIndexOf("\n", index - 1); // sentence ended with newline
           }
-          errorMessage += "\nStdOut file: " + outputFile + "\n";
-          errorMessage += "\nStdErr file: " + errorFile;
-          switch (exitCode) {
-            case 1:
-              throw new StackAdvisorRequestException(errorMessage);
-            case 2:
-              throw new StackAdvisorException(errorMessage);
+          if (index > -1) {
+            errMessage = errMessage.substring(index + 1).trim();
           }
+          errorMessage = String.format("Stack Advisor reported an error. Exit Code: %s. Error: %s ", exitCode, errMessage);
+        } else {
+          errorMessage = String.format("Error occurred during Stack Advisor execution. Exit Code: %s", exitCode);
+        }
+        errorMessage += "\nStdOut file: " + outputFile + "\n";
+        errorMessage += "\nStdErr file: " + errorFile;
+        switch (exitCode) {
+          case 1:
+            throw new StackAdvisorRequestException(errorMessage);
+          case 2:
+            throw new StackAdvisorException(errorMessage);
         }
-      } finally {
-        process.destroy();
       }
     } catch (StackAdvisorException ex) {
       throw ex;
-    } catch (Exception ioe) {
-      String message = "Error executing stack advisor: ";
-      LOG.error(message, ioe);
-      throw new StackAdvisorException(message + ioe.getMessage());
     }
   }
 
   /**
+   * Logs messages from the output/error file.
+   * @param type Severity type, stdout or stderr
+   * @param file File path
+   * @return File to a String
+   */
+  private String printMessage(String type, String file) {
+    String message = null;
+    try {
+      message = FileUtils.readFileToString(new File(file)).trim();
+      LOG.info("    Advisor script {}: {}", type, message);
+    } catch (IOException io) {
+      LOG.error("Error in reading script log files", io);
+    }
+    return message;
+  }
+
+  /**
    * Gets an instance of a {@link ProcessBuilder} that's ready to execute the
    * shell command to run the stack advisor script. This will take the
    * environment variables from the current process.
    *
-   * @param script
-   * @param saCommandType
-   * @param actionDirectory
-   * @param outputFile
-   * @param errorFile
-   * @return
+   * @param serviceAdvisorType Python or Java
+   * @param script Python script or jar path
+   * @param saCommandType command type such as validate, configure
+   * @param actionDirectory Directory that contains hosts.json, services.json, and output files
+   * @param outputFile Output file path
+   * @param errorFile Error file path
+   * @return Process that can launch
    */
-  ProcessBuilder prepareShellCommand(String script,
-      StackAdvisorCommandType saCommandType,
-      File actionDirectory, String outputFile, String errorFile) {
+  ProcessBuilder prepareShellCommand(ServiceInfo.ServiceAdvisorType serviceAdvisorType, String script,
+                                     StackAdvisorCommandType saCommandType,
+                                     File actionDirectory, String outputFile, String errorFile) {
     String hostsFile = actionDirectory + File.separator + "hosts.json";
     String servicesFile = actionDirectory + File.separator + "services.json";
 
     // includes the original command plus the arguments for it
-    List<String> builderParameters = new ArrayList<>();
-    if (System.getProperty("os.name").contains("Windows")) {
-      builderParameters.add("cmd");
-      builderParameters.add("/c");
-    } else {
-      builderParameters.add("sh");
-      builderParameters.add("-c");
+    List<String> builderParameters = new ArrayList<String>();
+
+    switch (serviceAdvisorType) {
+      case PYTHON:
+      case JAVA:
+        if (System.getProperty("os.name").contains("Windows")) {
+          builderParameters.add("cmd");
+          builderParameters.add("/c");
+        } else {
+          builderParameters.add("sh");
+          builderParameters.add("-c");
+        }
+        break;
+      default:
+        break;
     }
 
     // for the 3rd argument, build a single parameter since we use -c
     // ProcessBuilder doesn't support output redirection until JDK 1.7
-    String commandStringParameters[] = new String[] { script,
-        saCommandType.toString(), hostsFile,
-        servicesFile, "1>", outputFile, "2>", errorFile };
+    String commandStringParameters[] = new String[] {script, saCommandType.toString(), hostsFile, servicesFile, "1>", outputFile, "2>", errorFile};
 
     StringBuilder commandString = new StringBuilder();
     for (String command : commandStringParameters) {
@@ -149,7 +216,7 @@ public class StackAdvisorRunner {
 
     builderParameters.add(commandString.toString());
 
-    LOG.debug("Stack advisor command is {}", builderParameters);
+    LOG.debug("StackAdvisorRunner. Stack advisor command is {}", StringUtils.join(" ", builderParameters));
 
     return new ProcessBuilder(builderParameters);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutRecommendationCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutRecommendationCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutRecommendationCommand.java
index ca1d95f2..6a0c4d6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutRecommendationCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutRecommendationCommand.java
@@ -25,6 +25,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
+import org.apache.ambari.server.state.ServiceInfo;
 
 /**
  * {@link StackAdvisorCommand} implementation for component-layout
@@ -35,11 +36,11 @@ public class ComponentLayoutRecommendationCommand extends
 
   public ComponentLayoutRecommendationCommand(File recommendationsDir,
                                               String recommendationsArtifactsLifetime,
-                                              String stackAdvisorScript,
+                                              ServiceInfo.ServiceAdvisorType serviceAdvisorType,
                                               int requestId,
                                               StackAdvisorRunner saRunner,
                                               AmbariMetaInfo metaInfo) {
-    super(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript, requestId, saRunner, metaInfo);
+    super(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType, requestId, saRunner, metaInfo);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutValidationCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutValidationCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutValidationCommand.java
index 91d8f9c..feba22e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutValidationCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutValidationCommand.java
@@ -25,15 +25,20 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.validations.ValidationResponse;
+import org.apache.ambari.server.state.ServiceInfo;
 
 /**
  * {@link StackAdvisorCommand} implementation for component-layout validation.
  */
 public class ComponentLayoutValidationCommand extends StackAdvisorCommand<ValidationResponse> {
 
-  public ComponentLayoutValidationCommand(File recommendationsDir, String recommendationsArtifactsLifetime, String stackAdvisorScript,
-                                          int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
-    super(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript, requestId, saRunner, metaInfo);
+  public ComponentLayoutValidationCommand(File recommendationsDir,
+                                          String recommendationsArtifactsLifetime,
+                                          ServiceInfo.ServiceAdvisorType serviceAdvisorType,
+                                          int requestId,
+                                          StackAdvisorRunner saRunner,
+                                          AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType, requestId, saRunner, metaInfo);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationDependenciesRecommendationCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationDependenciesRecommendationCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationDependenciesRecommendationCommand.java
index fae0b16..83a6306 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationDependenciesRecommendationCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationDependenciesRecommendationCommand.java
@@ -32,6 +32,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
+import org.apache.ambari.server.state.ServiceInfo;
 
 /**
  * {@link StackAdvisorCommand} implementation for
@@ -40,9 +41,13 @@ import org.apache.ambari.server.api.services.stackadvisor.recommendations.Recomm
 public class ConfigurationDependenciesRecommendationCommand extends
     StackAdvisorCommand<RecommendationResponse> {
 
-  public ConfigurationDependenciesRecommendationCommand(File recommendationsDir, String recommendationsArtifactsLifetime, String stackAdvisorScript, int requestId,
-                                                        StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
-    super(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript, requestId, saRunner, metaInfo);
+  public ConfigurationDependenciesRecommendationCommand(File recommendationsDir,
+                                                        String recommendationsArtifactsLifetime,
+                                                        ServiceInfo.ServiceAdvisorType serviceAdvisorType,
+                                                        int requestId,
+                                                        StackAdvisorRunner saRunner,
+                                                        AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType, requestId, saRunner, metaInfo);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommand.java
index e25e39b..7ac3fdb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommand.java
@@ -32,6 +32,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
+import org.apache.ambari.server.state.ServiceInfo;
 
 /**
  * {@link org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand} implementation for
@@ -40,9 +41,13 @@ import org.apache.ambari.server.api.services.stackadvisor.recommendations.Recomm
 public class ConfigurationRecommendationCommand extends
     StackAdvisorCommand<RecommendationResponse> {
 
-  public ConfigurationRecommendationCommand(File recommendationsDir, String recommendationsArtifactsLifetime, String stackAdvisorScript, int requestId,
-                                            StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
-    super(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript, requestId, saRunner, metaInfo);
+  public ConfigurationRecommendationCommand(File recommendationsDir,
+                                            String recommendationsArtifactsLifetime,
+                                            ServiceInfo.ServiceAdvisorType serviceAdvisorType,
+                                            int requestId,
+                                            StackAdvisorRunner saRunner,
+                                            AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType, requestId, saRunner, metaInfo);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationValidationCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationValidationCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationValidationCommand.java
index 1892a82..1b6b703 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationValidationCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationValidationCommand.java
@@ -25,15 +25,20 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorException;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.validations.ValidationResponse;
+import org.apache.ambari.server.state.ServiceInfo;
 
 /**
  * {@link StackAdvisorCommand} implementation for configuration validation.
  */
 public class ConfigurationValidationCommand extends StackAdvisorCommand<ValidationResponse> {
 
-  public ConfigurationValidationCommand(File recommendationsDir, String recommendationsArtifactsLifetime, String stackAdvisorScript,
-                                        int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
-    super(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript, requestId, saRunner, metaInfo);
+  public ConfigurationValidationCommand(File recommendationsDir,
+                                        String recommendationsArtifactsLifetime,
+                                        ServiceInfo.ServiceAdvisorType serviceAdvisorType,
+                                        int requestId,
+                                        StackAdvisorRunner saRunner,
+                                        AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType, requestId, saRunner, metaInfo);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
index c2895d9..356754d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
@@ -67,7 +67,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
 
   /**
    * Type of response object provided by extending classes when
-   * {@link #invoke(StackAdvisorRequest)} is called.
+   * {@link #invoke(StackAdvisorRequest, ServiceInfo.ServiceAdvisorType)} is called.
    */
   private Class<T> type;
 
@@ -98,7 +98,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
 
   private File recommendationsDir;
   private String recommendationsArtifactsLifetime;
-  private String stackAdvisorScript;
+  private ServiceInfo.ServiceAdvisorType serviceAdvisorType;
 
   private int requestId;
   private File requestDirectory;
@@ -109,7 +109,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
   private final AmbariMetaInfo metaInfo;
 
   @SuppressWarnings("unchecked")
-  public StackAdvisorCommand(File recommendationsDir, String recommendationsArtifactsLifetime, String stackAdvisorScript, int requestId,
+  public StackAdvisorCommand(File recommendationsDir, String recommendationsArtifactsLifetime, ServiceInfo.ServiceAdvisorType serviceAdvisorType, int requestId,
       StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
     this.type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
         .getActualTypeArguments()[0];
@@ -119,7 +119,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
 
     this.recommendationsDir = recommendationsDir;
     this.recommendationsArtifactsLifetime = recommendationsArtifactsLifetime;
-    this.stackAdvisorScript = stackAdvisorScript;
+    this.serviceAdvisorType = serviceAdvisorType;
     this.requestId = requestId;
     this.saRunner = saRunner;
     this.metaInfo = metaInfo;
@@ -278,7 +278,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
     }
   }
 
-  public synchronized T invoke(StackAdvisorRequest request) throws StackAdvisorException {
+  public synchronized T invoke(StackAdvisorRequest request, ServiceInfo.ServiceAdvisorType serviceAdvisorType) throws StackAdvisorException {
     validate(request);
     String hostsJSON = getHostsInformation(request);
     String servicesJSON = getServicesInformation(request);
@@ -289,10 +289,9 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       createRequestDirectory();
 
       FileUtils.writeStringToFile(new File(requestDirectory, "hosts.json"), adjusted.hostsJSON);
-      FileUtils.writeStringToFile(new File(requestDirectory, "services.json"),
-          adjusted.servicesJSON);
+      FileUtils.writeStringToFile(new File(requestDirectory, "services.json"), adjusted.servicesJSON);
 
-      saRunner.runScript(stackAdvisorScript, getCommandType(), requestDirectory);
+      saRunner.runScript(serviceAdvisorType, getCommandType(), requestDirectory);
       String result = FileUtils.readFileToString(new File(requestDirectory, getResultFileName()));
 
       T response = this.mapper.readValue(result, this.type);

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
index e41d3b2..2b4398b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
@@ -205,6 +205,10 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> implem
     if (serviceInfo.getDisplayName() == null) {
       serviceInfo.setDisplayName(parent.getDisplayName());
     }
+    if (serviceInfo.getServiceAdvisorType() == null) {
+      ServiceInfo.ServiceAdvisorType serviceAdvisorType = parent.getServiceAdvisorType();
+      serviceInfo.setServiceAdvisorType(serviceAdvisorType == null ? ServiceInfo.ServiceAdvisorType.PYTHON : serviceAdvisorType);
+    }
     if (serviceInfo.getVersion() == null) {
       serviceInfo.setVersion(parent.getVersion());
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
index 97490e0..325434e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
@@ -36,6 +36,8 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlEnumValue;
 import javax.xml.bind.annotation.XmlTransient;
 
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
@@ -72,6 +74,20 @@ public class ServiceInfo implements Validable{
   private String serviceType;
   private Selection selection;
 
+  /**
+   * Default to Python if not specified.
+   */
+
+  @XmlEnum
+  public enum ServiceAdvisorType {
+    @XmlEnumValue("PYTHON")
+    PYTHON,
+    @XmlEnumValue("JAVA")
+    JAVA
+  }
+  @XmlElement(name="service_advisor_type")
+  private ServiceAdvisorType serviceAdvisorType = null;
+
   @XmlTransient
   private List<PropertyInfo> properties;
 
@@ -341,6 +357,14 @@ public class ServiceInfo implements Validable{
     this.displayName = displayName;
   }
 
+  public void setServiceAdvisorType(ServiceAdvisorType type) {
+    this.serviceAdvisorType = type;
+  }
+
+  public ServiceAdvisorType getServiceAdvisorType() {
+    return serviceAdvisorType;
+  }
+
   public String getServiceType() {
 	return serviceType;
   }
@@ -349,7 +373,7 @@ public class ServiceInfo implements Validable{
 	this.serviceType = serviceType;
   }
 
-public String getVersion() {
+  public String getVersion() {
     return version;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java
index e331ddd..cedf3a2 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java
@@ -38,12 +38,15 @@ import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorC
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
 import org.apache.ambari.server.api.services.stackadvisor.validations.ValidationResponse;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 /**
  * StackAdvisorHelper unit tests.
  */
 public class StackAdvisorHelperTest {
+
   @Test
   @SuppressWarnings("unchecked")
   public void testValidate_returnsCommandResult() throws StackAdvisorException, IOException {
@@ -51,19 +54,21 @@ public class StackAdvisorHelperTest {
     when(configuration.getRecommendationsArtifactsRolloverMax()).thenReturn(100);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    ServiceInfo service = mock(ServiceInfo.class);
+    when(metaInfo.getService(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(service);
+    when(service.getServiceAdvisorType()).thenReturn(ServiceInfo.ServiceAdvisorType.PYTHON);
     StackAdvisorHelper helper = spy(new StackAdvisorHelper(configuration, saRunner, metaInfo));
 
     StackAdvisorCommand<ValidationResponse> command = mock(StackAdvisorCommand.class);
     ValidationResponse expected = mock(ValidationResponse.class);
+
     StackAdvisorRequestType requestType = StackAdvisorRequestType.HOST_GROUPS;
     StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
         .ofType(requestType).build();
 
-    when(command.invoke(request)).thenReturn(expected);
-    doReturn(command).when(helper).createValidationCommand(requestType);
-
+    when(command.invoke(request, ServiceInfo.ServiceAdvisorType.PYTHON)).thenReturn(expected);
+    doReturn(command).when(helper).createValidationCommand("ZOOKEEPER", request);
     ValidationResponse response = helper.validate(request);
-
     assertEquals(expected, response);
   }
 
@@ -75,6 +80,9 @@ public class StackAdvisorHelperTest {
     when(configuration.getRecommendationsArtifactsRolloverMax()).thenReturn(100);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    ServiceInfo service = mock(ServiceInfo.class);
+    when(metaInfo.getService(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(service);
+    when(service.getServiceAdvisorType()).thenReturn(ServiceInfo.ServiceAdvisorType.PYTHON);
     StackAdvisorHelper helper = spy(new StackAdvisorHelper(configuration, saRunner, metaInfo));
 
     StackAdvisorCommand<ValidationResponse> command = mock(StackAdvisorCommand.class);
@@ -82,8 +90,8 @@ public class StackAdvisorHelperTest {
     StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
         .ofType(requestType).build();
 
-    when(command.invoke(request)).thenThrow(new StackAdvisorException("message"));
-    doReturn(command).when(helper).createValidationCommand(requestType);
+    when(command.invoke(request, ServiceInfo.ServiceAdvisorType.PYTHON)).thenThrow(new StackAdvisorException("message"));
+    doReturn(command).when(helper).createValidationCommand("ZOOKEEPER", request);
     helper.validate(request);
 
     assertTrue(false);
@@ -96,6 +104,9 @@ public class StackAdvisorHelperTest {
     when(configuration.getRecommendationsArtifactsRolloverMax()).thenReturn(100);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    ServiceInfo service = mock(ServiceInfo.class);
+    when(metaInfo.getService(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(service);
+    when(service.getServiceAdvisorType()).thenReturn(ServiceInfo.ServiceAdvisorType.PYTHON);
     StackAdvisorHelper helper = spy(new StackAdvisorHelper(configuration, saRunner, metaInfo));
 
     StackAdvisorCommand<RecommendationResponse> command = mock(StackAdvisorCommand.class);
@@ -104,8 +115,8 @@ public class StackAdvisorHelperTest {
     StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
         .ofType(requestType).build();
 
-    when(command.invoke(request)).thenReturn(expected);
-    doReturn(command).when(helper).createRecommendationCommand(requestType);
+    when(command.invoke(request, ServiceInfo.ServiceAdvisorType.PYTHON)).thenReturn(expected);
+    doReturn(command).when(helper).createRecommendationCommand("ZOOKEEPER", request);
     RecommendationResponse response = helper.recommend(request);
 
     assertEquals(expected, response);
@@ -119,6 +130,9 @@ public class StackAdvisorHelperTest {
     when(configuration.getRecommendationsArtifactsRolloverMax()).thenReturn(100);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    ServiceInfo service = mock(ServiceInfo.class);
+    when(metaInfo.getService(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(service);
+    when(service.getServiceAdvisorType()).thenReturn(ServiceInfo.ServiceAdvisorType.PYTHON);
     StackAdvisorHelper helper = spy(new StackAdvisorHelper(configuration, saRunner, metaInfo));
 
     StackAdvisorCommand<RecommendationResponse> command = mock(StackAdvisorCommand.class);
@@ -126,8 +140,8 @@ public class StackAdvisorHelperTest {
     StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
         .ofType(requestType).build();
 
-    when(command.invoke(request)).thenThrow(new StackAdvisorException("message"));
-    doReturn(command).when(helper).createRecommendationCommand(requestType);
+    when(command.invoke(request, ServiceInfo.ServiceAdvisorType.PYTHON)).thenThrow(new StackAdvisorException("message"));
+    doReturn(command).when(helper).createRecommendationCommand("ZOOKEEPER", request);
     helper.recommend(request);
 
     assertTrue(false);
@@ -140,11 +154,16 @@ public class StackAdvisorHelperTest {
     when(configuration.getRecommendationsArtifactsRolloverMax()).thenReturn(100);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    ServiceInfo service = mock(ServiceInfo.class);
+    when(metaInfo.getService(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(service);
+    when(service.getServiceAdvisorType()).thenReturn(ServiceInfo.ServiceAdvisorType.PYTHON);
     StackAdvisorHelper helper = new StackAdvisorHelper(configuration, saRunner, metaInfo);
     StackAdvisorRequestType requestType = StackAdvisorRequestType.HOST_GROUPS;
+    StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
+        .ofType(requestType).build();
 
     StackAdvisorCommand<RecommendationResponse> command = helper
-        .createRecommendationCommand(requestType);
+        .createRecommendationCommand("ZOOKEEPER", request);
 
     assertEquals(ComponentLayoutRecommendationCommand.class, command.getClass());
   }
@@ -156,10 +175,15 @@ public class StackAdvisorHelperTest {
     when(configuration.getRecommendationsArtifactsRolloverMax()).thenReturn(100);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    ServiceInfo service = mock(ServiceInfo.class);
+    when(metaInfo.getService(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(service);
+    when(service.getServiceAdvisorType()).thenReturn(ServiceInfo.ServiceAdvisorType.PYTHON);
     StackAdvisorHelper helper = new StackAdvisorHelper(configuration, saRunner, metaInfo);
     StackAdvisorRequestType requestType = StackAdvisorRequestType.HOST_GROUPS;
+    StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
+        .ofType(requestType).build();
 
-    StackAdvisorCommand<ValidationResponse> command = helper.createValidationCommand(requestType);
+    StackAdvisorCommand<ValidationResponse> command = helper.createValidationCommand("ZOOKEEPER", request);
 
     assertEquals(ComponentLayoutValidationCommand.class, command.getClass());
   }
@@ -171,10 +195,15 @@ public class StackAdvisorHelperTest {
     when(configuration.getRecommendationsArtifactsRolloverMax()).thenReturn(100);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    ServiceInfo service = mock(ServiceInfo.class);
+    when(metaInfo.getService(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(service);
+    when(service.getServiceAdvisorType()).thenReturn(ServiceInfo.ServiceAdvisorType.PYTHON);
     StackAdvisorHelper helper = new StackAdvisorHelper(configuration, saRunner, metaInfo);
     StackAdvisorRequestType requestType = StackAdvisorRequestType.CONFIGURATIONS;
+    StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
+        .ofType(requestType).build();
 
-    StackAdvisorCommand<ValidationResponse> command = helper.createValidationCommand(requestType);
+    StackAdvisorCommand<ValidationResponse> command = helper.createValidationCommand("ZOOKEEPER", request);
 
     assertEquals(ConfigurationValidationCommand.class, command.getClass());
   }
@@ -186,12 +215,16 @@ public class StackAdvisorHelperTest {
     when(configuration.getRecommendationsArtifactsRolloverMax()).thenReturn(100);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    ServiceInfo service = mock(ServiceInfo.class);
+    when(metaInfo.getService(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(service);
+    when(service.getServiceAdvisorType()).thenReturn(ServiceInfo.ServiceAdvisorType.PYTHON);
     StackAdvisorHelper helper = new StackAdvisorHelper(configuration, saRunner, metaInfo);
     StackAdvisorRequestType requestType = StackAdvisorRequestType.CONFIGURATION_DEPENDENCIES;
+    StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
+        .ofType(requestType).build();
 
-    StackAdvisorCommand<RecommendationResponse> command = helper.createRecommendationCommand(requestType);
+    StackAdvisorCommand<RecommendationResponse> command = helper.createRecommendationCommand("ZOOKEEPER", request);
 
     assertEquals(ConfigurationDependenciesRecommendationCommand.class, command.getClass());
   }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java
index 8d104ea..7eb9fb4 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRunnerTest.java
@@ -28,6 +28,7 @@ import java.io.File;
 import java.io.IOException;
 
 import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommandType;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -68,7 +69,7 @@ public class StackAdvisorRunnerTest {
         .toReturn(processBuilder);
     expect(processBuilder.start()).andThrow(new IOException());
     replay(processBuilder);
-    saRunner.runScript(script, saCommandType, actionDirectory);
+    saRunner.runScript(ServiceInfo.ServiceAdvisorType.PYTHON, saCommandType, actionDirectory);
   }
 
   @Test(expected = StackAdvisorRequestException.class)
@@ -85,7 +86,7 @@ public class StackAdvisorRunnerTest {
     expect(processBuilder.start()).andReturn(process);
     expect(process.waitFor()).andReturn(1);
     replay(processBuilder, process);
-    saRunner.runScript(script, saCommandType, actionDirectory);
+    saRunner.runScript(ServiceInfo.ServiceAdvisorType.PYTHON, saCommandType, actionDirectory);
   }
 
   @Test(expected = StackAdvisorException.class)
@@ -102,7 +103,7 @@ public class StackAdvisorRunnerTest {
     expect(processBuilder.start()).andReturn(process);
     expect(process.waitFor()).andReturn(2);
     replay(processBuilder, process);
-    saRunner.runScript(script, saCommandType, actionDirectory);
+    saRunner.runScript(ServiceInfo.ServiceAdvisorType.PYTHON, saCommandType, actionDirectory);
   }
 
   @Test
@@ -120,10 +121,9 @@ public class StackAdvisorRunnerTest {
     expect(process.waitFor()).andReturn(0);
     replay(processBuilder, process);
     try {
-      saRunner.runScript(script, saCommandType, actionDirectory);
+      saRunner.runScript(ServiceInfo.ServiceAdvisorType.PYTHON, saCommandType, actionDirectory);
     } catch (StackAdvisorException ex) {
       fail("Should not fail with StackAdvisorException");
     }
   }
-
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommandTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommandTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommandTest.java
index 17293eb..5e373c0 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommandTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommandTest.java
@@ -34,6 +34,7 @@ import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.junit.Test;
 
 public class ConfigurationRecommendationCommandTest {
@@ -43,7 +44,7 @@ public class ConfigurationRecommendationCommandTest {
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     File file = mock(File.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
-    ConfigurationRecommendationCommand command = new ConfigurationRecommendationCommand(file, "1w", "script", 1, saRunner, metaInfo);
+    ConfigurationRecommendationCommand command = new ConfigurationRecommendationCommand(file, "1w", ServiceInfo.ServiceAdvisorType.PYTHON, 1, saRunner, metaInfo);
 
     StackAdvisorRequest request = mock(StackAdvisorRequest.class);
     Map<String, Set<String>> componentHostGroupMap = new HashMap<>();

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
index 46552a3..eaa4716 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandTest.java
@@ -46,6 +46,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequestExc
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand.StackAdvisorData;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.commons.io.FileUtils;
 import org.codehaus.jackson.JsonNode;
 import org.codehaus.jackson.annotate.JsonProperty;
@@ -78,19 +79,18 @@ public class StackAdvisorCommandTest {
   public void testInvoke_invalidRequest_throwsException() throws StackAdvisorException {
     File recommendationsDir = temp.newFolder("recommendationDir");
     String recommendationsArtifactsLifetime = "1w";
-    String stackAdvisorScript = "echo";
     int requestId = 0;
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
     doReturn(Collections.emptyList()).when(metaInfo).getStackParentVersions(anyString(), anyString());
-    StackAdvisorCommand<TestResource> command = spy(new TestStackAdvisorCommand(recommendationsDir, recommendationsArtifactsLifetime, 
-        stackAdvisorScript, requestId, saRunner, metaInfo));
+    StackAdvisorCommand<TestResource> command = spy(new TestStackAdvisorCommand(recommendationsDir, recommendationsArtifactsLifetime,
+        ServiceInfo.ServiceAdvisorType.PYTHON, requestId, saRunner, metaInfo));
 
     StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
         .build();
 
     doThrow(new StackAdvisorException("message")).when(command).validate(request);
-    command.invoke(request);
+    command.invoke(request, ServiceInfo.ServiceAdvisorType.PYTHON);
 
     assertTrue(false);
   }
@@ -98,14 +98,13 @@ public class StackAdvisorCommandTest {
   @Test(expected = StackAdvisorException.class)
   public void testInvoke_saRunnerNotSucceed_throwsException() throws StackAdvisorException {
     File recommendationsDir = temp.newFolder("recommendationDir");
-    String stackAdvisorScript = "echo";
     String recommendationsArtifactsLifetime = "1w";
     int requestId = 0;
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
     doReturn(Collections.emptyList()).when(metaInfo).getStackParentVersions(anyString(), anyString());
     StackAdvisorCommand<TestResource> command = spy(new TestStackAdvisorCommand(recommendationsDir, recommendationsArtifactsLifetime,
-        stackAdvisorScript, requestId, saRunner, metaInfo));
+        ServiceInfo.ServiceAdvisorType.PYTHON, requestId, saRunner, metaInfo));
 
     StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
         .build();
@@ -117,24 +116,23 @@ public class StackAdvisorCommandTest {
     doReturn(servicesJSON).when(command).getServicesInformation(request);
     doReturn(data).when(command)
         .adjust(any(StackAdvisorData.class), any(StackAdvisorRequest.class));
-    doThrow(new StackAdvisorRequestException("error")).when(saRunner)
-        .runScript(any(String.class), any(StackAdvisorCommandType.class), any(File.class));
-    command.invoke(request);
 
+    doThrow(new StackAdvisorRequestException("error")).when(saRunner)
+        .runScript(any(ServiceInfo.ServiceAdvisorType.class), any(StackAdvisorCommandType.class), any(File.class));
+    command.invoke(request, ServiceInfo.ServiceAdvisorType.PYTHON);
     assertTrue(false);
   }
 
   @Test(expected = WebApplicationException.class)
   public void testInvoke_adjustThrowsException_throwsException() throws StackAdvisorException {
     File recommendationsDir = temp.newFolder("recommendationDir");
-    String stackAdvisorScript = "echo";
     String recommendationsArtifactsLifetime = "1w";
     int requestId = 0;
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
     doReturn(Collections.emptyList()).when(metaInfo).getStackParentVersions(anyString(), anyString());
     StackAdvisorCommand<TestResource> command = spy(new TestStackAdvisorCommand(recommendationsDir, recommendationsArtifactsLifetime,
-        stackAdvisorScript, requestId, saRunner, metaInfo));
+        ServiceInfo.ServiceAdvisorType.PYTHON, requestId, saRunner, metaInfo));
 
     StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
         .build();
@@ -143,9 +141,11 @@ public class StackAdvisorCommandTest {
     doReturn("{\"services\" : \"HDFS\"").when(command).getServicesInformation(request);
     doThrow(new WebApplicationException()).when(command).adjust(any(StackAdvisorData.class),
         any(StackAdvisorRequest.class));
+
     doThrow(new StackAdvisorException("error")).when(saRunner)
-        .runScript(any(String.class), any(StackAdvisorCommandType.class), any(File.class));
-    command.invoke(request);
+        .runScript(any(ServiceInfo.ServiceAdvisorType.class), any(StackAdvisorCommandType.class), any(File.class));
+    command.invoke(request, ServiceInfo.ServiceAdvisorType.PYTHON);
+
 
     assertTrue(false);
   }
@@ -155,14 +155,13 @@ public class StackAdvisorCommandTest {
     String expected = "success";
     final String testResourceString = String.format("{\"type\": \"%s\"}", expected);
     final File recommendationsDir = temp.newFolder("recommendationDir");
-    String stackAdvisorScript = "echo";
     String recommendationsArtifactsLifetime = "1w";
     final int requestId = 2;
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
     doReturn(Collections.emptyList()).when(metaInfo).getStackParentVersions(anyString(), anyString());
     final StackAdvisorCommand<TestResource> command = spy(new TestStackAdvisorCommand(
-        recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript, requestId, saRunner, metaInfo));
+        recommendationsDir, recommendationsArtifactsLifetime, ServiceInfo.ServiceAdvisorType.PYTHON, requestId, saRunner, metaInfo));
 
     StackAdvisorRequest request = StackAdvisorRequestBuilder.forStack("stackName", "stackVersion")
         .build();
@@ -174,6 +173,7 @@ public class StackAdvisorCommandTest {
     doReturn(servicesJSON).when(command).getServicesInformation(request);
     doReturn(data).when(command)
         .adjust(any(StackAdvisorData.class), any(StackAdvisorRequest.class));
+
     doAnswer(new Answer() {
       public Object answer(InvocationOnMock invocation) throws Throwable {
         String resultFilePath = String.format("%s/%s", requestId, command.getResultFileName());
@@ -182,8 +182,9 @@ public class StackAdvisorCommandTest {
         FileUtils.writeStringToFile(resultFile, testResourceString);
         return null;
       }
-    }).when(saRunner).runScript(any(String.class), any(StackAdvisorCommandType.class), any(File.class));
-    TestResource result = command.invoke(request);
+    }).when(saRunner).runScript(any(ServiceInfo.ServiceAdvisorType.class), any(StackAdvisorCommandType.class), any(File.class));
+
+    TestResource result = command.invoke(request, ServiceInfo.ServiceAdvisorType.PYTHON);
 
     assertEquals(expected, result.getType());
     assertEquals(requestId, result.getId());
@@ -195,7 +196,7 @@ public class StackAdvisorCommandTest {
     String recommendationsArtifactsLifetime = "1w";
     StackAdvisorRunner stackAdvisorRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo ambariMetaInfo = mock(AmbariMetaInfo.class);
-    StackAdvisorCommand<TestResource> cmd = new TestStackAdvisorCommand(file, recommendationsArtifactsLifetime, "test", 1,
+    StackAdvisorCommand<TestResource> cmd = new TestStackAdvisorCommand(file, recommendationsArtifactsLifetime, ServiceInfo.ServiceAdvisorType.PYTHON, 1,
         stackAdvisorRunner, ambariMetaInfo);
     ObjectNode objectNode = (ObjectNode) cmd.mapper.readTree("{\"Versions\": " +
         "{\"stack_name\": \"stack\", \"stack_version\":\"1.0.0\"}}");
@@ -223,7 +224,7 @@ public class StackAdvisorCommandTest {
     String recommendationsArtifactsLifetime = "1w";
     StackAdvisorRunner stackAdvisorRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo ambariMetaInfo = mock(AmbariMetaInfo.class);
-    StackAdvisorCommand<TestResource> cmd = new TestStackAdvisorCommand(file, recommendationsArtifactsLifetime, "test", 1,
+    StackAdvisorCommand<TestResource> cmd = new TestStackAdvisorCommand(file, recommendationsArtifactsLifetime, ServiceInfo.ServiceAdvisorType.PYTHON, 1,
       stackAdvisorRunner, ambariMetaInfo);
     ObjectNode objectNode = (ObjectNode) cmd.mapper.readTree("{\"Versions\": " +
       "{\"stack_name\": \"stack\", \"stack_version\":\"1.0.0\"}}");
@@ -245,7 +246,7 @@ public class StackAdvisorCommandTest {
     String recommendationsArtifactsLifetime = "1w";
     StackAdvisorRunner stackAdvisorRunner = mock(StackAdvisorRunner.class);
     AmbariMetaInfo ambariMetaInfo = mock(AmbariMetaInfo.class);
-    StackAdvisorCommand<TestResource> cmd = new TestStackAdvisorCommand(file, recommendationsArtifactsLifetime, "test", 1,
+    StackAdvisorCommand<TestResource> cmd = new TestStackAdvisorCommand(file, recommendationsArtifactsLifetime, ServiceInfo.ServiceAdvisorType.PYTHON, 1,
         stackAdvisorRunner, ambariMetaInfo);
     ObjectNode objectNode = (ObjectNode) cmd.mapper.readTree("{\"Versions\": " +
         "{\"stack_name\": \"stack\", \"stack_version\":\"1.0.0\"}}");
@@ -265,9 +266,9 @@ public class StackAdvisorCommandTest {
   }
 
   class TestStackAdvisorCommand extends StackAdvisorCommand<TestResource> {
-    public TestStackAdvisorCommand(File recommendationsDir, String recommendationsArtifactsLifetime, String stackAdvisorScript,
-        int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
-      super(recommendationsDir, recommendationsArtifactsLifetime, stackAdvisorScript, requestId, saRunner, metaInfo);
+    public TestStackAdvisorCommand(File recommendationsDir, String recommendationsArtifactsLifetime, ServiceInfo.ServiceAdvisorType serviceAdvisorType,
+                                   int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+      super(recommendationsDir, recommendationsArtifactsLifetime, serviceAdvisorType, requestId, saRunner, metaInfo);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
index 20d2168..784d884 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
@@ -439,6 +439,37 @@ public class ServiceModuleTest {
   }
 
   @Test
+  public void testResolveServiceAdvisor() throws Exception {
+    ServiceInfo info = new ServiceInfo();
+    ServiceInfo parentInfo = new ServiceInfo();
+    ServiceModule child = createServiceModule(info);
+    ServiceModule parent = createServiceModule(parentInfo);
+
+    // Parent is NULL, Child is NULL => Child defaults to PYTHON
+    parent.getModuleInfo().setServiceAdvisorType(null);
+    child.getModuleInfo().setServiceAdvisorType(null);
+    resolveService(child, parent);
+    assertEquals(ServiceInfo.ServiceAdvisorType.PYTHON, child.getModuleInfo().getServiceAdvisorType());
+
+    // Parent is NULL, Child is JAVA => Child is JAVA
+    child.getModuleInfo().setServiceAdvisorType(ServiceInfo.ServiceAdvisorType.JAVA);
+    resolveService(child, parent);
+    assertEquals(ServiceInfo.ServiceAdvisorType.JAVA, child.getModuleInfo().getServiceAdvisorType());
+
+    // Parent is JAVA, Child is NULL => Child inherits JAVA
+    parent.getModuleInfo().setServiceAdvisorType(ServiceInfo.ServiceAdvisorType.JAVA);
+    child.getModuleInfo().setServiceAdvisorType(null);
+    resolveService(child, parent);
+    assertEquals(ServiceInfo.ServiceAdvisorType.JAVA, child.getModuleInfo().getServiceAdvisorType());
+
+    // Parent is JAVA, Child is PYTHON => Child overrides and keeps PYTHON
+    parent.getModuleInfo().setServiceAdvisorType(null);
+    child.getModuleInfo().setServiceAdvisorType(ServiceInfo.ServiceAdvisorType.PYTHON);
+    resolveService(child, parent);
+    assertEquals(ServiceInfo.ServiceAdvisorType.PYTHON, child.getModuleInfo().getServiceAdvisorType());
+  }
+
+  @Test
   public void testResolve_UpgradeCheckDirectory() throws Exception {
     File checks = new File("checks");
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/ambari-views/examples/weather-view/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-views/examples/weather-view/pom.xml b/ambari-views/examples/weather-view/pom.xml
index abed017..d339fbb 100644
--- a/ambari-views/examples/weather-view/pom.xml
+++ b/ambari-views/examples/weather-view/pom.xml
@@ -81,7 +81,7 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.6</version>
+      <version>1.7.20</version>
     </dependency>
   </dependencies>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/contrib/views/hawq/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/hawq/pom.xml b/contrib/views/hawq/pom.xml
index 0c6591e..5a6e525 100644
--- a/contrib/views/hawq/pom.xml
+++ b/contrib/views/hawq/pom.xml
@@ -68,7 +68,7 @@
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
-            <version>1.7.5</version>
+            <version>1.7.20</version>
         </dependency>
         <dependency>
             <groupId>c3p0</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/contrib/views/hive-next/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/pom.xml b/contrib/views/hive-next/pom.xml
index 578a82c..9a6c65d 100644
--- a/contrib/views/hive-next/pom.xml
+++ b/contrib/views/hive-next/pom.xml
@@ -92,12 +92,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.5</version>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>
-      <version>1.7.5</version>
+      <version>1.7.20</version>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/contrib/views/hive20/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/hive20/pom.xml b/contrib/views/hive20/pom.xml
index 7ea95ad..0da3c88 100644
--- a/contrib/views/hive20/pom.xml
+++ b/contrib/views/hive20/pom.xml
@@ -93,12 +93,12 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.5</version>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-simple</artifactId>
-      <version>1.7.5</version>
+      <version>1.7.20</version>
       <scope>test</scope>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/contrib/views/pig/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/pig/pom.xml b/contrib/views/pig/pom.xml
index 5239cc2..1430f69 100644
--- a/contrib/views/pig/pom.xml
+++ b/contrib/views/pig/pom.xml
@@ -80,7 +80,7 @@
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.5</version>
+      <version>1.7.20</version>
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/contrib/views/tez/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/tez/pom.xml b/contrib/views/tez/pom.xml
index 170b89a..fa1a773 100644
--- a/contrib/views/tez/pom.xml
+++ b/contrib/views/tez/pom.xml
@@ -236,11 +236,10 @@
       <groupId>com.google.inject</groupId>
       <artifactId>guice</artifactId>
     </dependency>
-
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.7.5</version>
+      <version>1.7.20</version>
     </dependency>
 
     <dependency>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/contrib/views/wfmanager/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/pom.xml b/contrib/views/wfmanager/pom.xml
index a38cae5..1363a93 100644
--- a/contrib/views/wfmanager/pom.xml
+++ b/contrib/views/wfmanager/pom.xml
@@ -74,6 +74,7 @@
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>slf4j-api</artifactId>
+			<version>1.7.20</version>
 		</dependency>
 		<dependency>
 			<groupId>javax.inject</groupId>

http://git-wip-us.apache.org/repos/asf/ambari/blob/f1ca09c0/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 8faec29..4e27ca6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -264,7 +264,9 @@
             <exclude>pass.txt</exclude>
             <exclude>ambari-metrics/ambari-metrics-host-monitoring/conf/unix/metric_groups.conf</exclude>
             <exclude>ambari-metrics/ambari-metrics-host-monitoring/conf/windows/metric_groups.conf</exclude>
-            <exclude>contrib/addons/test/dataServices/jmx/data/cluster_configuration.json.nohbase</exclude>
+            <exclude>ambari-metrics/ambari-metrics-host-monitoring/conf/unix/metric_groups.conf</exclude>
+            <exclude>stack-advisor/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst</exclude>
+            <exclude>stack-advisor/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst</exclude>
             <exclude>contrib/ambari-scom/msi/src/GUI_Ambari.sln</exclude>
             <exclude>contrib/fast-hdfs-resource/dependency-reduced-pom.xml</exclude>
             <exclude>contrib/agent-simulator/docker_image/package_list.txt</exclude>
@@ -457,6 +459,7 @@
         </property>
       </activation>
       <modules>
+        <module>serviceadvisor</module>
         <module>ambari-web</module>
         <module>ambari-project</module>
         <module>ambari-views</module>
@@ -480,6 +483,7 @@
         </property>
       </activation>
       <modules>
+        <module>serviceadvisor</module>
         <module>ambari-web</module>
         <module>ambari-project</module>
         <module>ambari-views</module>
@@ -507,6 +511,7 @@
         <module>ambari-shell</module>
         <module>ambari-logsearch</module>
         <module>ambari-infra</module>
+        <module>serviceadvisor</module>
       </modules>
     </profile>
     <profile>
@@ -529,6 +534,7 @@
         <module>ambari-shell</module>
         <module>ambari-logsearch</module>
         <module>ambari-infra</module>
+        <module>serviceadvisor</module>
         </modules>
     </profile>
     <profile>
@@ -538,6 +544,12 @@
       </modules>
     </profile>
     <profile>
+      <id>serviceadvisor</id>
+      <modules>
+        <module>serviceadvisor</module>
+      </modules>
+    </profile>
+    <profile>
       <id>windows</id>
       <activation>
         <os>
@@ -545,6 +557,7 @@
         </os>
       </activation>
       <modules>
+        <module>serviceadvisor</module>
         <module>ambari-web</module>
         <module>ambari-project</module>
         <module>ambari-views</module>
@@ -555,7 +568,7 @@
         <module>ambari-agent</module>
         <module>ambari-client</module>
         <module>ambari-shell</module>
-        </modules>
+      </modules>
     </profile>
     <profile>
       <id>clover</id>