Explorar o código

AMBARI-5749. Store cluster installed state as part of the Cluster resource (Jonathan Hurley via ncole)

Nate Cole %!s(int64=11) %!d(string=hai) anos
pai
achega
db65324cf7
Modificáronse 22 ficheiros con 429 adicións e 142 borrados
  1. 70 29
      ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
  2. 34 2
      ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java
  3. 19 1
      ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java
  4. 17 14
      ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java
  5. 30 0
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
  6. 18 7
      ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterStateEntity.java
  7. 17 0
      ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
  8. 62 24
      ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
  9. 1 1
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java
  10. 43 6
      ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog161.java
  11. 1 1
      ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
  12. 1 1
      ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
  13. 1 1
      ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
  14. 1 1
      ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
  15. 1 0
      ambari-server/src/main/resources/properties.json
  16. 10 1
      ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
  17. 7 3
      ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterRequestTest.java
  18. 5 2
      ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterResponseTest.java
  19. 5 4
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
  20. 44 39
      ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java
  21. 12 1
      ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java
  22. 30 4
      ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog161Test.java

+ 70 - 29
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java

@@ -18,11 +18,29 @@
 
 package org.apache.ambari.server.controller;
 
-import com.google.gson.Gson;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Singleton;
-import com.google.inject.persist.Transactional;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_DRIVER;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_PASSWORD;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_URL;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_USERNAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_DRIVER_FILENAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JAVA_HOME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JCE_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.MYSQL_JDBC_URL;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.ORACLE_JDBC_URL;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.PACKAGE_LIST;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.REPO_INFO;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_REPO_INFO;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_NAME;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_VERSION;
+
 import java.io.File;
 import java.io.IOException;
 import java.net.InetAddress;
@@ -38,6 +56,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.DuplicateResourceException;
@@ -56,32 +75,10 @@ import org.apache.ambari.server.actionmanager.RequestFactory;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.StageFactory;
 import org.apache.ambari.server.agent.ExecutionCommand;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_DRIVER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_PASSWORD;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_URL;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.AMBARI_DB_RCA_USERNAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_DRIVER_FILENAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JAVA_HOME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JCE_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.MYSQL_JDBC_URL;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.ORACLE_JDBC_URL;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.PACKAGE_LIST;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.REPO_INFO;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_REPO_INFO;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_VERSION;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.controller.internal.RequestOperationLevel;
+import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.controller.internal.RequestStageContainer;
 import org.apache.ambari.server.controller.internal.URLStreamProvider;
 import org.apache.ambari.server.customactions.ActionDefinition;
@@ -133,6 +130,12 @@ import org.apache.http.client.utils.URIBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+
 @Singleton
 public class AmbariManagementControllerImpl implements AmbariManagementController {
 
@@ -150,7 +153,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
   private final ActionManager actionManager;
 
-  @SuppressWarnings("unused")
   private final Injector injector;
 
   private final Gson gson;
@@ -1036,7 +1038,46 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       clusters.mapHostsToCluster(
           request.getHostNames(), request.getClusterName());
     }
+    
+    // set the provisioning state of the cluster
+    if (null != request.getProvisioningState()) {
+      State provisioningState;
+      State oldProvisioningState = cluster.getProvisioningState();
+
+      provisioningState = State.valueOf(request.getProvisioningState());
+      if (provisioningState != State.INIT
+          && provisioningState != State.INSTALLED) {
+        LOG.warn(
+            "Invalid cluster provisioning state {} cannot be set on the cluster {}",
+            provisioningState, request.getClusterName());
 
+        throw new IllegalArgumentException(
+            "Invalid cluster provisioning state "
+            + provisioningState + " cannot be set on cluster "
+            + request.getClusterName());
+      }
+
+      if (provisioningState != oldProvisioningState) {
+        boolean isStateTransitionValid = State.isValidDesiredStateTransition(
+            oldProvisioningState, provisioningState);
+        
+        if (!isStateTransitionValid) {
+          LOG.warn(
+              "Invalid cluster provisioning state {} cannot be set on the cluster {} because the current state is {}",
+              provisioningState, request.getClusterName(), oldProvisioningState);
+          
+          throw new AmbariException("Invalid transition for"
+              + " cluster provisioning state" + ", clusterName="
+              + cluster.getClusterName() + ", clusterId="
+              + cluster.getClusterId() + ", currentProvisioningState="
+              + oldProvisioningState + ", newProvisioningState="
+              + provisioningState);
+        }
+      }
+      
+      cluster.setProvisioningState(provisioningState);
+    }
+    
     return null;
   }
 

+ 34 - 2
ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterRequest.java

