Explorar el Código

AMBARI-10207. BE: Extend stack-advisor to recommend property_value_attributes (mpapyrkovskyy via srimanth)

Srimanth Gunturi hace 10 años
padre
commit
d7fcd258d9
Se han modificado 31 ficheros con 734 adiciones y 100 borrados
  1. 41 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
  2. 12 8
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java
  3. 20 1
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java
  4. 8 5
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutRecommendationCommand.java
  5. 3 3
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutValidationCommand.java
  6. 119 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationDependenciesRecommendationCommand.java
  7. 3 3
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommand.java
  8. 3 3
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationValidationCommand.java
  9. 26 13
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java
  10. 2 0
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandType.java
  11. 33 3
      ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/recommendations/RecommendationResponse.java
  12. 28 6
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProvider.java
  13. 11 3
      ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java
  14. 8 8
      ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/configuration-mapred/mapred-site.xml
  15. 2 2
      ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/configuration/yarn-site.xml
  16. 1 0
      ambari-server/src/main/resources/properties.json
  17. 49 1
      ambari-server/src/main/resources/scripts/stack_advisor.py
  18. 1 1
      ambari-server/src/main/resources/stacks/BIGTOP/0.8/services/stack_advisor.py
  19. 49 9
      ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py
  20. 2 2
      ambari-server/src/main/resources/stacks/HDP/2.2/services/YARN/configuration/yarn-site.xml
  21. 25 3
      ambari-server/src/main/resources/stacks/HDP/2.2/services/stack_advisor.py
  22. 1 1
      ambari-server/src/main/resources/stacks/HDPWIN/2.1/services/stack_advisor.py
  23. 1 1
      ambari-server/src/main/resources/stacks/PHD/3.0.0.0/services/stack_advisor.py
  24. 2 2
      ambari-server/src/main/resources/stacks/stack_advisor.py
  25. 17 3
      ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
  26. 24 9
      ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java
  27. 2 2
      ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommandTest.java
  28. 4 4
      ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py
  29. 1 1
      ambari-server/src/test/python/stacks/2.1/common/test_stack_advisor.py
  30. 221 1
      ambari-server/src/test/python/stacks/2.2/common/test_stack_advisor.py
  31. 15 2
      ambari-server/src/test/resources/stacks/HDP/2.0.6/services/YARN/configuration/yarn-site.xml

+ 41 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java

@@ -59,8 +59,10 @@ import org.apache.ambari.server.stack.StackManager;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.DependencyInfo;
 import org.apache.ambari.server.state.OperatingSystemInfo;
+import org.apache.ambari.server.state.PropertyDependencyInfo;
 import org.apache.ambari.server.state.PropertyInfo;
 import org.apache.ambari.server.state.RepositoryInfo;
 import org.apache.ambari.server.state.Service;
@@ -1221,4 +1223,43 @@ public class AmbariMetaInfo {
 
     return kerberosServiceDescriptors;
   }
+
+  /**
+   * Get set of all the depended-by properties down to directed acyclic graph(DAG)
+   * of dependencies between configuration properties
+   * @param stackName the stack name
+   * @param stackVersion the stack version
+   * @param changedConfigs the list of changed configurations
+   * @return set of all depended-by properties including all changedConfigs
+   */
+  public Set<PropertyDependencyInfo> getDependedByProperties(String stackName,
+                                                             String stackVersion,
+                                                             List<PropertyDependencyInfo> changedConfigs) {
+    StackInfo stack = getStackManager().getStack(stackName, stackVersion);
+
+    if (changedConfigs == null) {
+      return Collections.emptySet();
+    }
+    int size = 0;
+    Set<PropertyDependencyInfo> configs =
+      new HashSet<PropertyDependencyInfo>();
+
+    configs.addAll(changedConfigs);
+
+    while (size != configs.size()) {
+      size = configs.size();
+      for (ServiceInfo service: stack.getServices()) {
+        for (PropertyInfo pi: service.getProperties()) {
+          String type = ConfigHelper.fileNameToConfigType(pi.getFilename());
+          String name = pi.getName();
+          PropertyDependencyInfo dep =
+            new PropertyDependencyInfo(type, name);
+          if (configs.contains(dep) && !configs.containsAll(pi.getDependedByProperties())) {
+            configs.addAll(pi.getDependedByProperties());
+          }
+        }
+      }
+    }
+    return configs;
+  }
 }

+ 12 - 8
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelper.java

@@ -23,10 +23,11 @@ import java.io.IOException;
 
 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.GetComponentLayoutRecommnedationCommand;
-import org.apache.ambari.server.api.services.stackadvisor.commands.GetComponentLayoutValidationCommand;
-import org.apache.ambari.server.api.services.stackadvisor.commands.GetConfigurationRecommnedationCommand;
-import org.apache.ambari.server.api.services.stackadvisor.commands.GetConfigurationValidationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ComponentLayoutRecommendationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ComponentLayoutValidationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ConfigurationDependenciesRecommendationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ConfigurationRecommendationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ConfigurationValidationCommand;
 import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
 import org.apache.ambari.server.api.services.stackadvisor.validations.ValidationResponse;
