ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jspei...@apache.org
Subject [4/4] ambari git commit: AMBARI-10990. Implement topology manager persistence
Date Thu, 07 May 2015 05:19:48 GMT
AMBARI-10990.  Implement topology manager persistence


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

Branch: refs/heads/trunk
Commit: 807b3c2df7a9a9fe1d728e75cf80c130848d4756
Parents: 8963501
Author: John Speidel <jspeidel@hortonworks.com>
Authored: Thu May 7 01:17:10 2015 -0400
Committer: John Speidel <jspeidel@hortonworks.com>
Committed: Thu May 7 01:17:10 2015 -0400

----------------------------------------------------------------------
 .../query/render/ClusterBlueprintRenderer.java  |   4 +-
 .../ambari/server/controller/AmbariServer.java  |   4 +-
 .../server/controller/ControllerModule.java     |   2 -
 .../internal/ExportBlueprintRequest.java        |  10 +
 .../internal/HostComponentResourceProvider.java |  34 +-
 .../internal/HostResourceProvider.java          |   4 +-
 .../internal/ProvisionClusterRequest.java       |  14 +-
 .../internal/ScaleClusterRequest.java           |  94 ++-
 .../server/controller/internal/Stack.java       |  30 +-
 .../server/orm/dao/TopologyHostGroupDAO.java    |  12 +
 .../server/orm/dao/TopologyHostTaskDAO.java     |  73 ++
 .../server/orm/dao/TopologyLogicalTaskDAO.java  |  63 ++
 .../server/orm/entities/BlueprintEntity.java    |   3 -
 .../orm/entities/TopologyHostGroupEntity.java   |  28 +-
 .../orm/entities/TopologyHostInfoEntity.java    |   6 +-
 .../orm/entities/TopologyHostRequestEntity.java |  11 +-
 .../orm/entities/TopologyHostTaskEntity.java    |   6 +
 .../entities/TopologyLogicalRequestEntity.java  |   4 -
 .../ambari/server/topology/AmbariContext.java   | 499 +++++++++++++
 .../ambari/server/topology/BlueprintImpl.java   |   3 +-
 .../topology/ClusterConfigurationRequest.java   |  30 +-
 .../ambari/server/topology/ClusterTopology.java |  30 +
 .../server/topology/ClusterTopologyImpl.java    |  33 +-
 .../ambari/server/topology/HostGroupInfo.java   |  15 +-
 .../server/topology/HostOfferResponse.java      |   9 +-
 .../ambari/server/topology/HostRequest.java     | 699 +++++++------------
 .../ambari/server/topology/LogicalRequest.java  | 153 ++--
 .../server/topology/LogicalRequestFactory.java  |  40 ++
 .../ambari/server/topology/PersistedState.java  |  69 ++
 .../server/topology/PersistedStateImpl.java     | 408 +++++++++++
 .../topology/PersistedTopologyRequest.java      |  41 ++
 .../ambari/server/topology/TopologyManager.java | 379 ++++------
 .../ambari/server/topology/TopologyRequest.java |   4 +
 .../ambari/server/topology/TopologyTask.java    |   5 +
 .../server/upgrade/UpgradeCatalog210.java       |  15 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  17 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  17 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  22 +-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  20 +-
 .../BlueprintConfigurationProcessorTest.java    | 142 ++--
 .../internal/StageResourceProviderTest.java     |   3 +
 .../orm/dao/TopologyLogicalRequestDAOTest.java  |   8 +-
 .../server/orm/dao/TopologyRequestDAOTest.java  |   3 +-
 .../topology/BlueprintValidatorImplTest.java    | 181 +++++
 .../topology/ClusterTopologyImplTest.java       |  41 +-
 .../server/topology/TopologyManagerTest.java    | 298 ++++++++
 46 files changed, 2595 insertions(+), 991 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java
index 351f6b4..cfc9bc0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRenderer.java
@@ -33,6 +33,7 @@ import org.apache.ambari.server.controller.internal.ExportBlueprintRequest;
 import org.apache.ambari.server.controller.internal.ResourceImpl;
 import org.apache.ambari.server.controller.internal.Stack;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.topology.AmbariContext;
 import org.apache.ambari.server.topology.ClusterTopology;
 import org.apache.ambari.server.topology.ClusterTopologyImpl;
 import org.apache.ambari.server.topology.Configuration;
@@ -40,7 +41,6 @@ import org.apache.ambari.server.topology.HostGroup;
 import org.apache.ambari.server.topology.HostGroupInfo;
 import org.apache.ambari.server.topology.InvalidTopologyException;
 import org.apache.ambari.server.topology.InvalidTopologyTemplateException;