@@ -31,17 +31,25 @@ public class ClusterRequest {
 
   private String stackVersion; // for CREATE/UPDATE
 
+  private String provisioningState; // for GET/CREATE/UPDATE
+  
   Set<String> hostNames; // CREATE/UPDATE
   
   private ConfigurationRequest config = null;
 
-  public ClusterRequest(Long clusterId, String clusterName,
+  public ClusterRequest(Long clusterId, String clusterName, 
       String stackVersion, Set<String> hostNames) {
+    this(clusterId, clusterName, null, stackVersion, hostNames);
+  }  
+  
+  public ClusterRequest(Long clusterId, String clusterName, 
+      String provisioningState, String stackVersion, Set<String> hostNames) {
     super();
     this.clusterId = clusterId;
     this.clusterName = clusterName;
+    this.provisioningState = provisioningState;
     this.stackVersion = stackVersion;
-    this.hostNames = hostNames;
+    this.hostNames = hostNames;    
   }
   
   /**
@@ -57,6 +65,29 @@ public class ClusterRequest {
   public String getClusterName() {
     return clusterName;
   }
+  
+  /**
+   * Gets whether the cluster is still initializing or has finished with its
+   * deployment requests.
+   * 
+   * @return either {@code INIT} or {@code INSTALLED} or {@code null} if not set
+   *         on the request.
+   */
+  public String getProvisioningState(){
+    return provisioningState;
+  }
+  
+  /**
+   * Sets whether the cluster is still initializing or has finished with its
+   * deployment requests.
+   * 
+   * @param provisioningState
+   *          either {@code INIT} or {@code INSTALLED}, or {@code null} if not
+   *          set on the request.
+   */
+  public void setProvisioningState(String provisioningState) {
+    this.provisioningState = provisioningState;
+  }
 
   /**
    * @return the stackVersion
@@ -116,6 +147,7 @@ public class ClusterRequest {
     sb.append("{"
         + " clusterName=" + clusterName
         + ", clusterId=" + clusterId
+        + ", provisioningState=" + provisioningState
         + ", stackVersion=" + stackVersion
         + ", hosts=[");
     if (hostNames != null) {

+ 19 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/ClusterResponse.java

@@ -22,6 +22,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.state.DesiredConfig;
+import org.apache.ambari.server.state.State;
 
 public class ClusterResponse {
 
@@ -35,13 +36,18 @@ public class ClusterResponse {
 
   private Map<String, DesiredConfig> desiredConfigs;
   
-  public ClusterResponse(Long clusterId, String clusterName,
+  private String provisioningState;
+  
+  public ClusterResponse(Long clusterId, String clusterName, State provisioningState,
       Set<String> hostNames, String desiredStackVersion) {
     super();
     this.clusterId = clusterId;
     this.clusterName = clusterName;
     this.hostNames = hostNames;
     this.desiredStackVersion = desiredStackVersion;
+    
+    if (null != provisioningState)
+      this.provisioningState = provisioningState.name();
   }
 
   /**
@@ -64,6 +70,16 @@ public class ClusterResponse {
   public Set<String> getHostNames() {
     return hostNames;
   }
+  
+  /**
+   * Gets whether the cluster is still initializing or has finished with its
+   * deployment requests.
+   * 
+   * @return either {@code INIT} or {@code INSTALLED}, never {@code null}.
+   */
+  public String getProvisioningState(){
+    return provisioningState;
+  }
 
   @Override
   public String toString() {
@@ -71,8 +87,10 @@ public class ClusterResponse {
     sb.append("{"
         + " clusterName=" + clusterName
         + ", clusterId=" + clusterId
+        + ", provisioningState=" + provisioningState
         + ", desiredStackVersion=" + desiredStackVersion
         + ", hosts=[");
+    
     if (hostNames != null) {
       int i = 0;
       for (String hostName : hostNames) {

+ 17 - 14
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterResourceProvider.java

@@ -17,7 +17,15 @@
  */
 package org.apache.ambari.server.controller.internal;
 
-import com.google.gson.Gson;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.StackAccessException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
@@ -55,14 +63,7 @@ import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigImpl;
 import org.apache.ambari.server.state.PropertyInfo;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
+import com.google.gson.Gson;
 
 /**
  * Resource provider for cluster resources.
@@ -74,11 +75,11 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
   // Clusters
   protected static final String CLUSTER_ID_PROPERTY_ID      = PropertyHelper.getPropertyId("Clusters", "cluster_id");
   protected static final String CLUSTER_NAME_PROPERTY_ID    = PropertyHelper.getPropertyId("Clusters", "cluster_name");
-  protected static final String CLUSTER_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "version");
+  protected static final String CLUSTER_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "version");  
+  protected static final String CLUSTER_PROVISIONING_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "provisioning_state");
   protected static final String CLUSTER_DESIRED_CONFIGS_PROPERTY_ID = PropertyHelper.getPropertyId("Clusters", "desired_configs");
   protected static final String BLUEPRINT_PROPERTY_ID = PropertyHelper.getPropertyId(null, "blueprint");
 
-
   private static Set<String> pkPropertyIds =
       new HashSet<String>(Arrays.asList(new String[]{CLUSTER_ID_PROPERTY_ID}));
 
@@ -182,12 +183,14 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
       LOG.debug("Found clusters matching getClusters request"
           + ", clusterResponseCount=" + responses.size());
     }
+    
     for (ClusterResponse response : responses) {
       Resource resource = new ResourceImpl(Resource.Type.Cluster);
       setResourceProperty(resource, CLUSTER_ID_PROPERTY_ID, response.getClusterId(), requestedIds);
       setResourceProperty(resource, CLUSTER_NAME_PROPERTY_ID, response.getClusterName(), requestedIds);
-      setResourceProperty(resource, CLUSTER_DESIRED_CONFIGS_PROPERTY_ID, response.getDesiredConfigs(), requestedIds);
-
+      setResourceProperty(resource, CLUSTER_PROVISIONING_STATE_PROPERTY_ID, response.getProvisioningState(), requestedIds);
+      setResourceProperty(resource, CLUSTER_DESIRED_CONFIGS_PROPERTY_ID, response.getDesiredConfigs(), requestedIds);      
+      
       resource.setProperty(CLUSTER_VERSION_PROPERTY_ID,
           response.getDesiredStackVersion());
 
@@ -276,10 +279,10 @@ public class ClusterResourceProvider extends AbstractControllerResourceProvider
     ClusterRequest cr = new ClusterRequest(
         (Long) properties.get(CLUSTER_ID_PROPERTY_ID),
         (String) properties.get(CLUSTER_NAME_PROPERTY_ID),
+        (String) properties.get(CLUSTER_PROVISIONING_STATE_PROPERTY_ID),
         (String) properties.get(CLUSTER_VERSION_PROPERTY_ID),
         null);
 
-
     ConfigurationRequest configRequest = getConfigurationRequest("Clusters", properties);
 
     if (null != configRequest)

+ 30 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java

@@ -19,6 +19,9 @@
 package org.apache.ambari.server.orm.entities;
 
 import javax.persistence.*;
+
+import org.apache.ambari.server.state.State;
+
 import java.util.Collection;
 
 import static org.apache.commons.lang.StringUtils.defaultString;
@@ -52,6 +55,11 @@ public class ClusterEntity {
       updatable = true, unique = true, length = 100)
   private String clusterName;
 
+  @Basic
+  @Enumerated(value = EnumType.STRING)
+  @Column(name = "provisioning_state", insertable = true, updatable = true)
+  private State provisioningState = State.INIT;   
+  
   @Basic
   @Column(name = "desired_cluster_state", insertable = true, updatable = true)
   private String desiredClusterState = "";
@@ -130,6 +138,28 @@ public class ClusterEntity {
   public void setDesiredStackVersion(String desiredStackVersion) {
     this.desiredStackVersion = desiredStackVersion;
   }
+  
+  /**
+   * Gets whether the cluster is still initializing or has finished with its 
+   * deployment requests.
+   * 
+   * @return either {@link State#INIT} or {@link State#INSTALLED}, 
+   * never {@code null}.
+   */
+  public State getProvisioningState(){
+    return this.provisioningState;
+  }
+  
+  /**
+   * Sets whether the cluster is still initializing or has finished with its 
+   * deployment requests.
+   * 
+   * @param provisioningState either {@link State#INIT} or 
+   * {@link State#INSTALLED}, never {@code null}. 
+   */
+  public void setProvisioningState(State provisioningState){
+    this.provisioningState = provisioningState;
+  }
 
   @Override
   public boolean equals(Object o) {

+ 18 - 7
ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterStateEntity.java

@@ -18,12 +18,22 @@
 
 package org.apache.ambari.server.orm.entities;
 
-import javax.persistence.*;
-
 import static org.apache.commons.lang.StringUtils.defaultString;
 
-@javax.persistence.Table(name = "clusterstate")
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+
+import org.apache.ambari.server.state.State;
+
 @Entity
+@Table(name = "clusterstate")
 public class ClusterStateEntity {
 
   @Id
@@ -31,8 +41,9 @@ public class ClusterStateEntity {
   private Long clusterId;
 
   @Basic
+  @Enumerated(value = EnumType.STRING)
   @Column(name = "current_cluster_state", insertable = true, updatable = true)
-  private String currentClusterState = "";
+  private State currentClusterState = State.INIT; 
 
   @Basic
   @Column(name = "current_stack_version", insertable = true, updatable = true)
@@ -50,11 +61,11 @@ public class ClusterStateEntity {
     this.clusterId = clusterId;
   }
 
-  public String getCurrentClusterState() {
-    return defaultString(currentClusterState);
+  public State getCurrentClusterState() {
+    return currentClusterState;
   }
 
-  public void setCurrentClusterState(String currentClusterState) {
+  public void setCurrentClusterState(State currentClusterState) {
     this.currentClusterState = currentClusterState;
   }
 

+ 17 - 0
ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java

@@ -101,6 +101,23 @@ public interface Cluster {
    * @param stackVersion
    */
   public void setCurrentStackVersion(StackId stackVersion) throws AmbariException;
+  
+  /**
+   * Gets whether the cluster is still initializing or has finished with its
+   * deployment requests.
+   * 
+   * @return either {@link State#INIT} or {@link State#INSTALLED}, never
+   *         {@code null}.
+   */
+  public State getProvisioningState();
+  
+  /**
+   * Sets the provisioning state of the cluster.
+   * 
+   * @param provisioningState
+   *          the provisioning state, not {@code null}.
+   */
+  public void setProvisioningState(State provisioningState);
 
   /**
    * Gets all configs that match the specified type.  Result is not the

+ 62 - 24
ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java

@@ -18,11 +18,24 @@
 
 package org.apache.ambari.server.state.cluster;
 
-import com.google.gson.Gson;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.assistedinject.Assisted;
-import com.google.inject.persist.Transactional;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import javax.persistence.RollbackException;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ServiceComponentHostNotFoundException;
 import org.apache.ambari.server.ServiceNotFoundException;
@@ -39,7 +52,6 @@ import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.ClusterStateEntity;
 import org.apache.ambari.server.orm.entities.ConfigGroupEntity;
-import org.apache.ambari.server.orm.entities.ConfigGroupHostMappingEntity;
 import org.apache.ambari.server.orm.entities.RequestScheduleEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -51,6 +63,7 @@ import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceFactory;
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.configgroup.ConfigGroup;
 import org.apache.ambari.server.state.configgroup.ConfigGroupFactory;
 import org.apache.ambari.server.state.scheduler.RequestExecution;
@@ -58,22 +71,11 @@ import org.apache.ambari.server.state.scheduler.RequestExecutionFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.persistence.RollbackException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.persist.Transactional;
 
 public class ClusterImpl implements Cluster {
 
@@ -913,8 +915,43 @@ public class ClusterImpl implements Cluster {
     } finally {
       clusterGlobalLock.readLock().unlock();
     }
+  }
+  
+  @Override
+  public State getProvisioningState() {    
+    clusterGlobalLock.readLock().lock();
+    try {
+      readLock.lock();
+      State provisioningState = null;
+      try {
+        provisioningState = clusterEntity.getProvisioningState();
+        
+        if( null == provisioningState )
+          provisioningState = State.INIT;
+        
+        return provisioningState;
+      } finally {
+        readLock.unlock();
+      }
+    } finally {
+      clusterGlobalLock.readLock().unlock();
+    }
+  }  
 
-
+  @Override
+  public void setProvisioningState(State provisioningState) {
+    clusterGlobalLock.readLock().lock();
+    try {
+      writeLock.lock();
+      try {
+        clusterEntity.setProvisioningState(provisioningState);
+        clusterDAO.merge(clusterEntity);        
+      } finally {
+        writeLock.unlock();
+      }
+    } finally {
+      clusterGlobalLock.readLock().unlock();
+    }
   }
 
   @Override
@@ -1047,7 +1084,8 @@ public class ClusterImpl implements Cluster {
     try {
       readWriteLock.readLock().lock();
       try {
-        ClusterResponse r = new ClusterResponse(getClusterId(), getClusterName(),
+        ClusterResponse r = new ClusterResponse(getClusterId(), 
+          getClusterName(), getProvisioningState(), 
           clusters.getHostsForCluster(getClusterName()).keySet(),
           getDesiredStackVersion().getStackId());
 

+ 1 - 1
ambari-server/src/main/java/org/apache/ambari/server/upgrade/SchemaUpgradeHelper.java

@@ -184,7 +184,7 @@ public class SchemaUpgradeHelper {
   }
 
   public void executeDMLUpdates(List<UpgradeCatalog> upgradeCatalogs) throws AmbariException {
-    LOG.info("Execution DML changes.");
+    LOG.info("Executing DML changes.");
 
     if (upgradeCatalogs != null && !upgradeCatalogs.isEmpty()) {
       for (UpgradeCatalog upgradeCatalog : upgradeCatalogs) {

+ 43 - 6
ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog161.java

@@ -18,22 +18,35 @@
 
 package org.apache.ambari.server.upgrade;
 
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.configuration.Configuration;
-
 import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 
-import static org.apache.ambari.server.orm.DBAccessor.DBColumnInfo;
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.orm.DBAccessor.DBColumnInfo;
+import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.state.State;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
 
 /**
  * Upgrade catalog for version 1.6.1.
  */
 public class UpgradeCatalog161 extends AbstractUpgradeCatalog {
 
+  /**
+   * Logger.
+   */
+  private static final Logger LOG = LoggerFactory.getLogger
+      (UpgradeCatalog161.class);
+  
   // ----- Constructors ------------------------------------------------------
 
   @Inject
@@ -64,6 +77,9 @@ public class UpgradeCatalog161 extends AbstractUpgradeCatalog {
     // Add constraints
     dbAccessor.addFKConstraint("requestoperationlevel", "FK_req_op_level_req_id",
             "request_id", "request", "request_id", true);
+    
+    // Clusters
+    dbAccessor.addColumn("clusters", new DBColumnInfo("provisioning_state", String.class, 255, State.INIT.name(), false));    
   }
 
 
@@ -77,9 +93,30 @@ public class UpgradeCatalog161 extends AbstractUpgradeCatalog {
     if (Configuration.ORACLE_DB_NAME.equals(dbType) || Configuration.MYSQL_DB_NAME.equals(dbType)) {
       valueColumnName = "value";
     }
+    
     //add new sequences for operation level
     dbAccessor.executeQuery("INSERT INTO ambari_sequences(sequence_name, " + valueColumnName + ") " +
             "VALUES('operation_level_id_seq', 1)", true);
+    
+    // upgrade cluster provision state
+    executeInTransaction(new Runnable() { 
+      @Override
+      public void run() {
+        // it should be safe to bulk update the current cluster state since 
+        // this field is not currently used and since all clusters stored in
+        // the database must (at this point) be installed
+        final EntityManager em = getEntityManagerProvider().get();        
+        final TypedQuery<ClusterEntity> query = em.createQuery(
+            "UPDATE ClusterEntity SET provisioningState = :provisioningState", 
+            ClusterEntity.class);
+
+        query.setParameter("provisioningState", State.INSTALLED);
+        final int updatedClusterProvisionedStateCount = query.executeUpdate();
+        
+        LOG.info("Updated {} cluster provisioning states to {}",
+            updatedClusterProvisionedStateCount, State.INSTALLED);
+      }
+    });
   }
 
   @Override

+ 1 - 1
ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql

@@ -26,7 +26,7 @@ delimiter ;
 
 # USE @schema;
 
-CREATE TABLE clusters (cluster_id BIGINT NOT NULL, cluster_info VARCHAR(255) NOT NULL, cluster_name VARCHAR(100) NOT NULL UNIQUE, desired_cluster_state VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id));
+CREATE TABLE clusters (cluster_id BIGINT NOT NULL, cluster_info VARCHAR(255) NOT NULL, cluster_name VARCHAR(100) NOT NULL UNIQUE, provisioning_state VARCHAR(255) NOT NULL DEFAULT 'INIT', desired_cluster_state VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id));
 CREATE TABLE clusterconfig (version_tag VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, config_data LONGTEXT NOT NULL, create_timestamp BIGINT NOT NULL, PRIMARY KEY (version_tag, type_name, cluster_id));
 CREATE TABLE clusterservices (service_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, service_enabled INTEGER NOT NULL, PRIMARY KEY (service_name, cluster_id));
 CREATE TABLE clusterstate (cluster_id BIGINT NOT NULL, current_cluster_state VARCHAR(255) NOT NULL, current_stack_version VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id));

+ 1 - 1
ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql

@@ -16,7 +16,7 @@
 -- limitations under the License.
 --
 
-CREATE TABLE clusters (cluster_id NUMBER(19) NOT NULL, cluster_info VARCHAR2(255) NULL, cluster_name VARCHAR2(100) NOT NULL UNIQUE, desired_cluster_state VARCHAR2(255) NULL, desired_stack_version VARCHAR2(255) NULL, PRIMARY KEY (cluster_id));
+CREATE TABLE clusters (cluster_id NUMBER(19) NOT NULL, cluster_info VARCHAR2(255) NULL, cluster_name VARCHAR2(100) NOT NULL UNIQUE, provisioning_state VARCHAR2(255) NOT NULL DEFAULT 'INIT', desired_cluster_state VARCHAR2(255) NULL, desired_stack_version VARCHAR2(255) NULL, PRIMARY KEY (cluster_id));
 CREATE TABLE clusterconfig (version_tag VARCHAR2(255) NOT NULL, type_name VARCHAR2(255) NOT NULL, cluster_id NUMBER(19) NOT NULL, config_data CLOB NOT NULL, create_timestamp NUMBER(19) NOT NULL, PRIMARY KEY (version_tag, type_name, cluster_id));
 CREATE TABLE clusterservices (service_name VARCHAR2(255) NOT NULL, cluster_id NUMBER(19) NOT NULL, service_enabled NUMBER(10) NOT NULL, PRIMARY KEY (service_name, cluster_id));
 CREATE TABLE clusterstate (cluster_id NUMBER(19) NOT NULL, current_cluster_state VARCHAR2(255) NULL, current_stack_version VARCHAR2(255) NULL, PRIMARY KEY (cluster_id));

+ 1 - 1
ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql

@@ -17,7 +17,7 @@
 --
 
 ------create tables ang grant privileges to db user---------
-CREATE TABLE clusters (cluster_id BIGINT NOT NULL, cluster_info VARCHAR(255) NOT NULL, cluster_name VARCHAR(100) NOT NULL UNIQUE, desired_cluster_state VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id));
+CREATE TABLE clusters (cluster_id BIGINT NOT NULL, cluster_info VARCHAR(255) NOT NULL, cluster_name VARCHAR(100) NOT NULL UNIQUE, provisioning_state VARCHAR(255) NOT NULL DEFAULT 'INIT', desired_cluster_state VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id));
 
 CREATE TABLE clusterconfig (version_tag VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, config_data VARCHAR(32000) NOT NULL, create_timestamp BIGINT NOT NULL, PRIMARY KEY (cluster_id, type_name, version_tag));
 

+ 1 - 1
ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql

@@ -28,7 +28,7 @@ ALTER SCHEMA ambari OWNER TO :username;
 ALTER ROLE :username SET search_path TO 'ambari';
 
 ------create tables ang grant privileges to db user---------
-CREATE TABLE ambari.clusters (cluster_id BIGINT NOT NULL, cluster_info VARCHAR(255) NOT NULL, cluster_name VARCHAR(100) NOT NULL UNIQUE, desired_cluster_state VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id));
+CREATE TABLE ambari.clusters (cluster_id BIGINT NOT NULL, cluster_info VARCHAR(255) NOT NULL, cluster_name VARCHAR(100) NOT NULL UNIQUE, provisioning_state VARCHAR(255) NOT NULL DEFAULT 'INIT', desired_cluster_state VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id));
 GRANT ALL PRIVILEGES ON TABLE ambari.clusters TO :username;
 
 CREATE TABLE ambari.clusterconfig (version_tag VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, config_data VARCHAR(32000) NOT NULL, create_timestamp BIGINT NOT NULL, PRIMARY KEY (cluster_id, type_name, version_tag));

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

@@ -2,6 +2,7 @@
     "Cluster":[
         "Clusters/cluster_id",
         "Clusters/cluster_name",
+        "Clusters/provisioning_state",
         "Clusters/version",
         "Clusters/state",
         "Clusters/desired_configs",

+ 10 - 1
ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java

@@ -227,7 +227,7 @@ public class AmbariManagementControllerTest {
   }
 
   private void createCluster(String clusterName) throws AmbariException {
-    ClusterRequest r = new ClusterRequest(null, clusterName, "HDP-0.1", null);
+    ClusterRequest r = new ClusterRequest(null, clusterName, State.INSTALLED.name(), "HDP-0.1", null);
     controller.createCluster(r);
   }
 
@@ -509,6 +509,15 @@ public class AmbariManagementControllerTest {
     } catch (Exception e) {
       // Expected
     }
+    
+    r.setStackVersion("HDP-1.0.1");
+    r.setProvisioningState(State.INSTALLING.name());
+    try {
+      controller.createCluster(r);
+     fail("Expected create cluster for invalid request - invalid provisioning state");
+    } catch (Exception e) {
+      // Expected
+    }    
   }
 
   @Test

+ 7 - 3
ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterRequestTest.java

@@ -22,6 +22,7 @@ import java.util.HashSet;
 import java.util.Set;
 
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.State;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -31,16 +32,18 @@ public class ClusterRequestTest {
   public void testBasicGetAndSet() {
     Long clusterId = new Long(10);
     String clusterName = "foo";
+    String provisioningState = State.INIT.name();
     StackId stackVersion = new StackId("HDP-1.0.1");
     Set<String> hostNames = new HashSet<String>();
     hostNames.add("h1");
 
     ClusterRequest r1 =
-        new ClusterRequest(clusterId, clusterName,
+        new ClusterRequest(clusterId, clusterName, provisioningState,
             stackVersion.getStackId(), hostNames);
 
     Assert.assertEquals(clusterId, r1.getClusterId());
     Assert.assertEquals(clusterName, r1.getClusterName());
+    Assert.assertEquals(provisioningState, r1.getProvisioningState());
     Assert.assertEquals(stackVersion.getStackId(),
         r1.getStackVersion());
     Assert.assertArrayEquals(hostNames.toArray(), r1.getHostNames().toArray());
@@ -49,19 +52,20 @@ public class ClusterRequestTest {
     r1.setHostNames(hostNames);
     r1.setClusterName("foo1");
     r1.setStackVersion("HDP-1.0.2");
+    r1.setProvisioningState(State.INSTALLED.name());
 
     hostNames.add("h2");
 
     Assert.assertEquals(clusterId, r1.getClusterId());
     Assert.assertEquals("foo1", r1.getClusterName());
+    Assert.assertEquals(State.INSTALLED.name(), r1.getProvisioningState());
     Assert.assertEquals("HDP-1.0.2", r1.getStackVersion());
     Assert.assertArrayEquals(hostNames.toArray(), r1.getHostNames().toArray());
-
   }
 
   @Test
   public void testToString() {
-    ClusterRequest r1 = new ClusterRequest(null, null, null, null);
+    ClusterRequest r1 = new ClusterRequest(null, null, null, null, null);
     r1.toString();
   }
 

+ 5 - 2
ambari-server/src/test/java/org/apache/ambari/server/controller/ClusterResponseTest.java

@@ -21,6 +21,7 @@ package org.apache.ambari.server.controller;
 import java.util.HashSet;
 import java.util.Set;
 
+import org.apache.ambari.server.state.State;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -30,21 +31,23 @@ public class ClusterResponseTest {
   public void testBasicGetAndSet() {
     Long clusterId = new Long(10);
     String clusterName = "foo";
+    State provisioningState = State.INSTALLED;
     Set<String> hostNames = new HashSet<String>();
     hostNames.add("h1");
 
     ClusterResponse r1 =
-        new ClusterResponse(clusterId, clusterName, hostNames, "bar");
+        new ClusterResponse(clusterId, clusterName, provisioningState, hostNames, "bar");
     
     Assert.assertEquals(clusterId, r1.getClusterId());
     Assert.assertEquals(clusterName, r1.getClusterName());
+    Assert.assertEquals(provisioningState.name(), r1.getProvisioningState());
     Assert.assertArrayEquals(hostNames.toArray(), r1.getHostNames().toArray());
     Assert.assertEquals("bar", r1.getDesiredStackVersion());
   }
 
   @Test
   public void testToString() {
-    ClusterResponse r = new ClusterResponse(null, null, null, null);
+    ClusterResponse r = new ClusterResponse(null, null, null, null, null);
     r.toString();
   }
 }

+ 5 - 4
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java

@@ -47,6 +47,7 @@ import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.state.State;
 import org.easymock.EasyMock;
 import org.easymock.IArgumentMatcher;
 import org.junit.Assert;
@@ -256,9 +257,9 @@ public class AbstractResourceProviderTest {
     }
 
     public static Set<ClusterRequest> getClusterRequestSet(
-        Long clusterId, String clusterName, String stackVersion, Set<String> hostNames)
+        Long clusterId, String clusterName, String provisioningState, String stackVersion, Set<String> hostNames)
     {
-      EasyMock.reportMatcher(new ClusterRequestSetMatcher(clusterId, clusterName, stackVersion, hostNames));
+      EasyMock.reportMatcher(new ClusterRequestSetMatcher(clusterId, clusterName, provisioningState, stackVersion, hostNames));
       return null;
     }
 
@@ -334,8 +335,8 @@ public class AbstractResourceProviderTest {
    */
   public static class ClusterRequestSetMatcher extends ClusterRequest implements IArgumentMatcher {
 
-    public ClusterRequestSetMatcher(Long clusterId, String clusterName, String stackVersion, Set<String> hostNames) {
-      super(clusterId, clusterName, stackVersion, hostNames);
+    public ClusterRequestSetMatcher(Long clusterId, String clusterName, String provisioningState, String stackVersion, Set<String> hostNames) {
+      super(clusterId, clusterName, provisioningState, stackVersion, hostNames);
     }
 
     @Override

+ 44 - 39
ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ClusterResourceProviderTest.java

@@ -18,7 +18,32 @@
 
 package org.apache.ambari.server.controller.internal;
 
-import com.google.gson.Gson;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.api.services.PersistKeyValueImpl;
 import org.apache.ambari.server.api.services.PersistKeyValueService;
@@ -34,6 +59,8 @@ import org.apache.ambari.server.controller.StackServiceComponentRequest;
 import org.apache.ambari.server.controller.StackServiceComponentResponse;
 import org.apache.ambari.server.controller.StackServiceRequest;
 import org.apache.ambari.server.controller.StackServiceResponse;
+import org.apache.ambari.server.controller.internal.ClusterResourceProvider.HostGroup;
+import org.apache.ambari.server.controller.internal.ClusterResourceProvider.PropertyUpdater;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.RequestStatus;
@@ -47,38 +74,15 @@ import org.apache.ambari.server.orm.entities.BlueprintEntity;
 import org.apache.ambari.server.orm.entities.HostGroupComponentEntity;
 import org.apache.ambari.server.orm.entities.HostGroupConfigEntity;
 import org.apache.ambari.server.orm.entities.HostGroupEntity;
-import org.apache.commons.collections.CollectionUtils;
 import org.apache.ambari.server.state.PropertyInfo;
+import org.apache.ambari.server.state.State;
+import org.apache.commons.collections.CollectionUtils;
 import org.easymock.Capture;
 import org.easymock.EasyMock;
 import org.junit.Assert;
 import org.junit.Test;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.createMockBuilder;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import org.apache.ambari.server.controller.internal.ClusterResourceProvider.HostGroup;
-import org.apache.ambari.server.controller.internal.ClusterResourceProvider.PropertyUpdater;
+
+import com.google.gson.Gson;
 
 /**
  * ClusterResourceProvider tests.
@@ -1880,17 +1884,17 @@ public class ClusterResourceProviderTest {
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
 
     Set<ClusterResponse> allResponse = new HashSet<ClusterResponse>();
-    allResponse.add(new ClusterResponse(100L, "Cluster100", null, null));
-    allResponse.add(new ClusterResponse(101L, "Cluster101", null, null));
-    allResponse.add(new ClusterResponse(102L, "Cluster102", null, null));
-    allResponse.add(new ClusterResponse(103L, "Cluster103", null, null));
-    allResponse.add(new ClusterResponse(104L, "Cluster104", null, null));
+    allResponse.add(new ClusterResponse(100L, "Cluster100", State.INSTALLED, null, null));
+    allResponse.add(new ClusterResponse(101L, "Cluster101", State.INSTALLED, null, null));
+    allResponse.add(new ClusterResponse(102L, "Cluster102", State.INSTALLED, null, null));
+    allResponse.add(new ClusterResponse(103L, "Cluster103", State.INSTALLED, null, null));
+    allResponse.add(new ClusterResponse(104L, "Cluster104", State.INSTALLED, null, null));
 
     Set<ClusterResponse> nameResponse = new HashSet<ClusterResponse>();
-    nameResponse.add(new ClusterResponse(102L, "Cluster102", null, null));
+    nameResponse.add(new ClusterResponse(102L, "Cluster102", State.INSTALLED, null, null));
 
     Set<ClusterResponse> idResponse = new HashSet<ClusterResponse>();
-    idResponse.add(new ClusterResponse(103L, "Cluster103", null, null));
+    idResponse.add(new ClusterResponse(103L, "Cluster103", State.INSTALLED, null, null));
 
     // set expectations
     expect(managementController.getClusters(EasyMock.<Set<ClusterRequest>>anyObject())).andReturn(allResponse).once();
@@ -1959,7 +1963,7 @@ public class ClusterResourceProviderTest {
     RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
 
     Set<ClusterResponse> nameResponse = new HashSet<ClusterResponse>();
-    nameResponse.add(new ClusterResponse(102L, "Cluster102", null, null));
+    nameResponse.add(new ClusterResponse(102L, "Cluster102", State.INIT, null, null));
 
     Map<String, String> mapRequestProps = new HashMap<String, String>();
     mapRequestProps.put("context", "Called from a test");
@@ -1967,10 +1971,11 @@ public class ClusterResourceProviderTest {
     // set expectations
     expect(managementController.getClusters(EasyMock.<Set<ClusterRequest>>anyObject())).andReturn(nameResponse).once();
     expect(managementController.updateClusters(
-        AbstractResourceProviderTest.Matcher.getClusterRequestSet(102L, "Cluster102", "HDP-0.1", null), eq(mapRequestProps))).
+        AbstractResourceProviderTest.Matcher.getClusterRequestSet(102L, "Cluster102", State.INSTALLED.name(), "HDP-0.1", null), eq(mapRequestProps))).
         andReturn(response).once();
+    
     expect(managementController.updateClusters(
-        AbstractResourceProviderTest.Matcher.getClusterRequestSet(103L, null, "HDP-0.1", null), eq(mapRequestProps))).
+        AbstractResourceProviderTest.Matcher.getClusterRequestSet(103L, null, null, "HDP-0.1", null), eq(mapRequestProps))).
         andReturn(response).once();
 
     // replay
@@ -2020,7 +2025,7 @@ public class ClusterResourceProviderTest {
     RequestStatusResponse response = createNiceMock(RequestStatusResponse.class);
 
     Set<ClusterResponse> nameResponse = new HashSet<ClusterResponse>();
-    nameResponse.add(new ClusterResponse(100L, "Cluster100", null, null));
+    nameResponse.add(new ClusterResponse(100L, "Cluster100", State.INSTALLED, null, null));
 
     Map<String, String> mapRequestProps = new HashMap<String, String>();
     mapRequestProps.put("context", "Called from a test");

+ 12 - 1
ambari-server/src/test/java/org/apache/ambari/server/state/cluster/ClusterTest.java

@@ -510,6 +510,17 @@ public class ClusterTest {
 
     assertTrue(configs.containsKey("h1"));
     assertEquals(1, configs.get("h1").size());
-
   }
+  
+  @Test
+  public void testProvisioningState() throws AmbariException {
+    c1.setProvisioningState(State.INIT);
+    Assert.assertEquals(State.INIT,
+        c1.getProvisioningState());
+    
+    c1.setProvisioningState(State.INSTALLED);
+    Assert.assertEquals(State.INSTALLED,
+        c1.getProvisioningState());    
+  }
+
 }

+ 30 - 4
ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog161Test.java

@@ -22,8 +22,10 @@ import com.google.inject.Binder;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Module;
+
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.state.State;
 import org.easymock.Capture;
 import org.junit.Assert;
 import org.junit.Test;
@@ -31,6 +33,7 @@ import org.junit.Test;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.sql.SQLException;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -43,6 +46,7 @@ import static org.easymock.EasyMock.createMockBuilder;
 import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 
@@ -56,10 +60,12 @@ public class UpgradeCatalog161Test {
 
     final DBAccessor dbAccessor = createNiceMock(DBAccessor.class);
     Configuration configuration = createNiceMock(Configuration.class);
-    Capture<List<DBAccessor.DBColumnInfo>> operationLevelEntitycolumnCapture = new Capture<List<DBAccessor.DBColumnInfo>>();
-
     expect(configuration.getDatabaseUrl()).andReturn(Configuration.JDBC_IN_MEMORY_URL).anyTimes();
 
+    Capture<DBAccessor.DBColumnInfo> provisioningStateColumnCapture = new Capture<DBAccessor.DBColumnInfo>();
+    Capture<List<DBAccessor.DBColumnInfo>> operationLevelEntitycolumnCapture = new Capture<List<DBAccessor.DBColumnInfo>>();
+    
+    setClustersConfigExpectations(dbAccessor, provisioningStateColumnCapture);    
     setOperationLevelEntityConfigExpectations(dbAccessor, operationLevelEntitycolumnCapture);
 
     replay(dbAccessor, configuration);
@@ -72,6 +78,7 @@ public class UpgradeCatalog161Test {
     upgradeCatalog.executeDDLUpdates();
     verify(dbAccessor, configuration);
 
+    assertClusterColumns(provisioningStateColumnCapture);
     assertOperationLevelEntityColumns(operationLevelEntitycolumnCapture);
   }
 
@@ -84,11 +91,15 @@ public class UpgradeCatalog161Test {
     Method m = AbstractUpgradeCatalog.class.getDeclaredMethod
       ("updateConfigurationProperties", String.class, Map.class, boolean.class);
 
-    UpgradeCatalog161 upgradeCatalog = createMockBuilder(UpgradeCatalog161.class)
+    UpgradeCatalog160 upgradeCatalog = createMockBuilder(UpgradeCatalog160.class)
       .addMockedMethod(m).createMock();
 
     expect(configuration.getDatabaseUrl()).andReturn(Configuration.JDBC_IN_MEMORY_URL).anyTimes();
 
+    upgradeCatalog.updateConfigurationProperties("global",
+      Collections.singletonMap("jobhistory_heapsize", "900"), false);
+    expectLastCall();
+
     replay(upgradeCatalog, dbAccessor, configuration);
 
     Class<?> c = AbstractUpgradeCatalog.class;
@@ -190,7 +201,22 @@ public class UpgradeCatalog161Test {
     assertEquals(String.class, column.getType());
     assertNull(column.getDefaultValue());
     assertTrue(column.isNullable());
-
   }
 
+  private void setClustersConfigExpectations(DBAccessor dbAccessor,
+      Capture<DBAccessor.DBColumnInfo> provisioningStateColumnCapture) throws SQLException {
+
+      dbAccessor.addColumn(eq("clusters"),
+        capture(provisioningStateColumnCapture));
+    }
+  
+  private void assertClusterColumns(
+      Capture<DBAccessor.DBColumnInfo> provisiontStateColumnCapture) {
+      DBAccessor.DBColumnInfo column = provisiontStateColumnCapture.getValue();
+      assertEquals("provisioning_state", column.getName());
+      assertEquals(255, (int) column.getLength());
+      assertEquals(String.class, column.getType());
+      assertEquals(State.INIT.name(), column.getDefaultValue());
+      assertFalse(column.isNullable());
+    }  
 }