@@ -77,10 +78,10 @@ public class StackAdvisorHelper {
       StackAdvisorRequestType requestType) throws StackAdvisorException {
     StackAdvisorCommand<ValidationResponse> command;
     if (requestType == StackAdvisorRequestType.HOST_GROUPS) {
-      command = new GetComponentLayoutValidationCommand(recommendationsDir, stackAdvisorScript,
+      command = new ComponentLayoutValidationCommand(recommendationsDir, stackAdvisorScript,
           requestId, saRunner, metaInfo);
     } else if (requestType == StackAdvisorRequestType.CONFIGURATIONS) {
-      command = new GetConfigurationValidationCommand(recommendationsDir, stackAdvisorScript,
+      command = new ConfigurationValidationCommand(recommendationsDir, stackAdvisorScript,
           requestId, saRunner, metaInfo);
     } else {
       throw new StackAdvisorRequestException(String.format("Unsupported request type, type=%s",
@@ -112,10 +113,13 @@ public class StackAdvisorHelper {
       StackAdvisorRequestType requestType) throws StackAdvisorException {
     StackAdvisorCommand<RecommendationResponse> command;
     if (requestType == StackAdvisorRequestType.HOST_GROUPS) {
-      command = new GetComponentLayoutRecommnedationCommand(recommendationsDir, stackAdvisorScript,
+      command = new ComponentLayoutRecommendationCommand(recommendationsDir, stackAdvisorScript,
           requestId, saRunner, metaInfo);
     } else if (requestType == StackAdvisorRequestType.CONFIGURATIONS) {
-      command = new GetConfigurationRecommnedationCommand(recommendationsDir, stackAdvisorScript,
+      command = new ConfigurationRecommendationCommand(recommendationsDir, stackAdvisorScript,
+          requestId, saRunner, metaInfo);
+    } else if (requestType == StackAdvisorRequestType.CONFIGURATION_DEPENDENCIES) {
+      command = new ConfigurationDependenciesRecommendationCommand(recommendationsDir, stackAdvisorScript,
           requestId, saRunner, metaInfo);
     } else {
       throw new StackAdvisorRequestException(String.format("Unsupported request type, type=%s",

+ 20 - 1
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorRequest.java

@@ -21,10 +21,12 @@ package org.apache.ambari.server.api.services.stackadvisor;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.ambari.server.state.PropertyDependencyInfo;
 import org.apache.commons.lang.StringUtils;
 
 /**
@@ -41,6 +43,7 @@ public class StackAdvisorRequest {
   private Map<String, Set<String>> hostComponents = new HashMap<String, Set<String>>();
   private Map<String, Set<String>> hostGroupBindings = new HashMap<String, Set<String>>();
   private Map<String, Map<String, Map<String, String>>> configurations = new HashMap<String, Map<String, Map<String, String>>>();
+  private List<PropertyDependencyInfo> changedConfigurations = new LinkedList<PropertyDependencyInfo>();
 
   public String getStackName() {
     return stackName;
@@ -86,6 +89,14 @@ public class StackAdvisorRequest {
     return configurations;
   }
 
+  public List<PropertyDependencyInfo> getChangedConfigurations() {
+    return changedConfigurations;
+  }
+
+  public void setChangedConfigurations(List<PropertyDependencyInfo> changedConfigurations) {
+    this.changedConfigurations = changedConfigurations;
+  }
+
   private StackAdvisorRequest(String stackName, String stackVersion) {
     this.stackName = stackName;
     this.stackVersion = stackVersion;
@@ -140,13 +151,21 @@ public class StackAdvisorRequest {
       return this;
     }
 
+    public StackAdvisorRequestBuilder withChangedConfigurations(
+      List<PropertyDependencyInfo> changedConfigurations) {
+      this.instance.changedConfigurations = changedConfigurations;
+      return this;
+    }
+
     public StackAdvisorRequest build() {
       return this.instance;
     }
   }
 
   public enum StackAdvisorRequestType {
-    HOST_GROUPS("host_groups"), CONFIGURATIONS("configurations");
+    HOST_GROUPS("host_groups"),
+    CONFIGURATIONS("configurations"),
+    CONFIGURATION_DEPENDENCIES("configuration-dependencies");
 
     private String type;
 

+ 8 - 5
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetComponentLayoutRecommnedationCommand.java → ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutRecommendationCommand.java

@@ -30,11 +30,14 @@ import org.apache.ambari.server.api.services.stackadvisor.recommendations.Recomm
  * {@link StackAdvisorCommand} implementation for component-layout
  * recommendation.
  */
-public class GetComponentLayoutRecommnedationCommand extends
+public class ComponentLayoutRecommendationCommand extends
     StackAdvisorCommand<RecommendationResponse> {
 
-  public GetComponentLayoutRecommnedationCommand(File recommendationsDir,
-      String stackAdvisorScript, int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+  public ComponentLayoutRecommendationCommand(File recommendationsDir,
+                                              String stackAdvisorScript,
+                                              int requestId,
+                                              StackAdvisorRunner saRunner,
+                                              AmbariMetaInfo metaInfo) {
     super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
   }
 
@@ -45,8 +48,8 @@ public class GetComponentLayoutRecommnedationCommand extends
 
   @Override
   protected void validate(StackAdvisorRequest request) throws StackAdvisorException {
-    if (request.getHosts() == null || request.getHosts().isEmpty() || request.getServices() == null
-        || request.getServices().isEmpty()) {
+    if (request.getHosts() == null || request.getHosts().isEmpty()
+      || request.getServices() == null || request.getServices().isEmpty()) {
       throw new StackAdvisorException("Hosts and services must not be empty");
     }
   }

+ 3 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetComponentLayoutValidationCommand.java → ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ComponentLayoutValidationCommand.java

@@ -29,10 +29,10 @@ import org.apache.ambari.server.api.services.stackadvisor.validations.Validation
 /**
  * {@link StackAdvisorCommand} implementation for component-layout validation.
  */
-public class GetComponentLayoutValidationCommand extends StackAdvisorCommand<ValidationResponse> {
+public class ComponentLayoutValidationCommand extends StackAdvisorCommand<ValidationResponse> {
 
-  public GetComponentLayoutValidationCommand(File recommendationsDir, String stackAdvisorScript,
-      int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+  public ComponentLayoutValidationCommand(File recommendationsDir, String stackAdvisorScript,
+                                          int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
     super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
   }
 

+ 119 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationDependenciesRecommendationCommand.java

@@ -0,0 +1,119 @@
+/**
+ * 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.server.api.services.stackadvisor.commands;
+
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+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 java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse.BindingHostGroup;
+import static org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse.HostGroup;
+
+/**
+ * {@link StackAdvisorCommand} implementation for
+ * configuration dependencies recommendation.
+ */
+public class ConfigurationDependenciesRecommendationCommand extends
+    StackAdvisorCommand<RecommendationResponse> {
+
+  public ConfigurationDependenciesRecommendationCommand(File recommendationsDir, String stackAdvisorScript, int requestId,
+                                                        StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+    super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
+  }
+
+  @Override
+  protected StackAdvisorCommandType getCommandType() {
+    return StackAdvisorCommandType.RECOMMEND_CONFIGURATION_DEPENDENCIES;
+  }
+
+  @Override
+  protected void validate(StackAdvisorRequest request)
+    throws StackAdvisorException {
+    if (request.getHosts() == null || request.getHosts().isEmpty()
+      || request.getServices() == null || request.getServices().isEmpty()
+      || request.getChangedConfigurations() == null
+      || request.getChangedConfigurations().isEmpty()) {
+      throw new StackAdvisorException("Hosts, services and changed-configurations must not be empty");
+    }
+  }
+
+  @Override
+  protected RecommendationResponse updateResponse(StackAdvisorRequest request,
+                                                  RecommendationResponse response) {
+    response.getRecommendations().getBlueprint().setHostGroups(processHostGroups(request));
+    response.getRecommendations().getBlueprintClusterBinding().setHostGroups(processHostGroupBindings(request));
+    return response;
+  }
+
+  protected Set<HostGroup> processHostGroups(StackAdvisorRequest request) {
+    Set<HostGroup> resultSet = new HashSet<HostGroup>();
+    for (Map.Entry<String, Set<String>> componentHost : request.getHostComponents().entrySet()) {
+      String hostGroupName = componentHost.getKey();
+      Set<String> components = componentHost.getValue();
+      if (hostGroupName != null && components != null) {
+        HostGroup hostGroup = new HostGroup();
+        Set<Map<String, String>> componentsSet = new HashSet<Map<String, String>>();
+        for (String component : components) {
+          Map<String, String> componentMap = new HashMap<String, String>();
+          componentMap.put("name", component);
+          componentsSet.add(componentMap);
+        }
+        hostGroup.setComponents(componentsSet);
+        hostGroup.setName(hostGroupName);
+        resultSet.add(hostGroup);
+      }
+    }
+    return resultSet;
+  }
+
+  private Set<BindingHostGroup> processHostGroupBindings(StackAdvisorRequest request) {
+    Set<BindingHostGroup> resultSet = new HashSet<BindingHostGroup>();
+    for (Map.Entry<String, Set<String>> hostBinding : request.getHostGroupBindings().entrySet()) {
+      String hostGroupName = hostBinding.getKey();
+      Set<String> hosts = hostBinding.getValue();
+      if (hostGroupName != null && hosts != null) {
+        BindingHostGroup bindingHostGroup = new BindingHostGroup();
+        Set<Map<String, String>> hostsSet = new HashSet<Map<String, String>>();
+        for (String host : hosts) {
+          Map<String, String> hostMap = new HashMap<String, String>();
+          hostMap.put("name", host);
+          hostsSet.add(hostMap);
+        }
+        bindingHostGroup.setHosts(hostsSet);
+        bindingHostGroup.setName(hostGroupName);
+        resultSet.add(bindingHostGroup);
+      }
+    }
+    return resultSet;
+  }
+
+  @Override
+  protected String getResultFileName() {
+    return "configurations.json";
+  }
+
+}

+ 3 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetConfigurationRecommnedationCommand.java → ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommand.java

@@ -35,11 +35,11 @@ import java.util.Set;
  * {@link org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand} implementation for
  * configuration recommendation.
  */
-public class GetConfigurationRecommnedationCommand extends
+public class ConfigurationRecommendationCommand extends
     StackAdvisorCommand<RecommendationResponse> {
 
-  public GetConfigurationRecommnedationCommand(File recommendationsDir, String stackAdvisorScript, int requestId,
-                                               StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+  public ConfigurationRecommendationCommand(File recommendationsDir, String stackAdvisorScript, int requestId,
+                                            StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
     super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
   }
 

+ 3 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetConfigurationValidationCommand.java → ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationValidationCommand.java

@@ -29,10 +29,10 @@ import org.apache.ambari.server.api.services.stackadvisor.validations.Validation
 /**
  * {@link StackAdvisorCommand} implementation for configuration validation.
  */
-public class GetConfigurationValidationCommand extends StackAdvisorCommand<ValidationResponse> {
+public class ConfigurationValidationCommand extends StackAdvisorCommand<ValidationResponse> {
 
-  public GetConfigurationValidationCommand(File recommendationsDir, String stackAdvisorScript,
-      int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
+  public ConfigurationValidationCommand(File recommendationsDir, String stackAdvisorScript,
+                                        int requestId, StackAdvisorRunner saRunner, AmbariMetaInfo metaInfo) {
     super(recommendationsDir, stackAdvisorScript, requestId, saRunner, metaInfo);
   }
 

+ 26 - 13
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommand.java

@@ -44,6 +44,7 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.state.PropertyDependencyInfo;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.logging.Log;
@@ -75,12 +76,14 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
       + ",services/StackServices/service_name,services/StackServices/service_version"
       + ",services/components/StackServiceComponents,services/components/dependencies,services/components/auto_deploy"
       + "&services/StackServices/service_name.in(%s)";
-  private static final String SERVICES_PROPETRY = "services";
-  private static final String SERVICES_COMPONENTS_PROPETRY = "components";
-  private static final String COMPONENT_INFO_PROPETRY = "StackServiceComponents";
+  private static final String SERVICES_PROPERTY = "services";
+  private static final String SERVICES_COMPONENTS_PROPERTY = "components";
+  private static final String COMPONENT_INFO_PROPERTY = "StackServiceComponents";
   private static final String COMPONENT_NAME_PROPERTY = "component_name";
-  private static final String COMPONENT_HOSTNAMES_PROPETRY = "hostnames";
-  private static final String CONFIGURATIONS_PROPETRY = "configurations";
+  private static final String COMPONENT_HOSTNAMES_PROPERTY = "hostnames";
+  private static final String CONFIGURATIONS_PROPERTY = "configurations";
+  private static final String CHANGED_CONFIGURATIONS_PROPERTY = "changed-configurations";
+  private static final String DEPENDED_CONFIGURATIONS_PROPERTY = "depended-configurations";
 
   private File recommendationsDir;
   private String stackAdvisorScript;
@@ -140,8 +143,7 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
 
       populateStackHierarchy(root);
       populateComponentHostsMap(root, request.getComponentHostsMap());
-      populateConfigurations(root, request.getConfigurations());
-
+      populateConfigurations(root, request);
       data.servicesJSON = mapper.writeValueAsString(root);
     } catch (Exception e) {
       // should not happen
@@ -154,8 +156,10 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
   }
 
   private void populateConfigurations(ObjectNode root,
-      Map<String, Map<String, Map<String, String>>> configurations) {
-    ObjectNode configurationsNode = root.putObject(CONFIGURATIONS_PROPETRY);
+                                      StackAdvisorRequest request) {
+    Map<String, Map<String, Map<String, String>>> configurations =
+      request.getConfigurations();
+    ObjectNode configurationsNode = root.putObject(CONFIGURATIONS_PROPERTY);
     for (String siteName : configurations.keySet()) {
       ObjectNode siteNode = configurationsNode.putObject(siteName);
 
@@ -170,6 +174,15 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
         }
       }
     }
+    // Populating changed configs info and depended by configs info
+    Set<PropertyDependencyInfo> dependedProperties =
+      metaInfo.getDependedByProperties(request.getStackName(),
+      request.getStackVersion(), request.getChangedConfigurations());
+
+    JsonNode changedConfigs = mapper.valueToTree(request.getChangedConfigurations());
+    JsonNode dependendConfigs = mapper.valueToTree(dependedProperties);
+    root.put(CHANGED_CONFIGURATIONS_PROPERTY, changedConfigs);
+    root.put(DEPENDED_CONFIGURATIONS_PROPERTY, dependendConfigs);
   }
 
   protected void populateStackHierarchy(ObjectNode root) {
@@ -185,21 +198,21 @@ public abstract class StackAdvisorCommand<T extends StackAdvisorResponse> extend
   }
 
   private void populateComponentHostsMap(ObjectNode root, Map<String, Set<String>> componentHostsMap) {
-    ArrayNode services = (ArrayNode) root.get(SERVICES_PROPETRY);
+    ArrayNode services = (ArrayNode) root.get(SERVICES_PROPERTY);
     Iterator<JsonNode> servicesIter = services.getElements();
 
     while (servicesIter.hasNext()) {
       JsonNode service = servicesIter.next();
-      ArrayNode components = (ArrayNode) service.get(SERVICES_COMPONENTS_PROPETRY);
+      ArrayNode components = (ArrayNode) service.get(SERVICES_COMPONENTS_PROPERTY);
       Iterator<JsonNode> componentsIter = components.getElements();
 
       while (componentsIter.hasNext()) {
         JsonNode component = componentsIter.next();
-        ObjectNode componentInfo = (ObjectNode) component.get(COMPONENT_INFO_PROPETRY);
+        ObjectNode componentInfo = (ObjectNode) component.get(COMPONENT_INFO_PROPERTY);
         String componentName = componentInfo.get(COMPONENT_NAME_PROPERTY).getTextValue();
 
         Set<String> componentHosts = componentHostsMap.get(componentName);
-        ArrayNode hostnames = componentInfo.putArray(COMPONENT_HOSTNAMES_PROPETRY);
+        ArrayNode hostnames = componentInfo.putArray(COMPONENT_HOSTNAMES_PROPERTY);
         if (null != componentHosts) {
           for (String hostName : componentHosts) {
             hostnames.add(hostName);

+ 2 - 0
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/commands/StackAdvisorCommandType.java

@@ -29,6 +29,8 @@ public enum StackAdvisorCommandType {
 
   RECOMMEND_CONFIGURATIONS("recommend-configurations"),
 
+  RECOMMEND_CONFIGURATION_DEPENDENCIES("recommend-configuration-dependencies"),
+
   VALIDATE_CONFIGURATIONS("validate-configurations");
 
   private final String name;

+ 33 - 3
ambari-server/src/main/java/org/apache/ambari/server/api/services/stackadvisor/recommendations/RecommendationResponse.java

@@ -23,6 +23,7 @@ import java.util.Set;
 
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorResponse;
 import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
 
 /**
  * Recommendation response POJO.
@@ -88,16 +89,16 @@ public class RecommendationResponse extends StackAdvisorResponse {
 
   public static class Blueprint {
     @JsonProperty
-    private Map<String, Map<String, Map<String, String>>> configurations;
+    private Map<String, BlueprintConfigurations> configurations;
 
     @JsonProperty("host_groups")
     private Set<HostGroup> hostGroups;
 
-    public Map<String, Map<String, Map<String, String>>> getConfigurations() {
+    public Map<String, BlueprintConfigurations> getConfigurations() {
       return configurations;
     }
 
-    public void setConfigurations(Map<String, Map<String, Map<String, String>>> configurations) {
+    public void setConfigurations(Map<String, BlueprintConfigurations> configurations) {
       this.configurations = configurations;
     }
 
@@ -110,6 +111,35 @@ public class RecommendationResponse extends StackAdvisorResponse {
     }
   }
 
+  public static class BlueprintConfigurations {
+    @JsonProperty
+    private Map<String, String> properties;
+
+    @JsonProperty("property_attributes")
+    @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
+    private Map<String, Map<String, String>> propertyAttributes;
+
+    public BlueprintConfigurations() {
+      System.out.println(this);
+    }
+
+    public Map<String, String> getProperties() {
+      return properties;
+    }
+
+    public void setProperties(Map<String, String> properties) {
+      this.properties = properties;
+    }
+
+    public Map<String, Map<String, String>> getPropertyAttributes() {
+      return propertyAttributes;
+    }
+
+    public void setPropertyAttributes(Map<String, Map<String, String>> propertyAttributes) {
+      this.propertyAttributes = propertyAttributes;
+    }
+  }
+
   public static class HostGroup {
     @JsonProperty
     private String name;

+ 28 - 6
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackAdvisorResourceProvider.java

@@ -18,8 +18,10 @@
 
 package org.apache.ambari.server.controller.internal;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -38,6 +40,7 @@ import org.apache.ambari.server.controller.spi.Resource.Type;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 
 import com.google.inject.Inject;
+import org.apache.ambari.server.state.PropertyDependencyInfo;
 
 /**
  * Abstract superclass for recommendations and validations.
@@ -52,6 +55,8 @@ public abstract class StackAdvisorResourceProvider extends ReadOnlyResourceProvi
   private static final String HOST_PROPERTY = "hosts";
   private static final String SERVICES_PROPERTY = "services";
 
+  private static final String CHANGED_CONFIGURATIONS_PROPERTY = "changed_configurations";
+
   private static final String BLUEPRINT_HOST_GROUPS_PROPERTY = "recommendations/blueprint/host_groups";
   private static final String BINDING_HOST_GROUPS_PROPERTY = "recommendations/blueprint_cluster_binding/host_groups";
 
@@ -99,12 +104,17 @@ public abstract class StackAdvisorResourceProvider extends ReadOnlyResourceProvi
           hgHostsMap);
       Map<String, Map<String, Map<String, String>>> configurations = calculateConfigurations(request);
 
-      StackAdvisorRequest saRequest = StackAdvisorRequestBuilder.forStack(stackName, stackVersion)
-          .ofType(requestType).forHosts(hosts).forServices(services)
-          .forHostComponents(hgComponentsMap).forHostsGroupBindings(hgHostsMap)
-          .withComponentHostsMap(componentHostsMap).withConfigurations(configurations).build();
-
-      return saRequest;
+      List<PropertyDependencyInfo> changedConfigurations =
+        requestType == StackAdvisorRequestType.CONFIGURATION_DEPENDENCIES ?
+          calculateChangedConfigurations(request) : Collections.<PropertyDependencyInfo>emptyList();
+
+      return StackAdvisorRequestBuilder.
+        forStack(stackName, stackVersion).ofType(requestType).forHosts(hosts).
+        forServices(services).forHostComponents(hgComponentsMap).
+        forHostsGroupBindings(hgHostsMap).
+        withComponentHostsMap(componentHostsMap).
+        withConfigurations(configurations).
+        withChangedConfigurations(changedConfigurations).build();
     } catch (Exception e) {
       LOG.warn("Error occured during preparation of stack advisor request", e);
       Response response = Response.status(Status.BAD_REQUEST)
@@ -176,6 +186,18 @@ public abstract class StackAdvisorResourceProvider extends ReadOnlyResourceProvi
     return map;
   }
 
+  protected List<PropertyDependencyInfo> calculateChangedConfigurations(Request request) {
+    List<PropertyDependencyInfo> configs =
+      new LinkedList<PropertyDependencyInfo>();
+    HashSet<HashMap<String, String>> changedConfigs =
+      (HashSet<HashMap<String, String>>) getRequestProperty(request, CHANGED_CONFIGURATIONS_PROPERTY);
+    for (HashMap<String, String> props: changedConfigs) {
+      configs.add(new PropertyDependencyInfo(props.get("type"), props.get("name")));
+    }
+
+    return configs;
+  }
+
   protected static final String CONFIGURATIONS_PROPERTY_ID = "recommendations/blueprint/configurations/";
 
   protected Map<String, Map<String, Map<String, String>>> calculateConfigurations(Request request) {

+ 11 - 3
ambari-server/src/main/java/org/apache/ambari/server/stack/StackModule.java

@@ -29,6 +29,7 @@ import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.PropertyDependencyInfo;
 import org.apache.ambari.server.state.PropertyInfo;
 import org.apache.ambari.server.state.RepositoryInfo;
@@ -597,11 +598,15 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
     for (ServiceModule serviceModule : serviceModules.values()) {
       for (PropertyInfo pi : serviceModule.getModuleInfo().getProperties()) {
         for (PropertyDependencyInfo pdi : pi.getDependsOnProperties()) {
-          PropertyDependencyInfo propertyDependency = new PropertyDependencyInfo(pi.getFilename(), pi.getName());
+          String type = ConfigHelper.fileNameToConfigType(pi.getFilename());
+          String name = pi.getName();
+          PropertyDependencyInfo propertyDependency =
+            new PropertyDependencyInfo(type, name);
           if (dependedByMap.keySet().contains(pdi)) {
             dependedByMap.get(pdi).add(propertyDependency);
           } else {
-            Set<PropertyDependencyInfo> newDependenciesSet = new HashSet<PropertyDependencyInfo>();
+            Set<PropertyDependencyInfo> newDependenciesSet =
+              new HashSet<PropertyDependencyInfo>();
             newDependenciesSet.add(propertyDependency);
             dependedByMap.put(pdi, newDependenciesSet);
           }
@@ -612,7 +617,10 @@ public class StackModule extends BaseModule<StackModule, StackInfo> implements V
     // Go through all service-configs again and set their 'depended-by' if necessary.
     for (ServiceModule serviceModule : serviceModules.values()) {
       for (PropertyInfo pi : serviceModule.getModuleInfo().getProperties()) {
-        Set<PropertyDependencyInfo> set = dependedByMap.remove(new PropertyDependencyInfo(pi.getFilename(), pi.getName()));
+        String type = ConfigHelper.fileNameToConfigType(pi.getFilename());
+        String name = pi.getName();
+        Set<PropertyDependencyInfo> set =
+          dependedByMap.remove(new PropertyDependencyInfo(type, name));
         if (set != null) {
           pi.getDependedByProperties().addAll(set);
         }

+ 8 - 8
ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/configuration-mapred/mapred-site.xml

@@ -41,7 +41,7 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>mapred-site.xml</type>
+        <type>mapred-site</type>
         <name>mapreduce.map.memory.mb</name>
       </property>
     </depends-on>
@@ -186,7 +186,7 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>yarn-site.xml</type>
+        <type>yarn-site</type>
         <name>yarn.scheduler.maximum-allocation-mb</name>
       </property>
     </depends-on>
@@ -206,7 +206,7 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>yarn-site.xml</type>
+        <type>yarn-site</type>
         <name>yarn.scheduler.maximum-allocation-mb</name>
       </property>
     </depends-on>
@@ -281,7 +281,7 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>yarn-site.xml</type>
+        <type>yarn-site</type>
         <name>yarn.scheduler.maximum-allocation-mb</name>
       </property>
     </depends-on>
@@ -306,7 +306,7 @@
     <display-name>MR AppMaster Java Heap Size</display-name>
     <depends-on>
       <property>
-        <type>mapred-site.xml</type>
+        <type>mapred-site</type>
         <name>yarn.app.mapreduce.am.resource.mb</name>
       </property>
     </depends-on>
@@ -328,7 +328,7 @@
     <display-name>MR AppMaster Java Heap Size</display-name>
     <depends-on>
       <property>
-        <type>mapred-site.xml</type>
+        <type>mapred-site</type>
         <name>yarn.app.mapreduce.am.resource.mb</name>
       </property>
     </depends-on>
@@ -383,7 +383,7 @@
     <display-name>MR Map Java Heap Size</display-name>
     <depends-on>
       <property>
-        <type>mapred-site.xml</type>
+        <type>mapred-site</type>
         <name>mapreduce.map.memory.mb</name>
       </property>
     </depends-on>
@@ -399,7 +399,7 @@
     <display-name>MR Reduce Java Heap Size</display-name>
     <depends-on>
       <property>
-        <type>mapred-site.xml</type>
+        <type>mapred-site</type>
         <name>mapreduce.reduce.memory.mb</name>
       </property>
     </depends-on>

+ 2 - 2
ambari-server/src/main/resources/common-services/YARN/2.1.0.2.0/configuration/yarn-site.xml

@@ -80,7 +80,7 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>yarn-site.xml</type>
+        <type>yarn-site</type>
         <name>yarn.nodemanager.resource.memory-mb</name>
       </property>
     </depends-on>
@@ -104,7 +104,7 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>yarn-site.xml</type>
+        <type>yarn-site</type>
         <name>yarn.nodemanager.resource.memory-mb</name>
       </property>
     </depends-on>

+ 1 - 0
ambari-server/src/main/resources/properties.json

@@ -376,6 +376,7 @@
         "recommend",
         "hosts",
         "services",
+        "changed_configurations",
         "recommendations",
         "recommendations/blueprint",
         "recommendations/blueprint/configurations",

+ 49 - 1
ambari-server/src/main/resources/scripts/stack_advisor.py

@@ -26,9 +26,14 @@ import traceback
 RECOMMEND_COMPONENT_LAYOUT_ACTION = 'recommend-component-layout'
 VALIDATE_COMPONENT_LAYOUT_ACTION = 'validate-component-layout'
 RECOMMEND_CONFIGURATIONS = 'recommend-configurations'
+RECOMMEND_CONFIGURATION_DEPENDENCIES = 'recommend-configuration-dependencies'
 VALIDATE_CONFIGURATIONS = 'validate-configurations'
 
-ALL_ACTIONS = [ RECOMMEND_COMPONENT_LAYOUT_ACTION, VALIDATE_COMPONENT_LAYOUT_ACTION, RECOMMEND_CONFIGURATIONS, VALIDATE_CONFIGURATIONS ]
+ALL_ACTIONS = [RECOMMEND_COMPONENT_LAYOUT_ACTION,
+               VALIDATE_COMPONENT_LAYOUT_ACTION,
+               RECOMMEND_CONFIGURATIONS,
+               RECOMMEND_CONFIGURATION_DEPENDENCIES,
+               VALIDATE_CONFIGURATIONS]
 USAGE = "Usage: <action> <hosts_file> <services_file>\nPossible actions are: {0}\n".format( str(ALL_ACTIONS) )
 
 SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
@@ -101,6 +106,10 @@ def main(argv=None):
   elif action == RECOMMEND_CONFIGURATIONS:
     result = stackAdvisor.recommendConfigurations(services, hosts)
     result_file = os.path.join(actionDir, "configurations.json")
+  elif action == RECOMMEND_CONFIGURATION_DEPENDENCIES:
+    result = stackAdvisor.recommendConfigurations(services, hosts)
+    result_file = os.path.join(actionDir, "configurations.json")
+    result = filterResult(result, services)
   else: # action == VALIDATE_CONFIGURATIONS
     result = stackAdvisor.validateConfigurations(services, hosts)
     result_file = os.path.join(actionDir, "configurations-validation.json")
@@ -108,6 +117,45 @@ def main(argv=None):
   dumpJson(result, result_file)
   pass
 
+# returns recommendations only for changed and depended properties
+def filterResult(result, services):
+  allRequestedProperties = getAllRequestedProperties(services)
+
+  configs = result['recommendations']['blueprint']['configurations']
+  filteredConfigs = {}
+  for type, names in configs.items():
+    for name in names['properties']:
+      if type in allRequestedProperties.keys() and \
+              name in allRequestedProperties[type]:
+        if type not in filteredConfigs.keys():
+          filteredConfigs[type] = {'properties': {}}
+        filteredConfigs[type]['properties'][name] = \
+          configs[type]['properties'][name]
+    if 'property_attributes' in names.keys():
+      for name in names['property_attributes']:
+        if type in allRequestedProperties.keys() and \
+                name in allRequestedProperties[type]:
+          if type not in filteredConfigs.keys():
+            filteredConfigs[type] = {'property_Attributes': {}}
+          elif 'property_attributes' not in filteredConfigs[type].keys():
+            filteredConfigs[type]['property_attributes'] = {}
+          filteredConfigs[type]['property_attributes'][name] = \
+            configs[type]['property_attributes'][name]
+
+  result['recommendations']['blueprint']['configurations'] = filteredConfigs
+  return result
+
+def getAllRequestedProperties(services):
+  changedConfigs = []
+  changedConfigs.extend(services['changed-configurations'])
+  changedConfigs.extend(services['depended-configurations'])
+  allRequestedProperties = {}
+  for config in changedConfigs:
+    if config['type'] in allRequestedProperties:
+      allRequestedProperties[config['type']].append(config['name'])
+    else:
+      allRequestedProperties[config['type']] = [config['name']]
+  return allRequestedProperties
 
 def instantiateStackAdvisor(stackName, stackVersion, parentVersions):
   """Instantiates StackAdvisor implementation for the specified Stack"""

+ 1 - 1
ambari-server/src/main/resources/stacks/BIGTOP/0.8/services/stack_advisor.py

@@ -105,7 +105,7 @@ class BaseBIGTOP08StackAdvisor(DefaultStackAdvisor):
     putMapredProperty('mapreduce.reduce.java.opts', "-Xmx" + str(int(round(0.8 * clusterData['reduceMemory']))) + "m")
     putMapredProperty('mapreduce.task.io.sort.mb', min(int(round(0.4 * clusterData['mapMemory'])), 1024))
 
-  def getConfigurationClusterSummary(self, servicesList, hosts, components):
+  def getConfigurationClusterSummary(self, servicesList, hosts, components, services):
 
     hBaseInstalled = False
     if 'HBASE' in servicesList:

+ 49 - 9
ambari-server/src/main/resources/stacks/HDP/2.0.6/services/stack_advisor.py

@@ -88,23 +88,48 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
       "AMBARI_METRICS": self.recommendAmsConfigurations
     }
 
-  def putProperty(self, config, configType):
-    if configType not in config or "properties" not in config[configType]:
-      config[configType] = {"properties": {}}
+  def putProperty(self, config, configType, services=None):
+    userConfigs = {}
+    changedConfigs = []
+    # if services parameter, prefer values, set by user
+    if services:
+      if 'configurations' in services.keys():
+        userConfigs = services['configurations']
+      if 'changed-configurations' in services.keys():
+        changedConfigs = services["changed-configurations"]
+
+    if configType not in config:
+      config[configType] = {}
+    if"properties" not in config[configType]:
+      config[configType]["properties"] = {}
     def appendProperty(key, value):
-      config[configType]["properties"][key] = str(value)
+      if {'type': configType, 'name': key} in changedConfigs:
+        config[configType]["properties"][key] = userConfigs[configType]['properties'][key]
+      else:
+        config[configType]["properties"][key] = str(value)
     return appendProperty
 
+  def putPropertyAttribute(self, config, configType):
+    if configType not in config:
+      config[configType] = {}
+    def appendPropertyAttribute(key, attribute, attributeValue):
+      if"property_attributes" not in config[configType]:
+        config[configType]["property_attributes"] = {}
+      if key not in config[configType]["property_attributes"]:
+        config[configType]["property_attributes"][key] = {}
+      config[configType]["property_attributes"][key][attribute] = str(attributeValue)
+    return appendPropertyAttribute
+
   def recommendYARNConfigurations(self, configurations, clusterData, services, hosts):
-    putYarnProperty = self.putProperty(configurations, "yarn-site")
-    putYarnEnvProperty = self.putProperty(configurations, "yarn-env")
+    putYarnProperty = self.putProperty(configurations, "yarn-site", services)
+    putYarnEnvProperty = self.putProperty(configurations, "yarn-env", services)
     putYarnProperty('yarn.nodemanager.resource.memory-mb', int(round(clusterData['containers'] * clusterData['ramPerContainer'])))
     putYarnProperty('yarn.scheduler.minimum-allocation-mb', int(clusterData['ramPerContainer']))
     putYarnProperty('yarn.scheduler.maximum-allocation-mb', int(round(clusterData['containers'] * clusterData['ramPerContainer'])))
     putYarnEnvProperty('min_user_id', self.get_system_min_uid())
 
   def recommendMapReduce2Configurations(self, configurations, clusterData, services, hosts):
-    putMapredProperty = self.putProperty(configurations, "mapred-site")
+    putMapredProperty = self.putProperty(configurations, "mapred-site", services)
     putMapredProperty('yarn.app.mapreduce.am.resource.mb', int(clusterData['amMemory']))
     putMapredProperty('yarn.app.mapreduce.am.command-opts', "-Xmx" + str(int(round(0.8 * clusterData['amMemory']))) + "m")
     putMapredProperty('mapreduce.map.memory.mb', clusterData['mapMemory'])
@@ -184,7 +209,18 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
 
 
 
-  def getConfigurationClusterSummary(self, servicesList, hosts, components):
+  def getHostWithComponent(self, serviceName, componentName, services, hosts):
+    if services is not None and hosts is not None:
+      service = [serviceEntry for serviceEntry in services["services"] if serviceEntry["StackServices"]["service_name"] == serviceName][0]
+      components = [componentEntry for componentEntry in service["components"] if componentEntry["StackServiceComponents"]["component_name"] == "NODEMANAGER"]
+      if (len(components) > 0 and len(components[0]["StackServiceComponents"]["hostnames"]) > 0):
+        # NodeManager available - determine hosts and memory
+        componentHostname = components[0]["StackServiceComponents"]["hostnames"][0]
+        componentHosts = [host for host in hosts["items"] if host["Hosts"]["host_name"] == componentHostname]
+        if (componentHosts is not None and len(componentHosts) > 0):
+          return componentHosts[0]
+
+  def getConfigurationClusterSummary(self, servicesList, hosts, components, services):
 
     hBaseInstalled = False
     if 'HBASE' in servicesList:
@@ -199,7 +235,11 @@ class HDP206StackAdvisor(DefaultStackAdvisor):
     }
 
     if len(hosts["items"]) > 0:
-      host = hosts["items"][0]["Hosts"]
+      nodeManagerHost = self.getHostWithComponent("YARN", "NODEMANAGER", services, hosts)
+      if nodeManagerHost is not None:
+        host = nodeManagerHost["Hosts"]
+      else:
+        host = hosts["items"][0]["Hosts"]
       cluster["cpu"] = host["cpu_count"]
       cluster["disk"] = len(host["disk_info"])
       cluster["ram"] = int(host["total_mem"] / (1024 * 1024))

+ 2 - 2
ambari-server/src/main/resources/stacks/HDP/2.2/services/YARN/configuration/yarn-site.xml

@@ -349,7 +349,7 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>yarn-site.xml</type>
+        <type>yarn-site</type>
         <name>yarn.nodemanager.resource.cpu-vcores</name>
       </property>
     </depends-on>
@@ -367,7 +367,7 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>yarn-site.xml</type>
+        <type>yarn-site</type>
         <name>yarn.nodemanager.resource.cpu-vcores</name>
       </property>
     </depends-on>

+ 25 - 3
ambari-server/src/main/resources/stacks/HDP/2.2/services/stack_advisor.py

@@ -38,8 +38,19 @@ class HDP22StackAdvisor(HDP21StackAdvisor):
 
   def recommendYARNConfigurations(self, configurations, clusterData, services, hosts):
     super(HDP22StackAdvisor, self).recommendYARNConfigurations(configurations, clusterData, services, hosts)
-    putYarnProperty = self.putProperty(configurations, "yarn-site")
+    putYarnProperty = self.putProperty(configurations, "yarn-site", services)
     putYarnProperty('yarn.nodemanager.resource.cpu-vcores', clusterData['cpu'])
+    # Property Attributes
+    putYarnPropertyAttribute = self.putPropertyAttribute(configurations, "yarn-site")
+    nodeManagerHost = self.getHostWithComponent("YARN", "NODEMANAGER", services, hosts)
+    if (nodeManagerHost is not None):
+      putYarnProperty('yarn.nodemanager.resource.cpu-vcores', nodeManagerHost["Hosts"]["cpu_count"] * 2)
+      putYarnPropertyAttribute('yarn.nodemanager.resource.memory-mb', 'max', int(nodeManagerHost["Hosts"]["total_mem"] / 1024)) # total_mem in kb
+      putYarnPropertyAttribute('yarn.nodemanager.resource.cpu-vcores', 'max', nodeManagerHost["Hosts"]["cpu_count"] * 4)
+      putYarnPropertyAttribute('yarn.scheduler.minimum-allocation-vcores', 'max', configurations["yarn-site"]["properties"]["yarn.nodemanager.resource.cpu-vcores"])
+      putYarnPropertyAttribute('yarn.scheduler.maximum-allocation-vcores', 'max', configurations["yarn-site"]["properties"]["yarn.nodemanager.resource.cpu-vcores"])
+      putYarnPropertyAttribute('yarn.scheduler.minimum-allocation-mb', 'max', configurations["yarn-site"]["properties"]["yarn.nodemanager.resource.memory-mb"])
+      putYarnPropertyAttribute('yarn.scheduler.maximum-allocation-mb', 'max', configurations["yarn-site"]["properties"]["yarn.nodemanager.resource.memory-mb"])
 
   def recommendHDFSConfigurations(self, configurations, clusterData, services, hosts):
     putHdfsProperty = self.putProperty(configurations, "hdfs-site")
@@ -156,14 +167,25 @@ class HDP22StackAdvisor(HDP21StackAdvisor):
     return self.toConfigurationValidationProblems(validationItems, "tez-site")
 
   def recommendMapReduce2Configurations(self, configurations, clusterData, services, hosts):
-    putMapredProperty = self.putProperty(configurations, "mapred-site")
+    self.recommendYARNConfigurations(configurations, clusterData, services, hosts)
+    putMapredProperty = self.putProperty(configurations, "mapred-site", services)
     putMapredProperty('yarn.app.mapreduce.am.resource.mb', int(clusterData['amMemory']))
     putMapredProperty('yarn.app.mapreduce.am.command-opts', "-Xmx" + str(int(round(0.8 * clusterData['amMemory']))) + "m" + " -Dhdp.version=${hdp.version}")
-    putMapredProperty('mapreduce.map.memory.mb', clusterData['mapMemory'])
+    putMapredProperty('mapreduce.map.memory.mb', configurations["yarn-site"]["properties"]["yarn.scheduler.minimum-allocation-mb"])
     putMapredProperty('mapreduce.reduce.memory.mb', int(clusterData['reduceMemory']))
     putMapredProperty('mapreduce.map.java.opts', "-Xmx" + str(int(round(0.8 * clusterData['mapMemory']))) + "m")
     putMapredProperty('mapreduce.reduce.java.opts', "-Xmx" + str(int(round(0.8 * clusterData['reduceMemory']))) + "m")
     putMapredProperty('mapreduce.task.io.sort.mb', min(int(round(0.4 * clusterData['mapMemory'])), 1024))
+    # Property Attributes
+    putMapredPropertyAttribute = self.putPropertyAttribute(configurations, "mapred-site")
+    yarnMinAllocationSize = int(clusterData['ramPerContainer'])
+    yarnMaxAllocationSize = max(30 * int(clusterData['ramPerContainer']), configurations["yarn-site"]["properties"]["yarn.scheduler.maximum-allocation-mb"])
+    putMapredPropertyAttribute("mapreduce.map.memory.mb", "max", yarnMaxAllocationSize)
+    putMapredPropertyAttribute("mapreduce.map.memory.mb", "min", yarnMinAllocationSize)
+    putMapredPropertyAttribute("mapreduce.reduce.memory.mb", "max", yarnMaxAllocationSize)
+    putMapredPropertyAttribute("mapreduce.reduce.memory.mb", "min", yarnMinAllocationSize)
+    putMapredPropertyAttribute("yarn.app.mapreduce.am.resource.mb", "max", yarnMaxAllocationSize)
+    putMapredPropertyAttribute("yarn.app.mapreduce.am.resource.mb", "min", yarnMinAllocationSize)
 
   def validateMapReduce2Configurations(self, properties, recommendedDefaults, configurations, services, hosts):
     validationItems = [ {"config-name": 'mapreduce.map.java.opts', "item": self.validateXmxValue(properties, recommendedDefaults, 'mapreduce.map.java.opts')},

+ 1 - 1
ambari-server/src/main/resources/stacks/HDPWIN/2.1/services/stack_advisor.py

@@ -133,7 +133,7 @@ class HDPWIN21StackAdvisor(DefaultStackAdvisor):
                    "-server -Xmx" + str(int(0.8 * clusterData["amMemory"]))
                    + "m -Djava.net.preferIPv4Stack=true -XX:+UseNUMA -XX:+UseParallelGC")
 
-  def getConfigurationClusterSummary(self, servicesList, hosts, components):
+  def getConfigurationClusterSummary(self, servicesList, hosts, components, services):
 
     hBaseInstalled = False
     if 'HBASE' in servicesList:

+ 1 - 1
ambari-server/src/main/resources/stacks/PHD/3.0.0.0/services/stack_advisor.py

@@ -106,7 +106,7 @@ class BasePHD3000StackAdvisor(DefaultStackAdvisor):
     putMapredProperty('mapreduce.reduce.java.opts', "-Xmx" + str(int(round(0.8 * clusterData['reduceMemory']))) + "m")
     putMapredProperty('mapreduce.task.io.sort.mb', min(int(round(0.4 * clusterData['mapMemory'])), 1024))
 
-  def getConfigurationClusterSummary(self, servicesList, hosts, components):
+  def getConfigurationClusterSummary(self, servicesList, hosts, components, services):
 
     hBaseInstalled = False
     if 'HBASE' in servicesList:

+ 2 - 2
ambari-server/src/main/resources/stacks/stack_advisor.py

@@ -465,7 +465,7 @@ class DefaultStackAdvisor(StackAdvisor):
   def getComponentLayoutValidations(self, services, hosts):
     return []
 
-  def getConfigurationClusterSummary(self, servicesList, hosts, components):
+  def getConfigurationClusterSummary(self, servicesList, hosts, components, services):
     pass
 
   def getConfigurationsValidationItems(self, services, hosts):
@@ -480,7 +480,7 @@ class DefaultStackAdvisor(StackAdvisor):
                   for service in services["services"]
                   for component in service["components"]]
 
-    clusterSummary = self.getConfigurationClusterSummary(servicesList, hosts, components)
+    clusterSummary = self.getConfigurationClusterSummary(servicesList, hosts, components, services)
 
     recommendations = {
       "Versions": {"stack_name": stackName, "stack_version": stackVersion},

+ 17 - 3
ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java

@@ -35,6 +35,7 @@ import java.lang.reflect.Field;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -62,6 +63,7 @@ import org.apache.ambari.server.state.AutoDeployInfo;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.CustomCommandDefinition;
 import org.apache.ambari.server.state.DependencyInfo;
 import org.apache.ambari.server.state.OperatingSystemInfo;
@@ -750,7 +752,7 @@ public class AmbariMetaInfoTest {
     PropertyInfo originalProperty = null;
 
     PropertyDependencyInfo propertyDependencyInfo =
-      new PropertyDependencyInfo("yarn-site.xml", "new-enhanced-yarn-property");
+      new PropertyDependencyInfo("yarn-site", "new-enhanced-yarn-property");
 
     for (PropertyInfo propertyInfo : redefinedService.getProperties()) {
       if (propertyInfo.getName().equals("yarn.resourcemanager.resource-tracker.address")) {
@@ -799,8 +801,8 @@ public class AmbariMetaInfoTest {
     Assert.assertEquals("some enhanced description.", newEnhancedProperty.getDescription());
     Assert.assertEquals("yarn-site.xml", newEnhancedProperty.getFilename());
     Assert.assertEquals(2, newEnhancedProperty.getDependsOnProperties().size());
-    Assert.assertTrue(newEnhancedProperty.getDependsOnProperties().contains(new PropertyDependencyInfo("yarn-site.xml", "new-yarn-property")));
-    Assert.assertTrue(newEnhancedProperty.getDependsOnProperties().contains(new PropertyDependencyInfo("global.xml", "yarn_heapsize")));
+    Assert.assertTrue(newEnhancedProperty.getDependsOnProperties().contains(new PropertyDependencyInfo("yarn-site", "new-yarn-property")));
+    Assert.assertTrue(newEnhancedProperty.getDependsOnProperties().contains(new PropertyDependencyInfo("global", "yarn_heapsize")));
     Assert.assertEquals("MB", newEnhancedProperty.getPropertyValueAttributes().getUnit());
     Assert.assertEquals("int", newEnhancedProperty.getPropertyValueAttributes().getType());
     Assert.assertEquals("512", newEnhancedProperty.getPropertyValueAttributes().getMinimum());
@@ -816,6 +818,18 @@ public class AmbariMetaInfoTest {
       originalProperty.getDescription());
     Assert.assertEquals(6, redefinedService.getConfigDependencies().size());
     Assert.assertEquals(7, redefinedService.getConfigDependenciesWithComponents().size());
+
+    // Test directed-acyclic-graph (DAG) of dependencies between configurations
+    List<PropertyDependencyInfo> changedConfigs = new LinkedList<PropertyDependencyInfo>();
+    String type = ConfigHelper.fileNameToConfigType(newProperty.getFilename());
+    String name = newProperty.getName();
+    changedConfigs.add(new PropertyDependencyInfo(type, name));
+    Set<PropertyDependencyInfo> dependedByProperties = metaInfo.getDependedByProperties(stackInfo.getName(), stackInfo.getVersion(), changedConfigs);
+    Assert.assertEquals(3, dependedByProperties.size());
+    Assert.assertTrue(dependedByProperties.contains(new PropertyDependencyInfo("yarn-site", "new-enhanced-yarn-property2")));
+    Assert.assertTrue(dependedByProperties.contains(new PropertyDependencyInfo("yarn-site", "new-enhanced-yarn-property")));
+    Assert.assertTrue(dependedByProperties.contains(new PropertyDependencyInfo("yarn-site", "new-yarn-property")));
+
   }
 
   @Test

+ 24 - 9
ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/StackAdvisorHelperTest.java

@@ -30,9 +30,10 @@ import java.io.IOException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestBuilder;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest.StackAdvisorRequestType;
-import org.apache.ambari.server.api.services.stackadvisor.commands.GetComponentLayoutRecommnedationCommand;
-import org.apache.ambari.server.api.services.stackadvisor.commands.GetComponentLayoutValidationCommand;
-import org.apache.ambari.server.api.services.stackadvisor.commands.GetConfigurationValidationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ComponentLayoutRecommendationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ComponentLayoutValidationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ConfigurationDependenciesRecommendationCommand;
+import org.apache.ambari.server.api.services.stackadvisor.commands.ConfigurationValidationCommand;
 import org.apache.ambari.server.api.services.stackadvisor.commands.StackAdvisorCommand;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
 import org.apache.ambari.server.api.services.stackadvisor.validations.ValidationResponse;
@@ -129,7 +130,7 @@ public class StackAdvisorHelperTest {
   }
 
   @Test
-  public void testCreateRecommendationCommand_returnsGetComponentLayoutRecommnedationCommand()
+  public void testCreateRecommendationCommand_returnsComponentLayoutRecommendationCommand()
       throws IOException, StackAdvisorException {
     Configuration configuration = mock(Configuration.class);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
@@ -140,11 +141,11 @@ public class StackAdvisorHelperTest {
     StackAdvisorCommand<RecommendationResponse> command = helper
         .createRecommendationCommand(requestType);
 
-    assertEquals(GetComponentLayoutRecommnedationCommand.class, command.getClass());
+    assertEquals(ComponentLayoutRecommendationCommand.class, command.getClass());
   }
 
   @Test
-  public void testCreateValidationCommand_returnsGetComponentLayoutValidationCommand()
+  public void testCreateValidationCommand_returnsComponentLayoutValidationCommand()
       throws IOException, StackAdvisorException {
     Configuration configuration = mock(Configuration.class);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
@@ -154,11 +155,11 @@ public class StackAdvisorHelperTest {
 
     StackAdvisorCommand<ValidationResponse> command = helper.createValidationCommand(requestType);
 
-    assertEquals(GetComponentLayoutValidationCommand.class, command.getClass());
+    assertEquals(ComponentLayoutValidationCommand.class, command.getClass());
   }
 
   @Test
-  public void testCreateValidationCommand_returnsGetConfigurationValidationCommand()
+  public void testCreateValidationCommand_returnsConfigurationValidationCommand()
       throws IOException, StackAdvisorException {
     Configuration configuration = mock(Configuration.class);
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
@@ -168,7 +169,21 @@ public class StackAdvisorHelperTest {
 
     StackAdvisorCommand<ValidationResponse> command = helper.createValidationCommand(requestType);
 
-    assertEquals(GetConfigurationValidationCommand.class, command.getClass());
+    assertEquals(ConfigurationValidationCommand.class, command.getClass());
+  }
+
+  @Test
+  public void testCreateRecommendationDependencyCommand_returnsConfigurationDependencyRecommendationCommand()
+    throws IOException, StackAdvisorException {
+    Configuration configuration = mock(Configuration.class);
+    StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
+    AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
+    StackAdvisorHelper helper = new StackAdvisorHelper(configuration, saRunner, metaInfo);
+    StackAdvisorRequestType requestType = StackAdvisorRequestType.CONFIGURATION_DEPENDENCIES;
+
+    StackAdvisorCommand<RecommendationResponse> command = helper.createRecommendationCommand(requestType);
+
+    assertEquals(ConfigurationDependenciesRecommendationCommand.class, command.getClass());
   }
 
 }

+ 2 - 2
ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/GetConfigurationRecommnedationCommandTest.java → ambari-server/src/test/java/org/apache/ambari/server/api/services/stackadvisor/commands/ConfigurationRecommendationCommandTest.java

@@ -36,14 +36,14 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRunner;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
 import org.junit.Test;
 
-public class GetConfigurationRecommnedationCommandTest {
+public class ConfigurationRecommendationCommandTest {
 
   @Test
   public void testProcessHostGroups() throws Exception {
     StackAdvisorRunner saRunner = mock(StackAdvisorRunner.class);
     File file = mock(File.class);
     AmbariMetaInfo metaInfo = mock(AmbariMetaInfo.class);
-    GetConfigurationRecommnedationCommand command = new GetConfigurationRecommnedationCommand(file, "script", 1, saRunner, metaInfo);
+    ConfigurationRecommendationCommand command = new ConfigurationRecommendationCommand(file, "script", 1, saRunner, metaInfo);
 
     StackAdvisorRequest request = mock(StackAdvisorRequest.class);
     Map<String, Set<String>> componentHostGroupMap = new HashMap<String, Set<String>>();

+ 4 - 4
ambari-server/src/test/python/stacks/2.0.6/common/test_stack_advisor.py

@@ -302,7 +302,7 @@ class TestHDP206StackAdvisor(TestCase):
       "amMemory": 512
     }
 
-    result = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components)
+    result = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components, None)
 
     self.assertEquals(result, expected)
 
@@ -344,7 +344,7 @@ class TestHDP206StackAdvisor(TestCase):
       "amMemory": 3072
     }
 
-    result = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components)
+    result = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components, None)
 
     self.assertEquals(result, expected)
 
@@ -402,7 +402,7 @@ class TestHDP206StackAdvisor(TestCase):
     hosts = {
       "items" : []
     }
-    result = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components)
+    result = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components, None)
 
     expected = {
       "hBaseInstalled": False,
@@ -530,7 +530,7 @@ class TestHDP206StackAdvisor(TestCase):
       }
     }
 
-    clusterData = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components)
+    clusterData = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components, None)
     self.assertEquals(clusterData['hbaseRam'], 8)
 
     self.stackAdvisor.recommendHbaseEnvConfigurations(configurations, clusterData, None, None)

+ 1 - 1
ambari-server/src/test/python/stacks/2.1/common/test_stack_advisor.py

@@ -191,7 +191,7 @@ class TestHDP21StackAdvisor(TestCase):
       }
     }
 
-    clusterData = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components)
+    clusterData = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components, None)
     self.assertEquals(clusterData['hbaseRam'], 8)
 
     self.stackAdvisor.recommendHbaseEnvConfigurations(configurations, clusterData, None, None)

+ 221 - 1
ambari-server/src/test/python/stacks/2.2/common/test_stack_advisor.py

@@ -644,6 +644,226 @@ class TestHDP22StackAdvisor(TestCase):
     self.stackAdvisor.recommendYARNConfigurations(configurations, clusterData, None, None)
     self.assertEquals(configurations, expected)
 
+  def test_recommendYARNConfigurationAttributes(self):
+    configurations = {
+      "yarn-env": {
+        "properties": {
+          "min_user_id": "500"
+        }
+      },
+      "yarn-site": {
+        "properties": {
+          "yarn.nodemanager.resource.memory-mb": "1280",
+          "yarn.scheduler.minimum-allocation-mb": "256",
+          "yarn.scheduler.maximum-allocation-mb": "1280",
+          "yarn.nodemanager.resource.cpu-vcores": "2"
+        },
+      }
+    }
+    clusterData = {
+      "cpu": 4,
+      "containers" : 5,
+      "ramPerContainer": 256
+    }
+    expected = {
+      "yarn-env": {
+        "properties": {
+          "min_user_id": "500"
+        }
+      },
+      "yarn-site": {
+        "properties": {
+          "yarn.nodemanager.resource.memory-mb": "1280",
+          "yarn.scheduler.minimum-allocation-mb": "256",
+          "yarn.scheduler.maximum-allocation-mb": "1280",
+          "yarn.nodemanager.resource.cpu-vcores": "2"
+        },
+        "property_attributes": {
+          'yarn.nodemanager.resource.memory-mb': {'max': '1877'},
+          'yarn.nodemanager.resource.cpu-vcores': {'max': '4'},
+          'yarn.scheduler.minimum-allocation-vcores': {'max': '2'},
+          'yarn.scheduler.maximum-allocation-vcores': {'max': '2'},
+          'yarn.scheduler.minimum-allocation-mb': {'max': '1280'},
+          'yarn.scheduler.maximum-allocation-mb': {'max': '1280'}
+        }
+      }
+    }
+    services = {
+      "services": [
+        {
+          "href": "/api/v1/stacks/HDP/versions/2.2/services/YARN",
+          "StackServices": {
+            "service_name": "YARN",
+            "service_version": "2.6.0.2.2",
+            "stack_name": "HDP",
+            "stack_version": "2.2"
+          },
+          "components": [
+            {
+              "StackServiceComponents": {
+                "advertise_version": "false",
+                "cardinality": "1",
+                "component_category": "MASTER",
+                "component_name": "APP_TIMELINE_SERVER",
+                "display_name": "App Timeline Server",
+                "is_client": "false",
+                "is_master": "true",
+                "hostnames": []
+              },
+              "dependencies": []
+            },
+            {
+              "StackServiceComponents": {
+                "advertise_version": "true",
+                "cardinality": "1+",
+                "component_category": "SLAVE",
+                "component_name": "NODEMANAGER",
+                "display_name": "NodeManager",
+                "is_client": "false",
+                "is_master": "false",
+                "hostnames": [
+                  "c6403.ambari.apache.org"
+                ]
+              },
+              "dependencies": []
+            },
+            {
+              "StackServiceComponents": {
+                "advertise_version": "true",
+                "cardinality": "1-2",
+                "component_category": "MASTER",
+                "component_name": "RESOURCEMANAGER",
+                "display_name": "ResourceManager",
+                "is_client": "false",
+                "is_master": "true",
+                "hostnames": []
+              },
+              "dependencies": []
+            },
+            {
+              "StackServiceComponents": {
+                "advertise_version": "true",
+                "cardinality": "1+",
+                "component_category": "CLIENT",
+                "component_name": "YARN_CLIENT",
+                "display_name": "YARN Client",
+                "is_client": "true",
+                "is_master": "false",
+                "hostnames": []
+              },
+              "dependencies": []
+            }
+          ]
+        },
+      ],
+      "configurations": configurations,
+      "changed-configurations": [
+        {
+          "type": "yarn-site",
+          "name": "yarn.nodemanager.resource.memory-mb"
+        },
+        {
+          "type": "yarn-site",
+          "name": "yarn.scheduler.minimum-allocation-mb"
+        },
+        {
+          "type": "yarn-site",
+          "name": "yarn.scheduler.maximum-allocation-mb"
+        },
+        {
+          "type": "yarn-site",
+          "name": "yarn.nodemanager.resource.cpu-vcores"
+        },
+        {
+          "type": "yarn-env",
+          "name": "min_user_id"
+        },
+      ],
+      "depended-configurations": [
+        {
+          "type" : "mapred-site",
+          "name" : "yarn.app.mapreduce.am.admin-command-opts"
+        }, {
+          "type" : "yarn-site",
+          "name" : "yarn.scheduler.maximum-allocation-mb"
+        }, {
+          "type" : "yarn-site",
+          "name" : "yarn.scheduler.minimum-allocation-mb"
+        }, {
+          "type" : "mapred-site",
+          "name" : "mapreduce.reduce.java.opts"
+        }, {
+          "type" : "mapred-site",
+          "name" : "mapreduce.map.java.opts"
+        }, {
+          "type" : "mapred-site",
+          "name" : "yarn.app.mapreduce.am.command-opts"
+        }, {
+          "type" : "mapred-site",
+          "name" : "yarn.app.mapreduce.am.resource.mb"
+        }, {
+          "type" : "yarn-site",
+          "name" : "yarn.nodemanager.resource.memory-mb"
+        }, {
+          "type" : "mapred-site",
+          "name" : "mapreduce.task.io.sort.mb"
+        }, {
+          "type" : "mapred-site",
+          "name" : "mapreduce.reduce.memory.mb"
+        }, {
+          "type" : "mapred-site",
+          "name" : "mapreduce.map.memory.mb"
+        }
+      ]
+
+      }
+    hosts = {
+      "items" : [
+        {
+          "href" : "/api/v1/hosts/c6401.ambari.apache.org",
+          "Hosts" : {
+            "cpu_count" : 1,
+            "host_name" : "c6401.ambari.apache.org",
+            "os_arch" : "x86_64",
+            "os_type" : "centos6",
+            "ph_cpu_count" : 1,
+            "public_host_name" : "c6401.ambari.apache.org",
+            "rack_info" : "/default-rack",
+            "total_mem" : 1922680
+          }
+        },
+        {
+          "href" : "/api/v1/hosts/c6402.ambari.apache.org",
+          "Hosts" : {
+            "cpu_count" : 1,
+            "host_name" : "c6402.ambari.apache.org",
+            "os_arch" : "x86_64",
+            "os_type" : "centos6",
+            "ph_cpu_count" : 1,
+            "public_host_name" : "c6402.ambari.apache.org",
+            "rack_info" : "/default-rack",
+            "total_mem" : 1922680
+          }
+        },
+        {
+          "href" : "/api/v1/hosts/c6403.ambari.apache.org",
+          "Hosts" : {
+            "cpu_count" : 1,
+            "host_name" : "c6403.ambari.apache.org",
+            "os_arch" : "x86_64",
+            "os_type" : "centos6",
+            "ph_cpu_count" : 1,
+            "public_host_name" : "c6403.ambari.apache.org",
+            "rack_info" : "/default-rack",
+            "total_mem" : 1922680
+          }
+        }
+      ]
+    }
+
+    self.stackAdvisor.recommendYARNConfigurations(configurations, clusterData, services, hosts)
+    self.assertEquals(configurations, expected)
+
   def test_recommendAmsConfigurations(self):
     configurations = {}
     clusterData = {}
@@ -730,7 +950,7 @@ class TestHDP22StackAdvisor(TestCase):
       }
     }
 
-    clusterData = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components)
+    clusterData = self.stackAdvisor.getConfigurationClusterSummary(servicesList, hosts, components, None)
     self.assertEquals(clusterData['hbaseRam'], 8)
 
     self.stackAdvisor.recommendHbaseEnvConfigurations(configurations, clusterData, None, None)

+ 15 - 2
ambari-server/src/test/resources/stacks/HDP/2.0.6/services/YARN/configuration/yarn-site.xml

@@ -69,15 +69,28 @@
     </value-attributes>
     <depends-on>
       <property>
-        <type>yarn-site.xml</type>
+        <type>yarn-site</type>
         <name>new-yarn-property</name>
       </property>
       <property>
-        <type>global.xml</type>
+        <type>global</type>
         <name>yarn_heapsize</name>
       </property>
     </depends-on>
   </property>
 
+  <property>
+    <name>new-enhanced-yarn-property2</name>
+    <value>1024</value>
+    <description>some enhanced description.</description>
+
+    <depends-on>
+      <property>
+        <type>yarn-site</type>
+        <name>new-enhanced-yarn-property</name>
+      </property>
+    </depends-on>
+  </property>
+
 
 </configuration>