-import org.apache.ambari.server.topology.NoSuchHostGroupException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -253,7 +253,7 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer {
   protected ClusterTopology createClusterTopology(TreeNode<Resource> clusterNode)
       throws InvalidTopologyTemplateException, InvalidTopologyException {
 
-    return new ClusterTopologyImpl(new ExportBlueprintRequest(clusterNode));
+    return new ClusterTopologyImpl(new AmbariContext(), new ExportBlueprintRequest(clusterNode));
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 84e1623..77f6d2c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -90,8 +90,8 @@ import org.apache.ambari.server.security.unsecured.rest.CertificateDownload;
 import org.apache.ambari.server.security.unsecured.rest.CertificateSign;
 import org.apache.ambari.server.security.unsecured.rest.ConnectionInfo;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.topology.AmbariContext;
 import org.apache.ambari.server.topology.BlueprintFactory;
-import org.apache.ambari.server.topology.HostRequest;
 import org.apache.ambari.server.topology.TopologyManager;
 import org.apache.ambari.server.topology.TopologyRequestFactoryImpl;
 import org.apache.ambari.server.utils.StageUtils;
@@ -618,7 +618,7 @@ public class AmbariServer {
     BlueprintFactory.init(injector.getInstance(BlueprintDAO.class));
     ProvisionClusterRequest.init(injector.getInstance(BlueprintFactory.class));
     ScaleClusterRequest.init(injector.getInstance(BlueprintFactory.class));
-    HostRequest.init(injector.getInstance(HostRoleCommandFactory.class));
+    AmbariContext.init(injector.getInstance(HostRoleCommandFactory.class));
 
     PermissionResourceProvider.init(injector.getInstance(PermissionDAO.class));
     ViewPermissionResourceProvider.init(injector.getInstance(PermissionDAO.class));

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 3994a7b..08a56d0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -111,7 +111,6 @@ import org.apache.ambari.server.state.scheduler.RequestExecutionImpl;
 import org.apache.ambari.server.state.stack.OsFamily;
 import org.apache.ambari.server.state.svccomphost.ServiceComponentHostImpl;
 import org.apache.ambari.server.topology.BlueprintFactory;
-import org.apache.ambari.server.topology.TopologyManager;
 import org.apache.ambari.server.view.ViewInstanceHandlerList;
 import org.eclipse.jetty.server.SessionIdManager;
 import org.eclipse.jetty.server.SessionManager;
@@ -324,7 +323,6 @@ public class ControllerModule extends AbstractModule {
     bind(ExecutionScheduler.class).to(ExecutionSchedulerImpl.class);
     bind(DBAccessor.class).to(DBAccessorImpl.class);
     bind(ViewInstanceHandlerList.class).to(AmbariHandlerList.class);
-    bind(TopologyManager.class);
 
     requestStaticInjection(ExecutionCommandWrapper.class);
     requestStaticInjection(DatabaseChecker.class);

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java
index e4acea2..9318db9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ExportBlueprintRequest.java
@@ -86,6 +86,11 @@ public class ExportBlueprintRequest implements TopologyRequest {
   }
 
   @Override
+  public Type getType() {
+    return Type.EXPORT;
+  }
+
+  @Override
   public Blueprint getBlueprint() {
     return blueprint;
   }
@@ -105,6 +110,11 @@ public class ExportBlueprintRequest implements TopologyRequest {
     return Collections.emptyList();
   }
 
+  @Override
+  public String getCommandDescription() {
+    return String.format("Export Command For Cluster '%s'", clusterName);
+  }
+
   // ----- private instance methods ------------------------------------------
 
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
index 30627eb..818147b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
@@ -355,13 +355,13 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
 
     installProperties.put(HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID, "INSTALLED");
     Map<String, String> requestInfo = new HashMap<String, String>();
-    requestInfo.put("context", "Install components on added hosts");
+    requestInfo.put("context", String.format("Install components on host %s", hostname));
     Request installRequest = PropertyHelper.getUpdateRequest(installProperties, requestInfo);
 
     Predicate statePredicate = new EqualsPredicate<String>(HOST_COMPONENT_STATE_PROPERTY_ID, "INIT");
     Predicate clusterPredicate = new EqualsPredicate<String>(HOST_COMPONENT_CLUSTER_NAME_PROPERTY_ID, cluster);
     // single host
-    Predicate hostPredicate = new EqualsPredicate(HOST_COMPONENT_HOST_NAME_PROPERTY_ID, hostname);
+    Predicate hostPredicate = new EqualsPredicate<String>(HOST_COMPONENT_HOST_NAME_PROPERTY_ID, hostname);
     //Predicate hostPredicate = new OrPredicate(hostPredicates.toArray(new Predicate[hostPredicates.size()]));
     Predicate hostAndStatePredicate = new AndPredicate(statePredicate, hostPredicate);
     Predicate installPredicate = new AndPredicate(hostAndStatePredicate, clusterPredicate);
@@ -387,10 +387,10 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
       UnsupportedPropertyException, NoSuchParentResourceException {
 
     Map<String, String> requestInfo = new HashMap<String, String>();
-    requestInfo.put("context", "Start components on added hosts");
+    requestInfo.put("context", String.format("Start components on host %s", hostName));
 
     Predicate clusterPredicate = new EqualsPredicate<String>(HOST_COMPONENT_CLUSTER_NAME_PROPERTY_ID, cluster);
-    Predicate hostPredicate = new EqualsPredicate(HOST_COMPONENT_HOST_NAME_PROPERTY_ID, hostName);
+    Predicate hostPredicate = new EqualsPredicate<String>(HOST_COMPONENT_HOST_NAME_PROPERTY_ID, hostName);
     //Predicate hostPredicate = new OrPredicate(hostPredicates.toArray(new Predicate[hostPredicates.size()]));
 
     RequestStageContainer requestStages;
@@ -742,12 +742,32 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
     RequestStageContainer requestStages = modifyResources(new Command<RequestStageContainer>() {
       @Override
       public RequestStageContainer invoke() throws AmbariException {
-        return updateHostComponents(stages, requests, request.getRequestInfoProperties(),
-            runSmokeTest);
+        RequestStageContainer stageContainer = null;
+        int retriesRemaining = 100;
+        do {
+          try {
+            stageContainer = updateHostComponents(stages, requests, request.getRequestInfoProperties(),
+                runSmokeTest);
+          } catch (Exception e) {
+            LOG.info("Caught an exception while updating host components, retrying : " + e);
+            if (--retriesRemaining == 0) {
+              e.printStackTrace();
+              throw new RuntimeException("Update Host request submission failed: " + e, e);
+            } else {
+              try {
+                Thread.sleep(250);
+              } catch (InterruptedException ie) {
+                Thread.currentThread().interrupt();
+                throw new RuntimeException("Update Host request submission failed: " + e, e);
+              }
+            }
+          }
+        } while (stageContainer == null);
+
+        return stageContainer;
       }
     });
     notifyUpdate(Resource.Type.HostComponent, request, predicate);
-
     return requestStages;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
index 07c0e58..47a4ce0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java
@@ -538,7 +538,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
     }
   }
 
-  public RequestStatusResponse install(final String hostname, final String cluster)
+  public RequestStatusResponse install(final String cluster, final String hostname)
       throws ResourceAlreadyExistsException,
       SystemException,
       NoSuchParentResourceException,
@@ -549,7 +549,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
         install(cluster, hostname);
   }
 
-  public RequestStatusResponse start(final String hostname, final String cluster)
+  public RequestStatusResponse start(final String cluster, final String hostname)
       throws ResourceAlreadyExistsException,
       SystemException,
       NoSuchParentResourceException,

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java
index 3da92f1..a1a0ac6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ProvisionClusterRequest.java
@@ -21,7 +21,6 @@
 package org.apache.ambari.server.controller.internal;
 
 import org.apache.ambari.server.api.predicate.InvalidQueryException;
-import org.apache.ambari.server.api.predicate.PredicateCompiler;
 import org.apache.ambari.server.stack.NoSuchStackException;
 import org.apache.ambari.server.topology.Blueprint;
 import org.apache.ambari.server.topology.BlueprintFactory;
@@ -46,7 +45,6 @@ import java.util.Map;
 public class ProvisionClusterRequest implements TopologyRequest {
 
   private static BlueprintFactory blueprintFactory;
-  private static PredicateCompiler predicateCompiler = new PredicateCompiler();
   private static ConfigurationFactory configurationFactory = new ConfigurationFactory();
 
   private String clusterName;
@@ -90,6 +88,11 @@ public class ProvisionClusterRequest implements TopologyRequest {
   }
 
   @Override
+  public Type getType() {
+    return Type.PROVISION;
+  }
+
+  @Override
   public Blueprint getBlueprint() {
     return blueprint;
   }
@@ -110,6 +113,11 @@ public class ProvisionClusterRequest implements TopologyRequest {
     return Collections.<TopologyValidator>singletonList(new RequiredPasswordValidator(defaultPassword));
   }
 
+  @Override
+  public String getCommandDescription() {
+    return String.format("Provision Cluster '%s'", clusterName);
+  }
+
   private void parseBlueprint(Map<String, Object> properties) throws NoSuchStackException, NoSuchBlueprintException {
     String blueprintName = String.valueOf(properties.get(ClusterResourceProvider.BLUEPRINT_PROPERTY_ID));
     blueprint = blueprintFactory.getBlueprint(blueprintName);
@@ -154,7 +162,7 @@ public class ProvisionClusterRequest implements TopologyRequest {
           String predicate = hostProperties.get("host_predicate");
           if (predicate != null && ! predicate.isEmpty()) {
             try {
-              hostGroupInfo.setPredicate(predicateCompiler.compile(predicate));
+              hostGroupInfo.setPredicate(predicate);
             } catch (InvalidQueryException e) {
               throw new InvalidTopologyTemplateException(
                   String.format("Unable to compile host predicate '%s': %s", predicate, e), e);

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java
index f3e45aa..1530a3e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ScaleClusterRequest.java
@@ -20,7 +20,6 @@
 package org.apache.ambari.server.controller.internal;
 
 import org.apache.ambari.server.api.predicate.InvalidQueryException;
-import org.apache.ambari.server.api.predicate.PredicateCompiler;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.stack.NoSuchStackException;
 import org.apache.ambari.server.topology.Blueprint;
@@ -42,10 +41,11 @@ import java.util.Map;
 public class ScaleClusterRequest implements TopologyRequest {
 
   private static BlueprintFactory blueprintFactory;
-  private static final PredicateCompiler predicateCompiler = new PredicateCompiler();
 
   private String clusterName;
 
+  private Blueprint blueprint;
+
   private Map<String, HostGroupInfo> hostGroupInfoMap = new HashMap<String, HostGroupInfo>();
 
   public static void init(BlueprintFactory factory) {
@@ -62,15 +62,57 @@ public class ScaleClusterRequest implements TopologyRequest {
     }
   }
 
+  @Override
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  @Override
+  public Type getType() {
+    return Type.SCALE;
+  }
+
+  @Override
+  public Blueprint getBlueprint() {
+    return blueprint;
+  }
+
+  @Override
+  public Configuration getConfiguration() {
+    // currently don't allow cluster scoped configuration in scaling operation
+    return new Configuration(Collections.<String, Map<String, String>>emptyMap(),
+        Collections.<String, Map<String, Map<String, String>>>emptyMap());
+  }
+
+  @Override
+  public Map<String, HostGroupInfo> getHostGroupInfo() {
+    return hostGroupInfoMap;
+  }
+
+  @Override
+  public List<TopologyValidator> getTopologyValidators() {
+    return Collections.emptyList();
+  }
+
+  @Override
+  public String getCommandDescription() {
+    return String.format("Scale Cluster '%s' (+%s hosts)", clusterName, getTotalRequestedHostCount());
+  }
+
   private void parseHostGroup(Map<String, Object> properties) throws InvalidTopologyTemplateException {
+    String blueprintName = String.valueOf(properties.get(HostResourceProvider.BLUEPRINT_PROPERTY_ID));
+    if (blueprint == null) {
+      blueprint = parseBlueprint(blueprintName);
+    } else if (! blueprintName.equals(blueprint.getName())) {
+      throw new InvalidTopologyTemplateException(
+          "Currently, a scaling request may only refer to a single blueprint");
+    }
+
     String hgName = String.valueOf(properties.get(HostResourceProvider.HOSTGROUP_PROPERTY_ID));
     //todo: need to use fully qualified host group name.  For now, disregard name collisions across BP's
     HostGroupInfo hostGroupInfo = hostGroupInfoMap.get(hgName);
 
     if (hostGroupInfo == null) {
-      String bpName = String.valueOf(properties.get(HostResourceProvider.BLUEPRINT_PROPERTY_ID));
-      Blueprint blueprint = parseBlueprint(bpName);
-
       if (blueprint.getHostGroup(hgName) == null) {
         throw new InvalidTopologyTemplateException("Invalid host group specified in request: " + hgName);
       }
@@ -78,15 +120,18 @@ public class ScaleClusterRequest implements TopologyRequest {
       hostGroupInfoMap.put(hgName, hostGroupInfo);
     }
 
+    // specifying configuration is scaling request isn't permitted
+    hostGroupInfo.setConfiguration(new Configuration(Collections.<String, Map<String, String>>emptyMap(),
+        Collections.<String, Map<String, Map<String, String>>>emptyMap()));
+
     // process host_name and host_count
     if (properties.containsKey("host_count")) {
-
       //todo: validate the host_name and host_predicate are not both specified for same group
       //todo: validate that when predicate is specified that only a single host group entry is specified
       String predicate = String.valueOf(properties.get("host_predicate"));
       if (predicate != null && ! predicate.isEmpty()) {
         try {
-          hostGroupInfo.setPredicate(predicateCompiler.compile(predicate));
+          hostGroupInfo.setPredicate(predicate);
         } catch (InvalidQueryException e) {
           throw new InvalidTopologyTemplateException(
               String.format("Unable to compile host predicate '%s': %s", predicate, e), e);
@@ -105,33 +150,6 @@ public class ScaleClusterRequest implements TopologyRequest {
     }
   }
 
-  @Override
-  public String getClusterName() {
-    return clusterName;
-  }
-
-  @Override
-  public Blueprint getBlueprint() {
-    // bp is only set at HG level from scaling operations
-    return null;
-  }
-
-  @Override
-  public Configuration getConfiguration() {
-    // currently don't allow cluster scoped configuration in scaling operation
-    return null;
-  }
-
-  @Override
-  public Map<String, HostGroupInfo> getHostGroupInfo() {
-    return hostGroupInfoMap;
-  }
-
-  @Override
-  public List<TopologyValidator> getTopologyValidators() {
-    return Collections.emptyList();
-  }
-
   private Blueprint parseBlueprint(String blueprintName) throws InvalidTopologyTemplateException  {
     Blueprint blueprint;
     try {
@@ -153,4 +171,12 @@ public class ScaleClusterRequest implements TopologyRequest {
     return hostname != null ? hostname :
         String.valueOf(properties.get(HostResourceProvider.HOST_NAME_NO_CATEGORY_PROPERTY_ID));
   }
+
+  private int getTotalRequestedHostCount() {
+    int count = 0;
+    for (HostGroupInfo groupInfo : getHostGroupInfo().values()) {
+      count += groupInfo.getRequestedHostCount();
+    }
+    return count;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java
index 7167449..38b5a3c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/Stack.java
@@ -36,6 +36,7 @@ import org.apache.ambari.server.controller.StackServiceRequest;
 import org.apache.ambari.server.controller.StackServiceResponse;
 import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.state.AutoDeployInfo;
+import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.DependencyInfo;
 import org.apache.ambari.server.state.PropertyInfo;
 import org.apache.ambari.server.topology.Cardinality;
@@ -140,11 +141,8 @@ public class Stack {
    *          the management controller (not {@code null}).
    * @throws AmbariException
    */
-  public Stack(StackEntity stack,
-      AmbariManagementController ambariManagementController)
-      throws AmbariException {
-    this(stack.getStackName(), stack.getStackVersion(),
-        ambariManagementController);
+  public Stack(StackEntity stack, AmbariManagementController ambariManagementController) throws AmbariException {
+    this(stack.getStackName(), stack.getStackVersion(), ambariManagementController);
   }
 
   /**
@@ -236,6 +234,28 @@ public class Stack {
   }
 
   /**
+   * Get info for the specified component.
+   *
+   * @param component  component name
+   *
+   * @return component information for the requested component
+   *         or null if the component doesn't exist in the stack
+   */
+  public ComponentInfo getComponentInfo(String component) {
+    ComponentInfo componentInfo = null;
+    String service = getServiceForComponent(component);
+    if (service != null) {
+      try {
+        componentInfo = controller.getAmbariMetaInfo().getComponent(
+            getName(), getVersion(), service, component);
+      } catch (AmbariException e) {
+        // just return null if component doesn't exist
+      }
+    }
+    return componentInfo;
+  }
+
+  /**
    * Get all configuration types, including excluded types for the specified service.
    *
    * @param service  service name

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java
index a11ec33..1457f3c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostGroupDAO.java
@@ -25,6 +25,7 @@ import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.TopologyHostGroupEntity;
 
 import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
 import java.util.List;
 
 @Singleton
@@ -41,6 +42,17 @@ public class TopologyHostGroupDAO {
   }
 
   @RequiresSession
+  public TopologyHostGroupEntity findByRequestIdAndName(long topologyRequestId, String name) {
+    TypedQuery<TopologyHostGroupEntity> query = entityManagerProvider.get().createNamedQuery(
+        "TopologyHostGroupEntity.findByRequestIdAndName", TopologyHostGroupEntity.class);
+
+    query.setParameter("requestId", topologyRequestId);
+    query.setParameter("name", name);
+
+    return query.getSingleResult();
+  }
+
+  @RequiresSession
   public List<TopologyHostGroupEntity> findAll() {
     return daoUtils.selectAll(entityManagerProvider.get(), TopologyHostGroupEntity.class);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostTaskDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostTaskDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostTaskDAO.java
new file mode 100644
index 0000000..031601a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyHostTaskDAO.java
@@ -0,0 +1,73 @@
+/**
+ * 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.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.TopologyHostTaskEntity;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.Collection;
+import java.util.List;
+
+@Singleton
+public class TopologyHostTaskDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  @Inject
+  DaoUtils daoUtils;
+
+  @RequiresSession
+  public TopologyHostTaskEntity findById(Long id) {
+    return entityManagerProvider.get().find(TopologyHostTaskEntity.class, id);
+  }
+
+  public Collection<TopologyHostTaskEntity> findByHostRequest(Long id) {
+    TypedQuery<TopologyHostTaskEntity> query = entityManagerProvider.get()
+        .createNamedQuery("TopologyHostTaskEntity.findByHostRequest", TopologyHostTaskEntity.class);
+
+    query.setParameter("hostRequestId", id);
+    return daoUtils.selectList(query);
+  }
+
+  @RequiresSession
+  public List<TopologyHostTaskEntity> findAll() {
+    return daoUtils.selectAll(entityManagerProvider.get(), TopologyHostTaskEntity.class);
+  }
+
+  @Transactional
+  public void create(TopologyHostTaskEntity requestEntity) {
+    entityManagerProvider.get().persist(requestEntity);
+  }
+
+  @Transactional
+  public TopologyHostTaskEntity merge(TopologyHostTaskEntity requestEntity) {
+    return entityManagerProvider.get().merge(requestEntity);
+  }
+
+  @Transactional
+  public void remove(TopologyHostTaskEntity requestEntity) {
+    entityManagerProvider.get().remove(requestEntity);
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyLogicalTaskDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyLogicalTaskDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyLogicalTaskDAO.java
new file mode 100644
index 0000000..f0331cc
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/TopologyLogicalTaskDAO.java
@@ -0,0 +1,63 @@
+/**
+ * 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.orm.dao;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.TopologyLogicalTaskEntity;
+
+import javax.persistence.EntityManager;
+import java.util.List;
+
+@Singleton
+public class TopologyLogicalTaskDAO {
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  @Inject
+  DaoUtils daoUtils;
+
+  @RequiresSession
+  public TopologyLogicalTaskEntity findById(Long id) {
+    return entityManagerProvider.get().find(TopologyLogicalTaskEntity.class, id);
+  }
+
+  @RequiresSession
+  public List<TopologyLogicalTaskEntity> findAll() {
+    return daoUtils.selectAll(entityManagerProvider.get(), TopologyLogicalTaskEntity.class);
+  }
+
+  @Transactional
+  public void create(TopologyLogicalTaskEntity logicalTaskEntity) {
+    entityManagerProvider.get().persist(logicalTaskEntity);
+  }
+
+  @Transactional
+  public TopologyLogicalTaskEntity merge(TopologyLogicalTaskEntity logicalTaskEntity) {
+    return entityManagerProvider.get().merge(logicalTaskEntity);
+  }
+
+  @Transactional
+  public void remove(TopologyLogicalTaskEntity logicalTaskEntity) {
+    entityManagerProvider.get().remove(logicalTaskEntity);
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
index 21813ba..ada924a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java
@@ -63,9 +63,6 @@ public class BlueprintEntity {
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint")
   private Collection<BlueprintConfigEntity> configurations;
 
-  @Transient
-  private static Gson jsonSerializer = new Gson();
-
 
   /**
    * Get the blueprint name.

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java
index 3448b65..0a81286 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostGroupEntity.java
@@ -22,19 +22,37 @@ import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.Lob;
 import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
+import javax.persistence.TableGenerator;
 import java.util.Collection;
 
 @Entity
 @Table(name = "topology_hostgroup")
+@NamedQueries({
+  @NamedQuery(name = "TopologyHostGroupEntity.findByRequestIdAndName",
+    query = "SELECT req FROM TopologyHostGroupEntity req WHERE req.topologyRequestEntity.id = :requestId AND req.name = :name")
+})
+@TableGenerator(name = "topology_host_group_id_generator", table = "ambari_sequences",
+  pkColumnName = "sequence_name", valueColumnName = "sequence_value",
+  pkColumnValue = "topology_host_group_id_seq", initialValue = 0)
 public class TopologyHostGroupEntity {
   @Id
-  @Column(name = "name", length = 255, nullable = false)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_host_group_id_generator")
+  @Column(name = "id", nullable = false, updatable = false)
+  private Long id;
+
+  @Column(name = "name", nullable = false, updatable = false)
+  @Basic(fetch = FetchType.LAZY)
+  @Lob
   private String name;
 
   @Column(name = "group_properties")
@@ -57,6 +75,14 @@ public class TopologyHostGroupEntity {
   @OneToMany(mappedBy = "topologyHostGroupEntity", cascade = CascadeType.ALL)
   private Collection<TopologyHostRequestEntity> topologyHostRequestEntities;
 
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
   public String getName() {
     return name;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java
index 36c2782..8ae8aa6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostInfoEntity.java
@@ -48,7 +48,7 @@ public class TopologyHostInfoEntity {
   private String predicate;
 
   @ManyToOne
-  @JoinColumn(name = "group_name", referencedColumnName = "name", nullable = false)
+  @JoinColumn(name = "group_id", referencedColumnName = "id", nullable = false)
   private TopologyHostGroupEntity topologyHostGroupEntity;
 
   public Long getId() {
@@ -59,8 +59,8 @@ public class TopologyHostInfoEntity {
     this.id = id;
   }
 
-  public String getGroupName() {
-    return topologyHostGroupEntity != null ? topologyHostGroupEntity.getName() : null;
+  public Long getGroupId() {
+    return topologyHostGroupEntity.getId();
   }
 
   public String getFqdn() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java
index 2f42d80..4e05ea1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostRequestEntity.java
@@ -32,12 +32,9 @@ import java.util.Collection;
 
 @Entity
 @Table(name = "topology_host_request")
-@TableGenerator(name = "topology_host_request_id_generator", table = "ambari_sequences",
-  pkColumnName = "sequence_name", valueColumnName = "sequence_value",
-  pkColumnValue = "topology_host_request_id_seq", initialValue = 0)
 public class TopologyHostRequestEntity {
   @Id
-  @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_request_id_generator")
+//  @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_host_request_id_generator")
   @Column(name = "id", nullable = false, updatable = false)
   private Long id;
 
@@ -52,7 +49,7 @@ public class TopologyHostRequestEntity {
   private TopologyLogicalRequestEntity topologyLogicalRequestEntity;
 
   @ManyToOne
-  @JoinColumn(name = "group_name", referencedColumnName = "name", nullable = false)
+  @JoinColumn(name = "group_id", referencedColumnName = "id", nullable = false)
   private TopologyHostGroupEntity topologyHostGroupEntity;
 
   @OneToMany(mappedBy = "topologyHostRequestEntity", cascade = CascadeType.ALL, orphanRemoval = true)
@@ -70,8 +67,8 @@ public class TopologyHostRequestEntity {
     return topologyLogicalRequestEntity != null ? topologyLogicalRequestEntity.getTopologyRequestId() : null;
   }
 
-  public String getHostGroupName() {
-    return topologyHostGroupEntity != null ? topologyHostGroupEntity.getName() : null;
+  public Long getHostGroupId() {
+    return topologyHostGroupEntity.getId();
   }
 
   public Long getStageId() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java
index 2c31bb5..49d3a97 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyHostTaskEntity.java
@@ -25,6 +25,8 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
@@ -36,6 +38,10 @@ import java.util.Collection;
 @TableGenerator(name = "topology_host_task_id_generator", table = "ambari_sequences",
   pkColumnName = "sequence_name", valueColumnName = "sequence_value",
   pkColumnValue = "topology_host_task_id_seq", initialValue = 0)
+@NamedQueries({
+  @NamedQuery(name = "TopologyHostTaskEntity.findByHostRequest",
+      query = "SELECT req FROM TopologyHostTaskEntity req WHERE req.topologyHostRequestEntity.id = :hostRequestId")
+})
 public class TopologyHostTaskEntity {
   @Id
   @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_host_task_id_generator")

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java
index 023a058..4d255b2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/TopologyLogicalRequestEntity.java
@@ -33,12 +33,8 @@ import java.util.Collection;
 
 @Entity
 @Table(name = "topology_logical_request")
-@TableGenerator(name = "topology_logical_request_id_generator", table = "ambari_sequences",
-  pkColumnName = "sequence_name", valueColumnName = "sequence_value",
-  pkColumnValue = "topology_logical_request_id_seq", initialValue = 0)
 public class TopologyLogicalRequestEntity {
   @Id
-  @GeneratedValue(strategy = GenerationType.TABLE, generator = "topology_logical_request_id_generator")
   @Column(name = "id", nullable = false, updatable = false)
   private Long id;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
new file mode 100644
index 0000000..e6c43ef
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java
@@ -0,0 +1,499 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.topology;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ClusterNotFoundException;
+import org.apache.ambari.server.Role;
+import org.apache.ambari.server.RoleCommand;
+import org.apache.ambari.server.actionmanager.HostRoleCommand;
+import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
+import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.AmbariServer;
+import org.apache.ambari.server.controller.ClusterRequest;
+import org.apache.ambari.server.controller.ConfigGroupRequest;
+import org.apache.ambari.server.controller.ConfigurationRequest;
+import org.apache.ambari.server.controller.RequestStatusResponse;
+import org.apache.ambari.server.controller.ServiceComponentHostRequest;
+import org.apache.ambari.server.controller.ServiceComponentRequest;
+import org.apache.ambari.server.controller.ServiceRequest;
+import org.apache.ambari.server.controller.internal.AbstractResourceProvider;
+import org.apache.ambari.server.controller.internal.ComponentResourceProvider;
+import org.apache.ambari.server.controller.internal.ConfigGroupResourceProvider;
+import org.apache.ambari.server.controller.internal.HostComponentResourceProvider;
+import org.apache.ambari.server.controller.internal.HostResourceProvider;
+import org.apache.ambari.server.controller.internal.RequestImpl;
+import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
+import org.apache.ambari.server.controller.internal.Stack;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Config;
+import org.apache.ambari.server.state.ConfigImpl;
+import org.apache.ambari.server.state.DesiredConfig;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.SecurityType;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.configgroup.ConfigGroup;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides topology related information as well as access to the core Ambari functionality.
+ */
+public class AmbariContext {
+
+  public enum TaskType {INSTALL, START}
+
+  private static PersistedState persistedState = new PersistedStateImpl();
+  private static AmbariManagementController controller;
+  //todo: task id's.  Use existing mechanism for getting next task id sequence
+  private final static AtomicLong nextTaskId = new AtomicLong(10000);
+
+  private static HostRoleCommandFactory hostRoleCommandFactory;
+  private static HostResourceProvider hostResourceProvider;
+  private static ServiceResourceProvider serviceResourceProvider;
+  private static ComponentResourceProvider componentResourceProvider;
+  private HostComponentResourceProvider hostComponentResourceProvider;
+
+  private final static Logger LOG = LoggerFactory.getLogger(TopologyManager.class);
+
+  public boolean isClusterKerberosEnabled(String clusterName) {
+    Cluster cluster;
+    try {
+      cluster = getController().getClusters().getCluster(clusterName);
+    } catch (AmbariException e) {
+      throw new RuntimeException("Parent Cluster resource doesn't exist.  clusterName= " + clusterName);
+    }
+    return cluster.getSecurityType() == SecurityType.KERBEROS;
+  }
+
+  //todo: change return type to a topology abstraction
+  public HostRoleCommand createAmbariTask(long requestId, long stageId, String component, String host, TaskType type) {
+    HostRoleCommand task = hostRoleCommandFactory.create(host, Role.valueOf(component), null, RoleCommand.valueOf(type.name()));
+    task.setStatus(HostRoleStatus.PENDING);
+    task.setCommandDetail(String.format("Logical Task: %s component %s on host %s", type.name(), component, host));
+    task.setTaskId(nextTaskId.getAndIncrement());
+    task.setRequestId(requestId);
+    task.setStageId(stageId);
+
+    return task;
+  }
+
+  //todo: change return type to a topology abstraction
+  public HostRoleCommand createAmbariTask(long taskId, long requestId, long stageId,
+                                          String component, String host, TaskType type) {
+    synchronized (nextTaskId) {
+      if (nextTaskId.get() <= taskId) {
+        nextTaskId.set(taskId + 1);
+      }
+    }
+
+    HostRoleCommand task = hostRoleCommandFactory.create(
+        host, Role.valueOf(component), null, RoleCommand.valueOf(type.name()));
+    task.setStatus(HostRoleStatus.PENDING);
+    task.setCommandDetail(String.format("Logical Task: %s component %s on host %s",
+        type.name(), component, host));
+    task.setTaskId(taskId);
+    task.setRequestId(requestId);
+    task.setStageId(stageId);
+
+    return task;
+  }
+
+  public HostRoleCommand getPhysicalTask(long id) {
+    return getController().getActionManager().getTaskById(id);
+  }
+
+  public void createAmbariResources(ClusterTopology topology) {
+    String clusterName = topology.getClusterName();
+    Stack stack = topology.getBlueprint().getStack();
+    createAmbariClusterResource(clusterName, stack.getName(), stack.getVersion());
+    createAmbariServiceAndComponentResources(topology);
+  }
+
+  public void createAmbariClusterResource(String clusterName, String stackName, String stackVersion) {
+    String stackInfo = String.format("%s-%s", stackName, stackVersion);
+    ClusterRequest clusterRequest = new ClusterRequest(null, clusterName, stackInfo, null);
+    try {
+      getController().createCluster(clusterRequest);
+    } catch (AmbariException e) {
+      e.printStackTrace();
+      throw new RuntimeException("Failed to create Cluster resource: " + e, e);
+    }
+  }
+
+  public void createAmbariServiceAndComponentResources(ClusterTopology topology) {
+    String clusterName = topology.getClusterName();
+    Collection<String> services = topology.getBlueprint().getServices();
+
+    try {
+      Cluster cluster = getController().getClusters().getCluster(clusterName);
+      services.removeAll(cluster.getServices().keySet());
+    } catch (AmbariException e) {
+      e.printStackTrace();
+      throw new RuntimeException("Failed to persist service and component resources: " + e, e);
+    }
+    Set<ServiceRequest> serviceRequests = new HashSet<ServiceRequest>();
+    Set<ServiceComponentRequest> componentRequests = new HashSet<ServiceComponentRequest>();
+    for (String service : services) {
+      serviceRequests.add(new ServiceRequest(clusterName, service, null));
+      for (String component : topology.getBlueprint().getComponents(service)) {
+        componentRequests.add(new ServiceComponentRequest(clusterName, service, component, null));
+      }
+    }
+    try {
+      getServiceResourceProvider().createServices(serviceRequests);
+      getComponentResourceProvider().createComponents(componentRequests);
+    } catch (AmbariException e) {
+      e.printStackTrace();
+      throw new RuntimeException("Failed to persist service and component resources: " + e, e);
+    }
+  }
+
+  public void createAmbariHostResources(String clusterName, String hostName, Map<String, Collection<String>> components) {
+    Host host;
+    try {
+      host = getController().getClusters().getHost(hostName);
+    } catch (AmbariException e) {
+      // system exception, shouldn't occur
+      throw new RuntimeException(String.format(
+          "Unable to obtain host instance '%s' when persisting host resources", hostName));
+    }
+
+    Map<String, Object> properties = new HashMap<String, Object>();
+    properties.put(HostResourceProvider.HOST_CLUSTER_NAME_PROPERTY_ID, clusterName);
+    properties.put(HostResourceProvider.HOST_NAME_PROPERTY_ID, hostName);
+    properties.put(HostResourceProvider.HOST_RACK_INFO_PROPERTY_ID, host.getRackInfo());
+
+    try {
+      getHostResourceProvider().createHosts(new RequestImpl(null, Collections.singleton(properties), null, null));
+    } catch (AmbariException e) {
+      e.printStackTrace();
+      throw new RuntimeException(String.format("Unable to create host resource for host '%s': %s",
+          hostName, e.toString()), e);
+    }
+
+    Set<ServiceComponentHostRequest> requests = new HashSet<ServiceComponentHostRequest>();
+    for (Map.Entry<String, Collection<String>> entry : components.entrySet()) {
+      String service = entry.getKey();
+      for (String component : entry.getValue()) {
+        //todo: handle this in a generic manner.  These checks are all over the code
+        if (!component.equals("AMBARI_SERVER")) {
+          requests.add(new ServiceComponentHostRequest(clusterName, service, component, hostName, null));
+        }
+      }
+    }
+    try {
+      getController().createHostComponents(requests);
+    } catch (AmbariException e) {
+      e.printStackTrace();
+      throw new RuntimeException(String.format("Unable to create host component resource for host '%s': %s",
+          hostName, e.toString()), e);
+    }
+  }
+
+  /**
+   * Since global configs are deprecated since 1.7.0, but still supported.
+   * We should automatically map any globals used, to *-env dictionaries.
+   *
+   * @param blueprintConfigurations map of blueprint configurations keyed by type
+   */
+  //todo: do once for all configs
+  public void convertGlobalProperties(ClusterTopology topology,
+                                      Map<String, Map<String, String>> blueprintConfigurations) {
+
+    Stack stack = topology.getBlueprint().getStack();
+    StackId stackId = new StackId(stack.getName(), stack.getVersion());
+    getController().getConfigHelper().moveDeprecatedGlobals(
+        stackId, blueprintConfigurations, topology.getClusterName());
+  }
+
+  public Long getNextRequestId() {
+    return getController().getActionManager().getNextRequestId();
+  }
+
+  public synchronized AmbariManagementController getController() {
+    if (controller == null) {
+      controller = AmbariServer.getController();
+    }
+    return controller;
+  }
+
+  public static void init(HostRoleCommandFactory factory) {
+    hostRoleCommandFactory = factory;
+  }
+
+  public void registerHostWithConfigGroup(String hostName, ClusterTopology topology, String groupName) {
+    try {
+      if (!addHostToExistingConfigGroups(hostName, topology, groupName)) {
+        createConfigGroupsAndRegisterHost(topology, groupName);
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new RuntimeException("Unable to register config group for host: " + hostName);
+    }
+  }
+
+  public RequestStatusResponse installHost(String hostName, String clusterName) {
+    try {
+      return getHostResourceProvider().install(clusterName, hostName);
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new RuntimeException("INSTALL Host request submission failed: " + e, e);
+    }
+  }
+
+  public RequestStatusResponse startHost(String hostName, String clusterName) {
+    try {
+      return getHostComponentResourceProvider().start(clusterName, hostName);
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new RuntimeException("START Host request submission failed: " + e, e);
+    }
+  }
+
+  /**
+   * Persist cluster state for the ambari UI.  Setting this state informs that UI that a cluster has been
+   * installed and started and that the monitoring screen for the cluster should be displayed to the user.
+   *
+   * @param clusterName  cluster name
+   * @param stackName    stack name
+   * @param stackVersion stack version
+   */
+  public void persistInstallStateForUI(String clusterName, String stackName, String stackVersion) {
+    String stackInfo = String.format("%s-%s", stackName, stackVersion);
+    ClusterRequest clusterRequest = new ClusterRequest(null, clusterName, "INSTALLED", null, stackInfo, null);
+
+    try {
+      getController().updateClusters(Collections.singleton(clusterRequest), null);
+    } catch (AmbariException e) {
+      LOG.error("Unable to set install state for UI", e);
+    }
+  }
+
+  //todo: non topology type shouldn't be returned
+  public List<ConfigurationRequest> createConfigurationRequests(Map<String, Object> clusterProperties) {
+    return AbstractResourceProvider.getConfigurationRequests("Clusters", clusterProperties);
+  }
+
+  public void setConfigurationOnCluster(ClusterRequest clusterRequest) {
+    try {
+      getController().updateClusters(Collections.singleton(clusterRequest), null);
+    } catch (AmbariException e) {
+      e.printStackTrace();
+      throw new RuntimeException("Failed to set configurations on cluster: " + e, e);
+    }
+  }
+
+  public boolean doesConfigurationWithTagExist(String clusterName, String tag) {
+    boolean isTopologyResolved = false;
+    try {
+      Cluster cluster = getController().getClusters().getCluster(clusterName);
+      Collection<DesiredConfig> desiredConfigs = cluster.getDesiredConfigs().values();
+      for (DesiredConfig config : desiredConfigs) {
+        if (config.getTag().equals(tag)) {
+          isTopologyResolved = true;
+          break;
+        }
+      }
+    } catch (ClusterNotFoundException e) {
+      LOG.info("Attempted to determine if configuration is topology resolved for a non-existent cluster: {}",
+          clusterName);
+    } catch (AmbariException e) {
+      throw new RuntimeException(
+          "Unable to determine if cluster config is topology resolved due to unknown error: " + e, e);
+    }
+
+    return isTopologyResolved;
+  }
+
+  public PersistedState getPersistedTopologyState() {
+    return persistedState;
+  }
+
+  public boolean isHostRegisteredWithCluster(String cluster, String host) {
+    boolean found = false;
+    try {
+      Collection<Host> hosts = getController().getClusters().getCluster(cluster).getHosts();
+      for (Host h : hosts) {
+        if (h.getHostName().equals(host)) {
+          found = true;
+          break;
+        }
+      }
+    } catch (AmbariException e) {
+      throw new RuntimeException(String.format("Unable to get hosts for cluster '%s': %s", cluster, e), e);
+    }
+    return found;
+  }
+
+  /**
+   * Add the new host to an existing config group.
+   */
+  private boolean addHostToExistingConfigGroups(String hostName, ClusterTopology topology, String groupName) {
+    boolean addedHost = false;
+    Clusters clusters;
+    Cluster cluster;
+    try {
+      clusters = getController().getClusters();
+      cluster = clusters.getCluster(topology.getClusterName());
+    } catch (AmbariException e) {
+      throw new RuntimeException(String.format(
+          "Attempt to add hosts to a non-existent cluster: '%s'", topology.getClusterName()));
+    }
+    // I don't know of a method to get config group by name
+    //todo: add a method to get config group by name
+    Map<Long, ConfigGroup> configGroups = cluster.getConfigGroups();
+    String qualifiedGroupName = getConfigurationGroupName(topology.getBlueprint().getName(), groupName);
+    for (ConfigGroup group : configGroups.values()) {
+      if (group.getName().equals(qualifiedGroupName)) {
+        try {
+          group.addHost(clusters.getHost(hostName));
+          group.persist();
+          addedHost = true;
+        } catch (AmbariException e) {
+          // shouldn't occur, this host was just added to the cluster
+          throw new RuntimeException(String.format(
+              "Unable to obtain newly created host '%s' from cluster '%s'", hostName, topology.getClusterName()));
+        }
+      }
+    }
+    return addedHost;
+  }
+
+  /**
+   * Register config groups for host group scoped configuration.
+   * For each host group with configuration specified in the blueprint, a config group is created
+   * and the hosts associated with the host group are assigned to the config group.
+   */
+  private void createConfigGroupsAndRegisterHost(ClusterTopology topology, String groupName) {
+
+    //HostGroupEntity entity = hostGroup.getEntity();
+    Map<String, Map<String, Config>> groupConfigs = new HashMap<String, Map<String, Config>>();
+
+    Stack stack = topology.getBlueprint().getHostGroup(groupName).getStack();
+
+    // get the host-group config with cluster creation template overrides
+    Configuration topologyHostGroupConfig = topology.
+        getHostGroupInfo().get(groupName).getConfiguration();
+
+    //handling backwards compatibility for group configs
+    //todo: doesn't belong here
+    convertGlobalProperties(topology, topologyHostGroupConfig.getProperties());
+
+    // iterate over topo host group configs which were defined in CCT/HG and BP/HG only, no parent configs
+    for (Map.Entry<String, Map<String, String>> entry : topologyHostGroupConfig.getProperties().entrySet()) {
+      String type = entry.getKey();
+      String service = stack.getServiceForConfigType(type);
+      Config config = new ConfigImpl(type);
+      config.setTag(groupName);
+      config.setProperties(entry.getValue());
+      //todo: attributes
+      Map<String, Config> serviceConfigs = groupConfigs.get(service);
+      if (serviceConfigs == null) {
+        serviceConfigs = new HashMap<String, Config>();
+        groupConfigs.put(service, serviceConfigs);
+      }
+      serviceConfigs.put(type, config);
+    }
+
+    String bpName = topology.getBlueprint().getName();
+    for (Map.Entry<String, Map<String, Config>> entry : groupConfigs.entrySet()) {
+      String service = entry.getKey();
+      Map<String, Config> serviceConfigs = entry.getValue();
+      String absoluteGroupName = getConfigurationGroupName(bpName, groupName);
+      Collection<String> groupHosts;
+
+      groupHosts = topology.getHostGroupInfo().
+          get(groupName).getHostNames();
+
+      ConfigGroupRequest request = new ConfigGroupRequest(
+          null, topology.getClusterName(), absoluteGroupName, service, "Host Group Configuration",
+          new HashSet<String>(groupHosts), serviceConfigs);
+
+      // get the config group provider and create config group resource
+      ConfigGroupResourceProvider configGroupProvider = (ConfigGroupResourceProvider)
+          ClusterControllerHelper.getClusterController().ensureResourceProvider(Resource.Type.ConfigGroup);
+
+      try {
+        configGroupProvider.createResources(Collections.singleton(request));
+      } catch (Exception e) {
+        e.printStackTrace();
+        throw new RuntimeException("Failed to create new configuration group: " + e, e);
+      }
+    }
+  }
+
+  /**
+   * Get a config group name based on a bp and host group.
+   *
+   * @param bpName        blueprint name
+   * @param hostGroupName host group name
+   * @return config group name
+   */
+  private String getConfigurationGroupName(String bpName, String hostGroupName) {
+    return String.format("%s:%s", bpName, hostGroupName);
+  }
+
+  private synchronized HostResourceProvider getHostResourceProvider() {
+    if (hostResourceProvider == null) {
+      hostResourceProvider = (HostResourceProvider)
+          ClusterControllerHelper.getClusterController().ensureResourceProvider(Resource.Type.Host);
+
+    }
+    return hostResourceProvider;
+  }
+
+  private synchronized HostComponentResourceProvider getHostComponentResourceProvider() {
+    if (hostComponentResourceProvider == null) {
+      hostComponentResourceProvider = (HostComponentResourceProvider)
+          ClusterControllerHelper.getClusterController().ensureResourceProvider(Resource.Type.HostComponent);
+
+    }
+    return hostComponentResourceProvider;
+  }
+
+  private synchronized ServiceResourceProvider getServiceResourceProvider() {
+    if (serviceResourceProvider == null) {
+      serviceResourceProvider = (ServiceResourceProvider) ClusterControllerHelper.
+          getClusterController().ensureResourceProvider(Resource.Type.Service);
+    }
+    return serviceResourceProvider;
+  }
+
+  private synchronized ComponentResourceProvider getComponentResourceProvider() {
+    if (componentResourceProvider == null) {
+      componentResourceProvider = (ComponentResourceProvider) ClusterControllerHelper.
+          getClusterController().ensureResourceProvider(Resource.Type.Component);
+    }
+    return componentResourceProvider;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
index f27d4ab..481d217 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java
@@ -229,8 +229,7 @@ public class BlueprintImpl implements Blueprint {
   }
 
   /**
-   * Process blueprint configurations.  This includes obtaining the default configuration properties
-   * from the stack and overlaying configuration properties specified in the blueprint.
+   * Process blueprint configurations.
    */
   private void processConfiguration(Collection<BlueprintConfigEntity> configs) {
     // not setting stack configuration as parent until after host groups are parsed in constructor

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java
index 07ea50b..a8c2ff3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterConfigurationRequest.java
@@ -19,11 +19,8 @@
 package org.apache.ambari.server.topology;
 
 import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.controller.AmbariManagementController;
-import org.apache.ambari.server.controller.AmbariServer;
 import org.apache.ambari.server.controller.ClusterRequest;
 import org.apache.ambari.server.controller.ConfigurationRequest;
-import org.apache.ambari.server.controller.internal.AbstractResourceProvider;
 import org.apache.ambari.server.controller.internal.BlueprintConfigurationProcessor;
 import org.apache.ambari.server.controller.internal.ClusterResourceProvider;
 import org.apache.ambari.server.controller.internal.ConfigurationTopologyException;
@@ -47,18 +44,21 @@ public class ClusterConfigurationRequest {
 
   protected final static Logger LOG = LoggerFactory.getLogger(ClusterConfigurationRequest.class);
 
+  private AmbariContext ambariContext;
   private ClusterTopology clusterTopology;
   private BlueprintConfigurationProcessor configurationProcessor;
-  private AmbariManagementController controller = AmbariServer.getController();
   private Stack stack;
 
-  public ClusterConfigurationRequest(ClusterTopology clusterTopology) throws AmbariException {
+  public ClusterConfigurationRequest(AmbariContext ambariContext, ClusterTopology clusterTopology, boolean setInitial) {
+    this.ambariContext = ambariContext;
+    this.clusterTopology = clusterTopology;
     Blueprint blueprint = clusterTopology.getBlueprint();
     this.stack = blueprint.getStack();
-    this.clusterTopology = clusterTopology;
     // set initial configuration (not topology resolved)
     this.configurationProcessor = new BlueprintConfigurationProcessor(clusterTopology);
-    setConfigurationsOnCluster(clusterTopology, "INITIAL");
+    if (setInitial) {
+      setConfigurationsOnCluster(clusterTopology, TopologyManager.INITIAL_CONFIG_TAG);
+    }
   }
 
   // get names of required host groups
@@ -74,17 +74,15 @@ public class ClusterConfigurationRequest {
       //log and continue to set configs on cluster to make progress
       LOG.error("An exception occurred while doing configuration topology update: " + e, e);
     }
-    setConfigurationsOnCluster(clusterTopology, "TOPOLOGY_RESOLVED");
+    setConfigurationsOnCluster(clusterTopology, TopologyManager.TOPOLOGY_RESOLVED_TAG);
   }
 
   /**
    * Set all configurations on the cluster resource.
    * @param clusterTopology  cluster topology
    * @param tag              config tag
-   *
-   * @throws AmbariException unable to set config on cluster
    */
-  public void setConfigurationsOnCluster(ClusterTopology clusterTopology, String tag) throws AmbariException {
+  public void setConfigurationsOnCluster(ClusterTopology clusterTopology, String tag)  {
     //todo: also handle setting of host group scoped configuration which is updated by config processor
     List<BlueprintServiceConfigRequest> listofConfigRequests = new LinkedList<BlueprintServiceConfigRequest>();
 
@@ -134,11 +132,9 @@ public class ClusterConfigurationRequest {
    * This method will also send these requests to the management controller.
    *
    * @param listOfBlueprintConfigRequests a list of requests to send to the AmbariManagementController.
-   *
-   * @throws AmbariException upon any error that occurs during updateClusters
    */
   private void setConfigurationsOnCluster(List<BlueprintServiceConfigRequest> listOfBlueprintConfigRequests,
-                                          String tag) throws AmbariException {
+                                          String tag)  {
     // iterate over services to deploy
     for (BlueprintServiceConfigRequest blueprintConfigRequest : listOfBlueprintConfigRequests) {
       ClusterRequest clusterRequest = null;
@@ -189,9 +185,7 @@ public class ClusterConfigurationRequest {
               null);
         }
 
-        //todo: made getConfigurationRequests static so that I could access from here, where does it belong?
-        List<ConfigurationRequest> listOfRequests =
-            AbstractResourceProvider.getConfigurationRequests("Clusters", clusterProperties);
+        List<ConfigurationRequest> listOfRequests = ambariContext.createConfigurationRequests(clusterProperties);
         requestsPerService.addAll(listOfRequests);
       }
 
@@ -199,7 +193,7 @@ public class ClusterConfigurationRequest {
       if (clusterRequest != null) {
         clusterRequest.setDesiredConfig(requestsPerService);
         LOG.info("Sending cluster config update request for service = " + blueprintConfigRequest.getServiceName());
-        controller.updateClusters(Collections.singleton(clusterRequest), null);
+        ambariContext.setConfigurationOnCluster(clusterRequest);
       } else {
         LOG.error("ClusterRequest should not be null for service = " + blueprintConfigRequest.getServiceName());
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java
index e924653..6a7a79b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopology.java
@@ -18,6 +18,9 @@
 
 package org.apache.ambari.server.topology;
 
+import org.apache.ambari.server.controller.RequestStatusResponse;
+import org.apache.ambari.server.state.SecurityType;
+
 import java.util.Collection;
 import java.util.Map;
 
@@ -113,4 +116,31 @@ public interface ClusterTopology {
    * @return true if NameNode HA is enabled; false otherwise
    */
   public boolean isNameNodeHAEnabled();
+
+  /**
+   * Determine if the cluster is kerberos enabled.
+   *
+   * @return true if the cluster is kerberos enabled; false otherwise
+   */
+  public boolean isClusterKerberosEnabled();
+
+  /**
+   * Install the specified host.
+   *
+   * @param hostName  host name
+   * @return install response
+   */
+  public RequestStatusResponse installHost(String hostName);
+
+  /**
+   * Start the specified host.
+   *
+   * @param hostName  host name
+   * @return start response
+   */
+  public RequestStatusResponse startHost(String hostName);
+
+  //todo: don't expose ambari context from this class
+  public AmbariContext getAmbariContext();
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java
index 84e90bf..e0e79b3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/ClusterTopologyImpl.java
@@ -19,6 +19,8 @@
 
 package org.apache.ambari.server.topology;
 
+import org.apache.ambari.server.controller.RequestStatusResponse;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -39,13 +41,13 @@ public class ClusterTopologyImpl implements ClusterTopology {
   //todo: for example: provision using bp1 and scale using bp2
   private Blueprint blueprint;
   private Configuration configuration;
-  private final Map<String, HostGroupInfo> hostGroupInfoMap =
-      new HashMap<String, HostGroupInfo>();
+  private final Map<String, HostGroupInfo> hostGroupInfoMap = new HashMap<String, HostGroupInfo>();
+  private final AmbariContext ambariContext;
 
 
   //todo: will need to convert all usages of hostgroup name to use fully qualified name (BP/HG)
   //todo: for now, restrict scaling to the same BP
-  public ClusterTopologyImpl(TopologyRequest topologyRequest) throws InvalidTopologyException {
+  public ClusterTopologyImpl(AmbariContext ambariContext, TopologyRequest topologyRequest) throws InvalidTopologyException {
     this.clusterName = topologyRequest.getClusterName();
     // provision cluster currently requires that all hostgroups have same BP so it is ok to use root level BP here
     this.blueprint = topologyRequest.getBlueprint();
@@ -54,10 +56,12 @@ public class ClusterTopologyImpl implements ClusterTopology {
     registerHostGroupInfo(topologyRequest.getHostGroupInfo());
 
     validateTopology(topologyRequest.getTopologyValidators());
+    this.ambariContext = ambariContext;
   }
 
   //todo: only used in tests, remove.  Validators not invoked when this constructor is used.
-  public ClusterTopologyImpl(String clusterName,
+  public ClusterTopologyImpl(AmbariContext ambariContext,
+                             String clusterName,
                              Blueprint blueprint,
                              Configuration configuration,
                              Map<String, HostGroupInfo> hostGroupInfo)
@@ -68,6 +72,7 @@ public class ClusterTopologyImpl implements ClusterTopology {
     this.configuration = configuration;
 
     registerHostGroupInfo(hostGroupInfo);
+    this.ambariContext = ambariContext;
   }
 
   @Override
@@ -174,6 +179,26 @@ public class ClusterTopologyImpl implements ClusterTopology {
     }
   }
 
+  @Override
+  public boolean isClusterKerberosEnabled() {
+    return ambariContext.isClusterKerberosEnabled(getClusterName());
+  }
+
+  @Override
+  public RequestStatusResponse installHost(String hostName) {
+    return ambariContext.installHost(hostName, getClusterName());
+  }
+
+  @Override
+  public RequestStatusResponse startHost(String hostName) {
+    return ambariContext.startHost(hostName, getClusterName());
+  }
+
+  @Override
+  public AmbariContext getAmbariContext() {
+    return ambariContext;
+  }
+
   private void registerHostGroupInfo(Map<String, HostGroupInfo> groupInfoMap) throws InvalidTopologyException {
     checkForDuplicateHosts(groupInfoMap);
     for (HostGroupInfo hostGroupInfo : groupInfoMap.values() ) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
index 07cc1b2..a48f331 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostGroupInfo.java
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.topology;
 
+import org.apache.ambari.server.api.predicate.InvalidQueryException;
+import org.apache.ambari.server.api.predicate.PredicateCompiler;
 import org.apache.ambari.server.controller.spi.Predicate;
 
 import java.util.Collection;
@@ -28,6 +30,8 @@ import java.util.HashSet;
  */
 public class HostGroupInfo {
 
+  private static PredicateCompiler predicateCompiler = new PredicateCompiler();
+
   private String hostGroupName;
   /**
    * Hosts contained associated with the host group
@@ -38,7 +42,7 @@ public class HostGroupInfo {
 
   Configuration configuration;
 
-
+  String predicateString;
   Predicate predicate;
 
 
@@ -81,11 +85,16 @@ public class HostGroupInfo {
     return configuration;
   }
 
-  public void setPredicate(Predicate predicate) {
-    this.predicate = predicate;
+  public void setPredicate(String predicateString) throws InvalidQueryException {
+    this.predicate = predicateCompiler.compile(predicateString);
+    this.predicateString = predicateString;
   }
 
   public Predicate getPredicate() {
     return predicate;
   }
+
+  public String getPredicateString() {
+    return predicateString;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/807b3c2d/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java
index ce636e2..2932581 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/HostOfferResponse.java
@@ -29,6 +29,7 @@ public class HostOfferResponse {
 
   private final Answer answer;
   private final String hostGroupName;
+  private final long hostRequestId;
   private final List<TopologyTask> tasks;
 
   public HostOfferResponse(Answer answer) {
@@ -36,12 +37,14 @@ public class HostOfferResponse {
       throw new IllegalArgumentException("For accepted response, hostgroup name and tasks must be set");
     }
     this.answer = answer;
+    this.hostRequestId = -1;
     this.hostGroupName = null;
     this.tasks = null;
   }
 
-  public HostOfferResponse(Answer answer, String hostGroupName, List<TopologyTask> tasks) {
+  public HostOfferResponse(Answer answer, long hostRequestId, String hostGroupName, List<TopologyTask> tasks) {
     this.answer = answer;
+    this.hostRequestId = hostRequestId;
     this.hostGroupName = hostGroupName;
     this.tasks = tasks;
   }
@@ -50,6 +53,10 @@ public class HostOfferResponse {
     return answer;
   }
 
+  public long getHostRequestId() {
+    return hostRequestId;
+  }
+
   //todo: for now assumes a host was added
   //todo: perhaps a topology modification object that modifies a passed in topology structure?
   public String getHostGroupName() {


Mime
View raw message