ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jonathanhur...@apache.org
Subject [7/8] ambari git commit: AMBARI-10511 - Use Stack Table For Entity Relationships (jonathanhurley)
Date Thu, 16 Apr 2015 14:37:30 GMT
http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
index 01b9c03..5181a0d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
@@ -48,15 +48,14 @@ import org.apache.ambari.server.state.RepositoryVersionState;
 @NamedQueries({
     @NamedQuery(name = "clusterVersionByClusterAndStackAndVersion", query =
         "SELECT clusterVersion FROM ClusterVersionEntity clusterVersion JOIN clusterVersion.clusterEntity cluster " +
-        "WHERE cluster.clusterName=:clusterName AND clusterVersion.repositoryVersion.stack=:stack AND clusterVersion.repositoryVersion.version=:version"),
+        "WHERE cluster.clusterName=:clusterName AND clusterVersion.repositoryVersion.stack.stackName=:stackName AND clusterVersion.repositoryVersion.stack.stackVersion=:stackVersion AND clusterVersion.repositoryVersion.version=:version"),
     @NamedQuery(name = "clusterVersionByClusterAndState", query =
         "SELECT clusterVersion FROM ClusterVersionEntity clusterVersion JOIN clusterVersion.clusterEntity cluster " +
         "WHERE cluster.clusterName=:clusterName AND clusterVersion.state=:state"),
     @NamedQuery(name = "clusterVersionByCluster", query =
         "SELECT clusterVersion FROM ClusterVersionEntity clusterVersion JOIN clusterVersion.clusterEntity cluster " +
         "WHERE cluster.clusterName=:clusterName"),
-    @NamedQuery(name = "clusterVersionByStackVersion",
-        query = "SELECT clusterVersion FROM ClusterVersionEntity clusterVersion WHERE clusterVersion.repositoryVersion.stack=:stack AND clusterVersion.repositoryVersion.version=:version"),
+    @NamedQuery(name = "clusterVersionByStackVersion", query = "SELECT clusterVersion FROM ClusterVersionEntity clusterVersion WHERE clusterVersion.repositoryVersion.stack.stackName=:stackName AND clusterVersion.repositoryVersion.stack.stackVersion=:stackVersion AND clusterVersion.repositoryVersion.version=:version"),
 })
 public class ClusterVersionEntity {
 
@@ -107,9 +106,9 @@ public class ClusterVersionEntity {
    * @param userName User who performed the action
    */
   public ClusterVersionEntity(ClusterEntity cluster, RepositoryVersionEntity repositoryVersion, RepositoryVersionState state, long startTime, String userName) {
-    this.clusterId = cluster.getClusterId();
+    clusterId = cluster.getClusterId();
     this.repositoryVersion = repositoryVersion;
-    this.clusterEntity = cluster;
+    clusterEntity = cluster;
     this.state = state;
     this.startTime = startTime;
     this.userName = userName;
@@ -192,13 +191,13 @@ public class ClusterVersionEntity {
 
     ClusterVersionEntity that = (ClusterVersionEntity) o;
 
-    if (this.id != that.id
-        || this.clusterId != that.clusterId
-        || !this.repositoryVersion.equals(that.repositoryVersion)
-        || !this.state.equals(that.state)
-        || !this.startTime.equals(that.startTime)
-        || !this.endTime.equals(that.endTime)
-        || !this.userName.equals(that.userName)) {
+    if (id != that.id
+        || clusterId != that.clusterId
+        || !repositoryVersion.equals(that.repositoryVersion)
+        || !state.equals(that.state)
+        || !startTime.equals(that.startTime)
+        || !endTime.equals(that.endTime)
+        || !userName.equals(that.userName)) {
       return false;
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
index 7f0b19d..570c84b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
@@ -29,10 +29,11 @@ import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.JoinColumns;
 import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
 
-import org.apache.ambari.server.state.SecurityState;
 import org.apache.ambari.server.state.HostComponentAdminState;
 import org.apache.ambari.server.state.MaintenanceState;
+import org.apache.ambari.server.state.SecurityState;
 import org.apache.ambari.server.state.State;
 
 @javax.persistence.IdClass(HostComponentDesiredStateEntityPK.class)
@@ -66,9 +67,12 @@ public class HostComponentDesiredStateEntity {
   @Enumerated(value = EnumType.STRING)
   private SecurityState securityState = SecurityState.UNSECURED;
 
-  @Basic
-  @Column(name = "desired_stack_version", insertable = true, updatable = true)
-  private String desiredStackVersion = "";
+  /**
+   * Unidirectional one-to-one association to {@link StackEntity}
+   */
+  @OneToOne
+  @JoinColumn(name = "desired_stack_id", unique = false, nullable = false)
+  private StackEntity desiredStack;
 
   @Enumerated(value = EnumType.STRING)
   @Column(name = "admin_state", nullable = true, insertable = true, updatable = true)
@@ -84,7 +88,7 @@ public class HostComponentDesiredStateEntity {
   @ManyToOne
   @JoinColumn(name = "host_id", referencedColumnName = "host_id", nullable = false)
   private HostEntity hostEntity;
-  
+
   @Enumerated(value = EnumType.STRING)
   @Column(name="maintenance_state", nullable = false, insertable = true, updatable = true)
   private MaintenanceState maintenanceState = MaintenanceState.OFF;
@@ -137,45 +141,65 @@ public class HostComponentDesiredStateEntity {
     this.securityState = securityState;
   }
 
-  public String getDesiredStackVersion() {
-    return defaultString(desiredStackVersion);
+  public StackEntity getDesiredStack() {
+    return desiredStack;
   }
 
-  public void setDesiredStackVersion(String desiredStackVersion) {
-    this.desiredStackVersion = desiredStackVersion;
+  public void setDesiredStack(StackEntity desiredStack) {
+    this.desiredStack = desiredStack;
   }
 
-
   public HostComponentAdminState getAdminState() {
     return adminState;
   }
 
   public void setAdminState(HostComponentAdminState attribute) {
-    this.adminState = attribute;
+    adminState = attribute;
   }
-  
+
   public MaintenanceState getMaintenanceState() {
     return maintenanceState;
   }
-  
+
   public void setMaintenanceState(MaintenanceState state) {
     maintenanceState = state;
   }
 
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     HostComponentDesiredStateEntity that = (HostComponentDesiredStateEntity) o;
 
-    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) return false;
-    if (componentName != null ? !componentName.equals(that.componentName) : that.componentName != null) return false;
-    if (desiredStackVersion != null ? !desiredStackVersion.equals(that.desiredStackVersion) : that.desiredStackVersion != null)
+    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) {
+      return false;
+    }
+
+    if (componentName != null ? !componentName.equals(that.componentName) : that.componentName != null) {
+      return false;
+    }
+
+    if (desiredStack != null ? !desiredStack.equals(that.desiredStack)
+        : that.desiredStack != null) {
+      return false;
+    }
+
+    if (desiredState != null ? !desiredState.equals(that.desiredState) : that.desiredState != null) {
+      return false;
+    }
+
+    if (hostEntity != null ? !hostEntity.equals(that.hostEntity) : that.hostEntity != null) {
+      return false;
+    }
+
+    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) {
       return false;
-    if (desiredState != null ? !desiredState.equals(that.desiredState) : that.desiredState != null) return false;
-    if (hostEntity != null ? !hostEntity.equals(that.hostEntity) : that.hostEntity != null) return false;
-    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
+    }
 
     return true;
   }
@@ -186,7 +210,7 @@ public class HostComponentDesiredStateEntity {
     result = 31 * result + (hostEntity != null ? hostEntity.hashCode() : 0);
     result = 31 * result + (componentName != null ? componentName.hashCode() : 0);
     result = 31 * result + (desiredState != null ? desiredState.hashCode() : 0);
-    result = 31 * result + (desiredStackVersion != null ? desiredStackVersion.hashCode() : 0);
+    result = 31 * result + (desiredStack != null ? desiredStack.hashCode() : 0);
     result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
     return result;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
index 4463366..dabe98b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
@@ -18,14 +18,25 @@
 
 package org.apache.ambari.server.orm.entities;
 
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+
 import org.apache.ambari.server.state.SecurityState;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.UpgradeState;
 
-import javax.persistence.*;
-
-import static org.apache.commons.lang.StringUtils.defaultString;
-
 @IdClass(HostComponentStateEntityPK.class)
 @Table(name = "hostcomponentstate")
 @Entity
@@ -67,9 +78,12 @@ public class HostComponentStateEntity {
   @Column(name = "security_state", nullable = false, insertable = true, updatable = true)
   private SecurityState securityState = SecurityState.UNSECURED;
 
-  @Basic
-  @Column(name = "current_stack_version", nullable = false, insertable = true, updatable = true)
-  private String currentStackVersion;
+  /**
+   * Unidirectional one-to-one association to {@link StackEntity}
+   */
+  @OneToOne
+  @JoinColumn(name = "current_stack_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private StackEntity currentStack;
 
   @ManyToOne(cascade = CascadeType.PERSIST)
   @JoinColumns({
@@ -99,7 +113,7 @@ public class HostComponentStateEntity {
   }
 
   public String getHostName() {
-    return this.hostEntity.getHostName();
+    return hostEntity.getHostName();
   }
 
   public Long getHostId() {
@@ -138,12 +152,12 @@ public class HostComponentStateEntity {
     this.upgradeState = upgradeState;
   }
 
-  public String getCurrentStackVersion() {
-    return currentStackVersion;
+  public StackEntity getCurrentStack() {
+    return currentStack;
   }
 
-  public void setCurrentStackVersion(String currentStackVersion) {
-    this.currentStackVersion = currentStackVersion;
+  public void setCurrentStack(StackEntity currentStack) {
+    this.currentStack = currentStack;
   }
 
   public String getVersion() {
@@ -156,20 +170,40 @@ public class HostComponentStateEntity {
 
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     HostComponentStateEntity that = (HostComponentStateEntity) o;
 
-    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) return false;
-    if (componentName != null ? !componentName.equals(that.componentName) : that.componentName != null) return false;
-    if (currentStackVersion != null ? !currentStackVersion.equals(that.currentStackVersion) : that.currentStackVersion != null)
+    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) {
+      return false;
+    }
+    if (componentName != null ? !componentName.equals(that.componentName) : that.componentName != null) {
+      return false;
+    }
+    if (currentStack != null ? !currentStack.equals(that.currentStack)
+        : that.currentStack != null) {
+      return false;
+    }
+    if (currentState != null ? !currentState.equals(that.currentState) : that.currentState != null) {
+      return false;
+    }
+    if (upgradeState != null ? !upgradeState.equals(that.upgradeState) : that.upgradeState != null) {
+      return false;
+    }
+    if (hostEntity != null ? !hostEntity.equals(that.hostEntity) : that.hostEntity != null) {
+      return false;
+    }
+    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) {
+      return false;
+    }
+    if (version != null ? !version.equals(that.version) : that.version != null) {
       return false;
-    if (currentState != null ? !currentState.equals(that.currentState) : that.currentState != null) return false;
-    if (upgradeState != null ? !upgradeState.equals(that.upgradeState) : that.upgradeState != null) return false;
-    if (hostEntity != null ? !hostEntity.equals(that.hostEntity) : that.hostEntity != null) return false;
-    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
-    if (version != null ? !version.equals(that.version) : that.version != null) return false;
+    }
 
     return true;
   }
@@ -181,7 +215,7 @@ public class HostComponentStateEntity {
     result = 31 * result + (componentName != null ? componentName.hashCode() : 0);
     result = 31 * result + (currentState != null ? currentState.hashCode() : 0);
     result = 31 * result + (upgradeState != null ? upgradeState.hashCode() : 0);
-    result = 31 * result + (currentStackVersion != null ? currentStackVersion.hashCode() : 0);
+    result = 31 * result + (currentStack != null ? currentStack.hashCode() : 0);
     result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
     result = 31 * result + (version != null ? version.hashCode() : 0);
     return result;

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java
index a811c16..c329f24 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostEntity.java
@@ -18,6 +18,11 @@
 
 package org.apache.ambari.server.orm.entities;
 
+import static org.apache.commons.lang.StringUtils.defaultString;
+
+import java.util.Collection;
+import java.util.Collections;
+
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -35,10 +40,6 @@ import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.TableGenerator;
-import java.util.Collection;
-import java.util.Collections;
-
-import static org.apache.commons.lang.StringUtils.defaultString;
 
 @javax.persistence.Table(name = "hosts")
 @Entity
@@ -138,7 +139,7 @@ public class HostEntity implements Comparable<HostEntity> {
   )
   private Collection<ClusterEntity> clusterEntities;
 
-  @OneToOne(mappedBy = "hostEntity", cascade = CascadeType.REMOVE)
+  @OneToOne(mappedBy = "hostEntity", cascade = {CascadeType.REMOVE, CascadeType.PERSIST})
   private HostStateEntity hostStateEntity;
 
   @OneToMany(mappedBy = "host", cascade = CascadeType.REMOVE)
@@ -199,7 +200,7 @@ public class HostEntity implements Comparable<HostEntity> {
   public void setCpuCount(Integer cpuCount) {
     this.cpuCount = cpuCount;
   }
-  
+
   public Integer getPhCpuCount() {
     return phCpuCount;
   }
@@ -207,7 +208,7 @@ public class HostEntity implements Comparable<HostEntity> {
   public void setPhCpuCount(Integer phCpuCount) {
     this.phCpuCount = phCpuCount;
   }
-  
+
   public String getCpuInfo() {
     return defaultString(cpuInfo);
   }
@@ -274,22 +275,26 @@ public class HostEntity implements Comparable<HostEntity> {
 
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     HostEntity that = (HostEntity) o;
 
-    return this.hostId == that.hostId && this.hostName.equals(that.hostName);
+    return hostId == that.hostId && hostName.equals(that.hostName);
   }
 
   @Override
   public int hashCode() {
-    return hostId.hashCode();
+    return (null == hostId ? 0 : hostId.hashCode());
   }
 
   @Override
   public int compareTo(HostEntity other) {
-    return this.hostName.compareTo(other.hostName);
+    return hostName.compareTo(other.hostName);
   }
 
   /**
@@ -382,7 +387,7 @@ public class HostEntity implements Comparable<HostEntity> {
     return hostVersionEntities;
   }
 
-  public void setHostVersionEntities(Collection<HostVersionEntity> hostVersionEntities) { 
+  public void setHostVersionEntities(Collection<HostVersionEntity> hostVersionEntities) {
     this.hostVersionEntities = hostVersionEntities;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
index 363e6be..5fb024d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
@@ -45,7 +45,7 @@ import org.apache.ambari.server.state.RepositoryVersionState;
 @NamedQueries({
     @NamedQuery(name = "hostVersionByClusterAndStackAndVersion", query =
         "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN host.clusterEntities clusters " +
-            "WHERE clusters.clusterName=:clusterName AND hostVersion.repositoryVersion.stack=:stack AND hostVersion.repositoryVersion.version=:version"),
+            "WHERE clusters.clusterName=:clusterName AND hostVersion.repositoryVersion.stack.stackName=:stackName AND hostVersion.repositoryVersion.stack.stackVersion=:stackVersion AND hostVersion.repositoryVersion.version=:version"),
 
     @NamedQuery(name = "hostVersionByClusterAndHostname", query =
         "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN host.clusterEntities clusters " +
@@ -61,7 +61,7 @@ import org.apache.ambari.server.state.RepositoryVersionState;
 
     @NamedQuery(name = "hostVersionByClusterStackVersionAndHostname", query =
         "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN host.clusterEntities clusters " +
-            "WHERE clusters.clusterName=:clusterName AND hostVersion.repositoryVersion.stack=:stack AND hostVersion.repositoryVersion.version=:version AND " +
+            "WHERE clusters.clusterName=:clusterName AND hostVersion.repositoryVersion.stack.stackName=:stackName AND hostVersion.repositoryVersion.stack.stackVersion=:stackVersion AND hostVersion.repositoryVersion.version=:version AND " +
             "hostVersion.hostName=:hostName"),
 })
 public class HostVersionEntity {
@@ -106,9 +106,9 @@ public class HostVersionEntity {
    * This constructor is mainly used by the unit tests in order to construct an object without the id.
    */
   public HostVersionEntity(HostVersionEntity other) {
-    this.hostName = other.hostName;
-    this.repositoryVersion = other.repositoryVersion;
-    this.state = other.state;
+    hostName = other.hostName;
+    repositoryVersion = other.repositoryVersion;
+    state = other.state;
   }
 
   public Long getId() {
@@ -165,24 +165,48 @@ public class HostVersionEntity {
 
   @Override
   public boolean equals(Object obj) {
-    if (this == obj) return true;
-    if (obj == null) return false;
-    if (getClass() != obj.getClass()) return false;
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
 
     HostVersionEntity other = (HostVersionEntity) obj;
     if (hostEntity == null) {
-      if (other.hostEntity != null) return false;
-    } else if (!hostEntity.equals(other.hostEntity)) return false;
+      if (other.hostEntity != null) {
+        return false;
+      }
+    } else if (!hostEntity.equals(other.hostEntity)) {
+      return false;
+    }
     if (hostName == null) {
-      if (other.hostName != null) return false;
-    } else if (!hostName.equals(other.hostName)) return false;
+      if (other.hostName != null) {
+        return false;
+      }
+    } else if (!hostName.equals(other.hostName)) {
+      return false;
+    }
     if (id == null) {
-      if (other.id != null) return false;
-    } else if (!id.equals(other.id)) return false;
+      if (other.id != null) {
+        return false;
+      }
+    } else if (!id.equals(other.id)) {
+      return false;
+    }
     if (repositoryVersion == null) {
-      if (other.repositoryVersion != null) return false;
-    } else if (!repositoryVersion.equals(other.repositoryVersion)) return false;
-    if (state != other.state) return false;
+      if (other.repositoryVersion != null) {
+        return false;
+      }
+    } else if (!repositoryVersion.equals(other.repositoryVersion)) {
+      return false;
+    }
+    if (state != other.state) {
+      return false;
+    }
     return true;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java
index e536f02..dd5ac0a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/RepositoryVersionEntity.java
@@ -27,10 +27,12 @@ import javax.persistence.Entity;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.persistence.JoinColumn;
 import javax.persistence.Lob;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 import javax.persistence.UniqueConstraint;
@@ -59,9 +61,9 @@ import com.google.inject.Provider;
     allocationSize = 1
     )
 @NamedQueries({
-  @NamedQuery(name = "repositoryVersionByDisplayName", query = "SELECT repoversion FROM RepositoryVersionEntity repoversion WHERE repoversion.displayName=:displayname"),
-  @NamedQuery(name = "repositoryVersionByStackVersion", query = "SELECT repoversion FROM RepositoryVersionEntity repoversion WHERE repoversion.stack=:stack AND repoversion.version=:version"),
-  @NamedQuery(name = "repositoryVersionByStack", query = "SELECT repoversion FROM RepositoryVersionEntity repoversion WHERE repoversion.stack=:stack")
+    @NamedQuery(name = "repositoryVersionByDisplayName", query = "SELECT repoversion FROM RepositoryVersionEntity repoversion WHERE repoversion.displayName=:displayname"),
+    @NamedQuery(name = "repositoryVersionByStackVersion", query = "SELECT repoversion FROM RepositoryVersionEntity repoversion WHERE repoversion.stack.stackName=:stackName AND repoversion.stack.stackVersion=:stackVersion AND repoversion.version=:version"),
+    @NamedQuery(name = "repositoryVersionByStack", query = "SELECT repoversion FROM RepositoryVersionEntity repoversion WHERE repoversion.stack.stackName=:stackName AND repoversion.stack.stackVersion=:stackVersion")
 })
 @StaticallyInject
 public class RepositoryVersionEntity {
@@ -76,8 +78,12 @@ public class RepositoryVersionEntity {
   @GeneratedValue(strategy = GenerationType.TABLE, generator = "repository_version_id_generator")
   private Long id;
 
-  @Column(name = "stack")
-  private String stack;
+  /**
+   * Unidirectional one-to-one association to {@link StackEntity}
+   */
+  @OneToOne
+  @JoinColumn(name = "stack_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private StackEntity stack;
 
   @Column(name = "version")
   private String version;
@@ -104,7 +110,8 @@ public class RepositoryVersionEntity {
 
   }
 
-  public RepositoryVersionEntity(String stack, String version, String displayName, String upgradePackage, String operatingSystems) {
+  public RepositoryVersionEntity(StackEntity stack, String version,
+      String displayName, String upgradePackage, String operatingSystems) {
     this.stack = stack;
     this.version = version;
     this.displayName = displayName;
@@ -120,11 +127,22 @@ public class RepositoryVersionEntity {
     this.id = id;
   }
 
-  public String getStack() {
+  /**
+   * Gets the repository version's stack.
+   *
+   * @return the stack.
+   */
+  public StackEntity getStack() {
     return stack;
   }
 
-  public void setStack(String stack) {
+  /**
+   * Sets the repository version's stack.
+   *
+   * @param stack
+   *          the stack to set for the repo version (not {@code null}).
+   */
+  public void setStack(StackEntity stack) {
     this.stack = stack;
   }
 
@@ -157,7 +175,7 @@ public class RepositoryVersionEntity {
   }
 
   public void setOperatingSystems(String repositories) {
-    this.operatingSystems = repositories;
+    operatingSystems = repositories;
   }
 
   /**
@@ -186,22 +204,42 @@ public class RepositoryVersionEntity {
   }
 
   public StackId getStackId() {
-    return new StackId(stack);
+    if (null == stack) {
+      return null;
+    }
+
+    return new StackId(stack.getStackName(), stack.getStackVersion());
   }
 
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     RepositoryVersionEntity that = (RepositoryVersionEntity) o;
 
-    if (id != null ? !id.equals(that.id) : that.id != null) return false;
-    if (stack != null ? !stack.equals(that.stack) : that.stack != null) return false;
-    if (version != null ? !version.equals(that.version) : that.version != null) return false;
-    if (displayName != null ? !displayName.equals(that.displayName) : that.displayName != null) return false;
-    if (upgradePackage != null ? !upgradePackage.equals(that.upgradePackage) : that.upgradePackage != null) return false;
-    if (operatingSystems != null ? !operatingSystems.equals(that.operatingSystems) : that.operatingSystems != null) return false;
+    if (id != null ? !id.equals(that.id) : that.id != null) {
+      return false;
+    }
+    if (stack != null ? !stack.equals(that.stack) : that.stack != null) {
+      return false;
+    }
+    if (version != null ? !version.equals(that.version) : that.version != null) {
+      return false;
+    }
+    if (displayName != null ? !displayName.equals(that.displayName) : that.displayName != null) {
+      return false;
+    }
+    if (upgradePackage != null ? !upgradePackage.equals(that.upgradePackage) : that.upgradePackage != null) {
+      return false;
+    }
+    if (operatingSystems != null ? !operatingSystems.equals(that.operatingSystems) : that.operatingSystems != null) {
+      return false;
+    }
 
     return true;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
index 780f8ba..4195710 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
@@ -18,13 +18,21 @@
 
 package org.apache.ambari.server.orm.entities;
 
-import org.apache.ambari.server.state.State;
-import org.apache.commons.lang.StringUtils;
-
-import javax.persistence.*;
 import java.util.Collection;
 
-import static org.apache.commons.lang.StringUtils.defaultString;
+import javax.persistence.CascadeType;
+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.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+
+import org.apache.ambari.server.state.State;
 
 @javax.persistence.IdClass(ServiceComponentDesiredStateEntityPK.class)
 @javax.persistence.Table(name = "servicecomponentdesiredstate")
@@ -47,9 +55,12 @@ public class ServiceComponentDesiredStateEntity {
   @Enumerated(EnumType.STRING)
   private State desiredState = State.INIT;
 
-  @Column(name = "desired_stack_version", insertable = true, updatable = true)
-  @Basic
-  private String desiredStackVersion = "";
+  /**
+   * Unidirectional one-to-one association to {@link StackEntity}
+   */
+  @OneToOne
+  @JoinColumn(name = "desired_stack_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private StackEntity desiredStack;
 
   @ManyToOne
   @JoinColumns({@javax.persistence.JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false), @JoinColumn(name = "service_name", referencedColumnName = "service_name", nullable = false)})
@@ -93,27 +104,41 @@ public class ServiceComponentDesiredStateEntity {
     this.desiredState = desiredState;
   }
 
-  public String getDesiredStackVersion() {
-    return defaultString(desiredStackVersion);
+  public StackEntity getDesiredStack() {
+    return desiredStack;
   }
 
-  public void setDesiredStackVersion(String desiredStackVersion) {
-    this.desiredStackVersion = desiredStackVersion;
+  public void setDesiredStack(StackEntity desiredStack) {
+    this.desiredStack = desiredStack;
   }
 
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     ServiceComponentDesiredStateEntity that = (ServiceComponentDesiredStateEntity) o;
 
-    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) return false;
-    if (componentName != null ? !componentName.equals(that.componentName) : that.componentName != null) return false;
-    if (desiredState != null ? !desiredState.equals(that.desiredState) : that.desiredState != null) return false;
-    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
-    if (desiredStackVersion != null ? !desiredStackVersion.equals(that.desiredStackVersion) : that.desiredStackVersion != null)
+    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) {
+      return false;
+    }
+    if (componentName != null ? !componentName.equals(that.componentName) : that.componentName != null) {
+      return false;
+    }
+    if (desiredState != null ? !desiredState.equals(that.desiredState) : that.desiredState != null) {
+      return false;
+    }
+    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) {
+      return false;
+    }
+    if (desiredStack != null ? !desiredStack.equals(that.desiredStack)
+        : that.desiredStack != null) {
       return false;
+    }
     return true;
   }
 
@@ -123,7 +148,7 @@ public class ServiceComponentDesiredStateEntity {
     result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
     result = 31 * result + (componentName != null ? componentName.hashCode() : 0);
     result = 31 * result + (desiredState != null ? desiredState.hashCode() : 0);
-    result = 31 * result + (desiredStackVersion != null ? desiredStackVersion.hashCode() : 0);
+    result = 31 * result + (desiredStack != null ? desiredStack.hashCode() : 0);
 
     return result;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java
index ec6bd9f..86b919f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceConfigEntity.java
@@ -18,8 +18,9 @@
 
 package org.apache.ambari.server.orm.entities;
 
+import java.util.List;
+
 import javax.persistence.Basic;
-import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -31,11 +32,9 @@ import javax.persistence.JoinColumn;
 import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
-import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
-import java.util.Collection;
-import java.util.List;
 
 @Entity
 @Table(name = "serviceconfig")
@@ -96,6 +95,13 @@ public class ServiceConfigEntity {
   @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false)
   private ClusterEntity clusterEntity;
 
+  /**
+   * Unidirectional one-to-one association to {@link StackEntity}
+   */
+  @OneToOne
+  @JoinColumn(name = "stack_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private StackEntity stack;
+
   public Long getServiceConfigId() {
     return serviceConfigId;
   }
@@ -125,7 +131,7 @@ public class ServiceConfigEntity {
   }
 
   public void setCreateTimestamp(Long create_timestamp) {
-    this.createTimestamp = create_timestamp;
+    createTimestamp = create_timestamp;
   }
 
   public List<ClusterConfigEntity> getClusterConfigEntities() {
@@ -183,4 +189,23 @@ public class ServiceConfigEntity {
   public void setHostNames(List<String> hostNames) {
     this.hostNames = hostNames;
   }
+
+  /**
+   * Gets the service configuration's stack.
+   *
+   * @return the stack.
+   */
+  public StackEntity getStack() {
+    return stack;
+  }
+
+  /**
+   * Sets the service configuration's stack.
+   *
+   * @param stack
+   *          the stack to set for the service configuration (not {@code null}).
+   */
+  public void setStack(StackEntity stack) {
+    this.stack = stack;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntity.java
index 2d2c386..6cb3dde 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntity.java
@@ -18,12 +18,18 @@
 
 package org.apache.ambari.server.orm.entities;
 
+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 org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.SecurityState;
 import org.apache.ambari.server.state.State;
-import org.apache.commons.lang.StringUtils;
-
-import javax.persistence.*;
 
 @javax.persistence.IdClass(ServiceDesiredStateEntityPK.class)
 @javax.persistence.Table(name = "servicedesiredstate")
@@ -46,14 +52,17 @@ public class ServiceDesiredStateEntity {
   @Basic
   private int desiredHostRoleMapping = 0;
 
-  @Column(name = "desired_stack_version", insertable = true, updatable = true)
-  @Basic
-  private String desiredStackVersion = "";
+  /**
+   * Unidirectional one-to-one association to {@link StackEntity}
+   */
+  @OneToOne
+  @JoinColumn(name = "desired_stack_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private StackEntity desiredStack;
 
   @Column(name = "maintenance_state", nullable = false, insertable = true, updatable = true)
   @Enumerated(value = EnumType.STRING)
   private MaintenanceState maintenanceState = MaintenanceState.OFF;
-  
+
   @Column(name = "security_state", nullable = false, insertable = true, updatable = true)
   @Enumerated(value = EnumType.STRING)
   private SecurityState securityState = SecurityState.UNSECURED;
@@ -98,18 +107,18 @@ public class ServiceDesiredStateEntity {
     this.desiredHostRoleMapping = desiredHostRoleMapping;
   }
 
-  public String getDesiredStackVersion() {
-    return StringUtils.defaultString(desiredStackVersion);
+  public StackEntity getDesiredStack() {
+    return desiredStack;
   }
 
-  public void setDesiredStackVersion(String desiredStackVersion) {
-    this.desiredStackVersion = desiredStackVersion;
+  public void setDesiredStack(StackEntity desiredStack) {
+    this.desiredStack = desiredStack;
   }
-  
+
   public MaintenanceState getMaintenanceState() {
     return maintenanceState;
-  }  
-  
+  }
+
   public void setMaintenanceState(MaintenanceState state) {
     maintenanceState = state;
   }
@@ -124,17 +133,35 @@ public class ServiceDesiredStateEntity {
 
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     ServiceDesiredStateEntity that = (ServiceDesiredStateEntity) o;
 
-    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) return false;
-    if (desiredState != null ? !desiredState.equals(that.desiredState) : that.desiredState != null) return false;
-    if (desiredHostRoleMapping != that.desiredHostRoleMapping) return false;
-    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
-    if (desiredStackVersion != null ? !desiredStackVersion.equals(that.desiredStackVersion) : that.desiredStackVersion != null)
+    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) {
+      return false;
+    }
+
+    if (desiredState != null ? !desiredState.equals(that.desiredState) : that.desiredState != null) {
+      return false;
+    }
+
+    if (desiredHostRoleMapping != that.desiredHostRoleMapping) {
+      return false;
+    }
+
+    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) {
+      return false;
+    }
+
+    if (desiredStack != null ? !desiredStack.equals(that.desiredStack) : that.desiredStack != null) {
       return false;
+    }
     return true;
   }
 
@@ -144,7 +171,7 @@ public class ServiceDesiredStateEntity {
     result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
     result = 31 * result + (desiredState != null ? desiredState.hashCode() : 0);
     result = 31 * result + desiredHostRoleMapping;
-    result = 31 * result + (desiredStackVersion != null ? desiredStackVersion.hashCode() : 0);
+    result = 31 * result + (desiredStack != null ? desiredStack.hashCode() : 0);
     return result;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java
index fc9774b..472953c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java
@@ -51,9 +51,9 @@ import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.UpgradeState;
 import org.apache.ambari.server.state.svccomphost.ServiceComponentHostSummary;
 import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.text.StrBuilder;
 
 import com.google.inject.Inject;
-import org.apache.commons.lang.text.StrBuilder;
 
 /**
  * Action that represents finalizing the Upgrade by completing any database changes.
@@ -122,8 +122,7 @@ public class FinalizeUpgradeAction extends AbstractServerAction {
 
       Cluster cluster = clusters.getCluster(clusterName);
 
-      StackId stack = cluster.getCurrentStackVersion();
-      String stackId = stack.getStackId();
+      StackId stackId = cluster.getCurrentStackVersion();
       ClusterVersionEntity upgradingClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(clusterName,
           stackId, version);
 
@@ -153,7 +152,8 @@ public class FinalizeUpgradeAction extends AbstractServerAction {
             // It is possible that the host version has a state of INSTALLED and it never changed if the host only has
             // components that do not advertise a version.
             HostEntity host = hostVersion.getHostEntity();
-            ServiceComponentHostSummary hostSummary = new ServiceComponentHostSummary(ambariMetaInfo, host, stack);
+            ServiceComponentHostSummary hostSummary = new ServiceComponentHostSummary(
+                ambariMetaInfo, host, stackId);
             if (hostSummary.haveAllComponentsFinishedAdvertisingVersion()){
               isStateCorrect = true;
               atLeastOneHostInInstalledState = true;
@@ -179,11 +179,12 @@ public class FinalizeUpgradeAction extends AbstractServerAction {
         throw new AmbariException(message);
       }
 
-      checkHostComponentVesions(cluster, version, stack);
+      checkHostComponentVesions(cluster, version, stackId);
 
       // May need to first transition to UPGRADED
       if (atLeastOneHostInInstalledState) {
-        cluster.transitionClusterVersion(stackId, version, RepositoryVersionState.UPGRADED);
+        cluster.transitionClusterVersion(stackId, version,
+            RepositoryVersionState.UPGRADED);
         upgradingClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(clusterName,
             stackId, version);
       }
@@ -210,7 +211,8 @@ public class FinalizeUpgradeAction extends AbstractServerAction {
       cluster.mapHostVersions(hostsToUpdate, upgradingClusterVersion, RepositoryVersionState.CURRENT);
 
       outSB.append(String.format("Will finalize the version for cluster %s.\n", clusterName));
-      cluster.transitionClusterVersion(stackId, version, RepositoryVersionState.CURRENT);
+      cluster.transitionClusterVersion(stackId, version,
+          RepositoryVersionState.CURRENT);
 
       outSB.append("Upgrade was successful!\n");
       return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outSB.toString(), errSB.toString());
@@ -278,7 +280,7 @@ public class FinalizeUpgradeAction extends AbstractServerAction {
       Set<String> badHosts = new HashSet<String>();
       for (String badVersion : badVersions) {
         List<HostVersionEntity> hostVersions = hostVersionDAO.findByClusterStackAndVersion(
-            clusterName, stackId.getStackId(), badVersion);
+            clusterName, stackId, badVersion);
 
         for (HostVersionEntity hostVersion : hostVersions) {
           badHosts.add(hostVersion.getHostName());

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
index b10157a..847e349 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java
@@ -187,25 +187,37 @@ public interface Cluster {
   public void recalculateAllClusterVersionStates() throws AmbariException;
 
   /**
-   * Create a cluster version for the given stack and version, whose initial state must either
-   * be either {@link RepositoryVersionState#UPGRADING} (if no other cluster version exists) or
-   * {@link RepositoryVersionState#INSTALLING} (if at exactly one CURRENT cluster version already exists).
-   * @param stack Stack name
-   * @param version Stack version
-   * @param userName User performing the operation
-   * @param state Initial state
+   * Create a cluster version for the given stack and version, whose initial
+   * state must either be either {@link RepositoryVersionState#UPGRADING} (if no
+   * other cluster version exists) or {@link RepositoryVersionState#INSTALLING}
+   * (if at exactly one CURRENT cluster version already exists).
+   *
+   * @param stackId
+   *          Stack ID
+   * @param version
+   *          Stack version
+   * @param userName
+   *          User performing the operation
+   * @param state
+   *          Initial state
    * @throws AmbariException
    */
-  public void createClusterVersion(String stack, String version, String userName, RepositoryVersionState state) throws AmbariException;
+  public void createClusterVersion(StackId stackId, String version,
+      String userName, RepositoryVersionState state) throws AmbariException;
 
   /**
    * Transition an existing cluster version from one state to another.
-   * @param stack Stack name
-   * @param version Stack version
-   * @param state Desired state
+   * 
+   * @param stackId
+   *          Stack ID
+   * @param version
+   *          Stack version
+   * @param state
+   *          Desired state
    * @throws AmbariException
    */
-  public void transitionClusterVersion(String stack, String version, RepositoryVersionState state) throws AmbariException;
+  public void transitionClusterVersion(StackId stackId, String version,
+      RepositoryVersionState state) throws AmbariException;
 
   /**
    * Gets whether the cluster is still initializing or has finished with its

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/state/Clusters.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Clusters.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Clusters.java
index 8676521..80ac6a7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Clusters.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Clusters.java
@@ -18,11 +18,12 @@
 
 package org.apache.ambari.server.state;
 
-import org.apache.ambari.server.AmbariException;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.ambari.server.AmbariException;
+
 /**
  * Single entity that tracks all clusters and hosts that are managed
  * by the Ambari server
@@ -31,9 +32,13 @@ public interface Clusters {
 
   /**
    * Add a new Cluster
+   * 
    * @param clusterName
+   *          the cluster name (not {@code null}).
+   * @param stackId
+   *          the stack for the cluster (not {@code null}).
    */
-  public void addCluster(String clusterName)
+  public void addCluster(String clusterName, StackId stackId)
       throws AmbariException;
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
index 0211b68..5176d69 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigImpl.java
@@ -18,7 +18,11 @@
 
 package org.apache.ambari.server.state;
 
-import java.util.*;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ServiceConfigDAO;
@@ -31,7 +35,6 @@ import com.google.inject.Injector;
 import com.google.inject.assistedinject.Assisted;
 import com.google.inject.assistedinject.AssistedInject;
 import com.google.inject.persist.Transactional;
-import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
 
 public class ConfigImpl implements Config {
   public static final String GENERATED_TAG_PREFIX = "generatedTag_";
@@ -50,25 +53,25 @@ public class ConfigImpl implements Config {
   private Gson gson;
   @Inject
   private ServiceConfigDAO serviceConfigDAO;
-  
+
 
   @AssistedInject
-  public ConfigImpl(@Assisted Cluster cluster, @Assisted String type, @Assisted Map<String, String> properties, 
+  public ConfigImpl(@Assisted Cluster cluster, @Assisted String type, @Assisted Map<String, String> properties,
       @Assisted Map<String, Map<String, String>> propertiesAttributes, Injector injector) {
     this.cluster = cluster;
     this.type = type;
     this.properties = properties;
     this.propertiesAttributes = propertiesAttributes;
     injector.injectMembers(this);
-    
+
   }
-  
+
   @AssistedInject
   public ConfigImpl(@Assisted Cluster cluster, @Assisted ClusterConfigEntity entity, Injector injector) {
     this.cluster = cluster;
-    this.type = entity.getType();
-    this.tag = entity.getTag();
-    this.version = entity.getVersion();
+    type = entity.getType();
+    tag = entity.getTag();
+    version = entity.getVersion();
     this.entity = entity;
     injector.injectMembers(this);
   }
@@ -87,7 +90,7 @@ public class ConfigImpl implements Config {
 
   @Override
   public synchronized String getTag() {
-    if (this.tag == null) {
+    if (tag == null) {
       tag = GENERATED_TAG_PREFIX + getVersion();
     }
     return tag;
@@ -95,8 +98,8 @@ public class ConfigImpl implements Config {
 
   @Override
   public synchronized Long getVersion() {
-    if (this.version == null && cluster != null) {
-      this.version = cluster.getNextConfigVersion(type);
+    if (version == null && cluster != null) {
+      version = cluster.getNextConfigVersion(type);
     }
     return version;
   }
@@ -104,9 +107,9 @@ public class ConfigImpl implements Config {
   @Override
   public synchronized Map<String, String> getProperties() {
     if (null != entity && null == properties) {
-      
+
       properties = gson.<Map<String, String>>fromJson(entity.getData(), Map.class);
-      
+
     }
     return null == properties ? new HashMap<String, String>()
         : new HashMap<String, String>(properties);
@@ -159,11 +162,11 @@ public class ConfigImpl implements Config {
       this.properties.remove(key);
     }
   }
-  
+
   @Transactional
   @Override
   public synchronized void persist() {
-    
+
     ClusterEntity clusterEntity = clusterDAO.findById(cluster.getClusterId());
 
     ClusterConfigEntity entity = new ClusterConfigEntity();
@@ -173,7 +176,8 @@ public class ConfigImpl implements Config {
     entity.setVersion(getVersion());
     entity.setTag(getTag());
     entity.setTimestamp(new Date().getTime());
-    
+    entity.setStack(clusterEntity.getDesiredStack());
+
     entity.setData(gson.toJson(getProperties()));
     if (null != getPropertiesAttributes()) {
       entity.setAttributes(gson.toJson(getPropertiesAttributes()));

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
index 73ed25e..9e84353 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentImpl.java
@@ -24,7 +24,6 @@ import java.util.Map.Entry;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
-import com.google.inject.ProvisionException;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.ServiceComponentHostNotFoundException;
@@ -33,6 +32,7 @@ import org.apache.ambari.server.controller.ServiceComponentResponse;
 import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
 import org.apache.ambari.server.orm.dao.HostComponentDesiredStateDAO;
 import org.apache.ambari.server.orm.dao.ServiceComponentDesiredStateDAO;
+import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
@@ -40,13 +40,14 @@ import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntityPK;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntityPK;
+import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.state.cluster.ClusterImpl;
 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.ProvisionException;
 import com.google.inject.assistedinject.Assisted;
 import com.google.inject.assistedinject.AssistedInject;
 import com.google.inject.persist.Transactional;
@@ -62,8 +63,6 @@ public class ServiceComponentImpl implements ServiceComponent {
   private final boolean isMasterComponent;
   boolean persisted = false;
   @Inject
-  private Gson gson;
-  @Inject
   private ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO;
   @Inject
   private ClusterServiceDAO clusterServiceDAO;
@@ -76,6 +75,12 @@ public class ServiceComponentImpl implements ServiceComponent {
   private ServiceComponentDesiredStateEntity desiredStateEntity;
   private Map<String, ServiceComponentHost> hostComponents;
 
+  /**
+   * Data access object used for lookup up stacks.
+   */
+  @Inject
+  private StackDAO stackDAO;
+
   @AssistedInject
   public ServiceComponentImpl(@Assisted Service service,
                               @Assisted String componentName, Injector injector) throws AmbariException {
@@ -348,15 +353,20 @@ public class ServiceComponentImpl implements ServiceComponent {
   public StackId getDesiredStackVersion() {
     readWriteLock.readLock().lock();
     try {
-      return gson.fromJson(desiredStateEntity.getDesiredStackVersion(),
-          StackId.class);
+      StackEntity stackEntity = desiredStateEntity.getDesiredStack();
+      if (null != stackEntity) {
+        return new StackId(stackEntity.getStackName(),
+            stackEntity.getStackVersion());
+      } else {
+        return null;
+      }
     } finally {
       readWriteLock.readLock().unlock();
     }
   }
 
   @Override
-  public void setDesiredStackVersion(StackId stackVersion) {
+  public void setDesiredStackVersion(StackId stack) {
     readWriteLock.writeLock().lock();
     try {
       if (LOG.isDebugEnabled()) {
@@ -365,9 +375,13 @@ public class ServiceComponentImpl implements ServiceComponent {
             + service.getCluster().getClusterId() + ", serviceName="
             + service.getName() + ", serviceComponentName=" + getName()
             + ", oldDesiredStackVersion=" + getDesiredStackVersion()
-            + ", newDesiredStackVersion=" + stackVersion);
+            + ", newDesiredStackVersion=" + stack);
       }
-      desiredStateEntity.setDesiredStackVersion(gson.toJson(stackVersion));
+
+      StackEntity stackEntity = stackDAO.find(stack.getStackName(),
+          stack.getStackVersion());
+
+      desiredStateEntity.setDesiredStack(stackEntity);
       saveIfPersisted();
     } finally {
       readWriteLock.writeLock().unlock();

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
index c8018a0..f7a59dc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
@@ -34,15 +34,16 @@ import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
 import org.apache.ambari.server.orm.dao.ServiceDesiredStateDAO;
+import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity;
+import org.apache.ambari.server.orm.entities.StackEntity;
 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.ProvisionException;
@@ -67,8 +68,6 @@ public class ServiceImpl implements Service {
   private final boolean isClientOnlyService;
 
   @Inject
-  Gson gson;
-  @Inject
   private ClusterServiceDAO clusterServiceDAO;
   @Inject
   private ServiceDesiredStateDAO serviceDesiredStateDAO;
@@ -80,6 +79,12 @@ public class ServiceImpl implements Service {
   private AmbariMetaInfo ambariMetaInfo;
 
   /**
+   * Data access object for retrieving stack instances.
+   */
+  @Inject
+  private StackDAO stackDAO;
+
+  /**
    * Used to publish events relating to service CRUD operations.
    */
   @Inject
@@ -338,15 +343,19 @@ public class ServiceImpl implements Service {
   public StackId getDesiredStackVersion() {
     readWriteLock.readLock().lock();
     try {
-      return gson.fromJson(serviceDesiredStateEntity.getDesiredStackVersion(),
-          StackId.class);
+      StackEntity desiredStackEntity = serviceDesiredStateEntity.getDesiredStack();
+      if( null != desiredStackEntity ) {
+        return new StackId(desiredStackEntity);
+      } else {
+        return null;
+      }
     } finally {
       readWriteLock.readLock().unlock();
     }
   }
 
   @Override
-  public void setDesiredStackVersion(StackId stackVersion) {
+  public void setDesiredStackVersion(StackId stack) {
     readWriteLock.writeLock().lock();
     try {
       if (LOG.isDebugEnabled()) {
@@ -354,9 +363,11 @@ public class ServiceImpl implements Service {
             + cluster.getClusterName() + ", clusterId="
             + cluster.getClusterId() + ", serviceName=" + getName()
             + ", oldDesiredStackVersion=" + getDesiredStackVersion()
-            + ", newDesiredStackVersion=" + stackVersion);
+            + ", newDesiredStackVersion=" + stack);
       }
-      serviceDesiredStateEntity.setDesiredStackVersion(gson.toJson(stackVersion));
+
+      StackEntity stackEntity = stackDAO.find(stack.getStackName(), stack.getStackVersion());
+      serviceDesiredStateEntity.setDesiredStack(stackEntity);
       saveIfPersisted();
     } finally {
       readWriteLock.writeLock().unlock();

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/state/StackId.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/StackId.java b/ambari-server/src/main/java/org/apache/ambari/server/state/StackId.java
index 0be39c1..80aed71 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/StackId.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/StackId.java
@@ -18,6 +18,7 @@
 
 package org.apache.ambari.server.state;
 
+import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.utils.VersionUtils;
 
 public class StackId implements Comparable<StackId> {
@@ -28,8 +29,8 @@ public class StackId implements Comparable<StackId> {
   private String stackVersion;
 
   public StackId() {
-    this.stackName = "";
-    this.stackVersion = "";
+    stackName = "";
+    stackVersion = "";
   }
 
   public StackId(String stackId) {
@@ -37,14 +38,18 @@ public class StackId implements Comparable<StackId> {
   }
 
   public StackId(StackInfo stackInfo) {
-    this.stackName = stackInfo.getName();
-    this.stackVersion = stackInfo.getVersion();
+    stackName = stackInfo.getName();
+    stackVersion = stackInfo.getVersion();
   }
 
   public StackId(String stackName, String stackVersion) {
     this(stackName + NAME_SEPARATOR + stackVersion);
   }
 
+  public StackId(StackEntity stackEntity) {
+    this(stackEntity.getStackName(), stackEntity.getStackVersion());
+  }
+
   /**
    * @return the stackName
    */
@@ -115,6 +120,7 @@ public class StackId implements Comparable<StackId> {
     return returnValue;
   }
 
+  @Override
   public String toString() {
     return getStackId();
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index 1a8bf43..9643fe1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -64,6 +64,7 @@ import org.apache.ambari.server.orm.dao.HostDAO;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.dao.ServiceConfigDAO;
+import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity;
@@ -81,6 +82,7 @@ import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.RequestScheduleEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
+import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.ClusterHealthReport;
@@ -119,7 +121,6 @@ import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
-import com.google.gson.Gson;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import com.google.inject.assistedinject.Assisted;
@@ -196,8 +197,6 @@ public class ClusterImpl implements Cluster {
   @Inject
   private ConfigFactory configFactory;
   @Inject
-  private Gson gson;
-  @Inject
   private HostConfigMappingDAO hostConfigMappingDAO;
   @Inject
   private ConfigGroupFactory configGroupFactory;
@@ -232,6 +231,12 @@ public class ClusterImpl implements Cluster {
   @Inject
   private AmbariSessionManager sessionManager;
 
+  /**
+   * Data access object used for looking up stacks from the database.
+   */
+  @Inject
+  private StackDAO stackDAO;
+
   private volatile boolean svcHostsLoaded = false;
 
   private volatile Multimap<String, String> serviceConfigTypes;
@@ -246,8 +251,9 @@ public class ClusterImpl implements Cluster {
       Map<String, Map<String, ServiceComponentHost>>>();
     serviceComponentHostsByHost = new HashMap<String,
       List<ServiceComponentHost>>();
-    desiredStackVersion = gson.fromJson(
-      clusterEntity.getDesiredStackVersion(), StackId.class);
+
+    desiredStackVersion = new StackId(clusterEntity.getDesiredStack());
+
     allConfigs = new HashMap<String, Map<String, Config>>();
     if (!clusterEntity.getClusterConfigEntities().isEmpty()) {
       for (ClusterConfigEntity entity : clusterEntity.getClusterConfigEntities()) {
@@ -876,17 +882,21 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public void setDesiredStackVersion(StackId stackVersion) throws AmbariException {
+  public void setDesiredStackVersion(StackId stackId) throws AmbariException {
     clusterGlobalLock.writeLock().lock();
     try {
       if (LOG.isDebugEnabled()) {
         LOG.debug("Changing DesiredStackVersion of Cluster" + ", clusterName="
             + getClusterName() + ", clusterId=" + getClusterId()
             + ", currentDesiredStackVersion=" + desiredStackVersion
-            + ", newDesiredStackVersion=" + stackVersion);
+            + ", newDesiredStackVersion=" + stackId);
       }
-      desiredStackVersion = stackVersion;
-      clusterEntity.setDesiredStackVersion(gson.toJson(stackVersion));
+
+      desiredStackVersion = stackId;
+      StackEntity stackEntity = stackDAO.find(stackId.getStackName(),
+          stackId.getStackVersion());
+
+      clusterEntity.setDesiredStack(stackEntity);
       clusterDAO.merge(clusterEntity);
       loadServiceConfigTypes();
     } finally {
@@ -900,10 +910,8 @@ public class ClusterImpl implements Cluster {
     try {
       ClusterStateEntity clusterStateEntity = clusterEntity.getClusterStateEntity();
       if (clusterStateEntity != null) {
-        String stackVersion = clusterStateEntity.getCurrentStackVersion();
-        if (stackVersion != null && !stackVersion.isEmpty()) {
-          return gson.fromJson(stackVersion, StackId.class);
-        }
+        StackEntity currentStackEntity = clusterStateEntity.getCurrentStack();
+        return new StackId(currentStackEntity);
       }
       return null;
     } finally {
@@ -1008,10 +1016,12 @@ public class ClusterImpl implements Cluster {
 
     clusterGlobalLock.writeLock().lock();
     try {
+      StackEntity repoVersionStackEntity = currentClusterVersion.getRepositoryVersion().getStack();
+      StackId repoVersionStackId = new StackId(repoVersionStackEntity);
+
       Map<String, HostVersionEntity> existingHostToHostVersionEntity = new HashMap<String, HostVersionEntity>();
       List<HostVersionEntity> existingHostVersionEntities = hostVersionDAO.findByClusterStackAndVersion(
-          getClusterName(),
-          currentClusterVersion.getRepositoryVersion().getStack(),
+          getClusterName(), repoVersionStackId,
           currentClusterVersion.getRepositoryVersion().getVersion());
 
       if (existingHostVersionEntities != null) {
@@ -1091,9 +1101,11 @@ public class ClusterImpl implements Cluster {
 
     clusterGlobalLock.writeLock().lock();
     try {
+      StackEntity repoVersionStackEntity = sourceClusterVersion.getRepositoryVersion().getStack();
+      StackId repoVersionStackId = new StackId(repoVersionStackEntity);
+
       List<HostVersionEntity> existingHostVersionEntities = hostVersionDAO.findByClusterStackAndVersion(
-          getClusterName(),
-          sourceClusterVersion.getRepositoryVersion().getStack(),
+          getClusterName(), repoVersionStackId,
           sourceClusterVersion.getRepositoryVersion().getVersion());
 
       if (existingHostVersionEntities != null) {
@@ -1203,7 +1215,7 @@ public class ClusterImpl implements Cluster {
       // Part 1, bootstrap cluster version if necessary.
 
       ClusterVersionEntity clusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(
-          getClusterName(), stackId.getStackId(), repositoryVersion);
+          getClusterName(), stackId, repositoryVersion);
 
       if (clusterVersion == null) {
         if (clusterVersionDAO.findByCluster(getClusterName()).isEmpty()) {
@@ -1213,12 +1225,12 @@ public class ClusterImpl implements Cluster {
           // which can happen if the first HostComponentState to trigger this method
           // cannot advertise a version.
           createClusterVersionInternal(
-              stackId.getStackId(),
+              stackId,
               repositoryVersion,
               AuthorizationHelper.getAuthenticatedName(configuration.getAnonymousAuditName()),
               RepositoryVersionState.UPGRADING);
           clusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(
-              getClusterName(), stackId.getStackId(), repositoryVersion);
+              getClusterName(), stackId, repositoryVersion);
 
           if (clusterVersion == null) {
             LOG.warn(String.format(
@@ -1251,7 +1263,7 @@ public class ClusterImpl implements Cluster {
       for (Host host : hosts.values()) {
         String hostName = host.getHostName();
         HostVersionEntity hostVersion = hostVersionDAO.findByClusterStackVersionAndHost(
-            getClusterName(), stackId.getStackId(), repositoryVersion, hostName);
+            getClusterName(), stackId, repositoryVersion, hostName);
 
         if (hostVersion == null) {
           // This host either has not had a chance to heartbeat yet with its
@@ -1303,7 +1315,7 @@ public class ClusterImpl implements Cluster {
         // Any mismatch will be caught while transitioning, and raise an
         // exception.
         try {
-          transitionClusterVersion(stackId.getStackId(), repositoryVersion,
+          transitionClusterVersion(stackId, repositoryVersion,
               effectiveClusterVersionState);
         } catch (AmbariException e) {
           ;
@@ -1324,7 +1336,12 @@ public class ClusterImpl implements Cluster {
   @Override
   @Transactional
   public HostVersionEntity transitionHostVersionState(HostEntity host, final RepositoryVersionEntity repositoryVersion, final StackId stack) throws AmbariException {
-    HostVersionEntity hostVersionEntity = hostVersionDAO.findByClusterStackVersionAndHost(getClusterName(), repositoryVersion.getStack(), repositoryVersion.getVersion(), host.getHostName());
+    StackEntity repoVersionStackEntity = repositoryVersion.getStack();
+    StackId repoVersionStackId = new StackId(repoVersionStackEntity);
+
+    HostVersionEntity hostVersionEntity = hostVersionDAO.findByClusterStackVersionAndHost(
+        getClusterName(), repoVersionStackId, repositoryVersion.getVersion(),
+        host.getHostName());
 
     hostTransitionStateWriteLock.lock();
     try {
@@ -1387,10 +1404,11 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public void createClusterVersion(String stack, String version, String userName, RepositoryVersionState state) throws AmbariException {
+  public void createClusterVersion(StackId stackId, String version,
+      String userName, RepositoryVersionState state) throws AmbariException {
     clusterGlobalLock.writeLock().lock();
     try {
-      createClusterVersionInternal(stack, version, userName, state);
+      createClusterVersionInternal(stackId, version, userName, state);
     } finally {
       clusterGlobalLock.writeLock().unlock();
     }
@@ -1401,7 +1419,8 @@ public class ClusterImpl implements Cluster {
    *
    * This method is intended to be called only when cluster lock is already acquired.
    */
-  private void createClusterVersionInternal(String stack, String version, String userName, RepositoryVersionState state) throws AmbariException {
+  private void createClusterVersionInternal(StackId stackId, String version,
+      String userName, RepositoryVersionState state) throws AmbariException {
     Set<RepositoryVersionState> allowedStates = new HashSet<RepositoryVersionState>();
     Collection<ClusterVersionEntity> allClusterVersions = getAllClusterVersions();
     if (allClusterVersions == null || allClusterVersions.isEmpty()) {
@@ -1414,15 +1433,20 @@ public class ClusterImpl implements Cluster {
       throw new AmbariException("The allowed state for a new cluster version must be within " + allowedStates);
     }
 
-    ClusterVersionEntity existing = clusterVersionDAO.findByClusterAndStackAndVersion(getClusterName(), stack, version);
+    ClusterVersionEntity existing = clusterVersionDAO.findByClusterAndStackAndVersion(
+        getClusterName(), stackId, version);
     if (existing != null) {
-      throw new DuplicateResourceException("Duplicate item, a cluster version with stack=" + stack + ", version=" +
+      throw new DuplicateResourceException(
+          "Duplicate item, a cluster version with stack=" + stackId
+              + ", version=" +
           version + " for cluster " + getClusterName() + " already exists");
     }
 
-    RepositoryVersionEntity repositoryVersionEntity = repositoryVersionDAO.findByStackAndVersion(stack, version);
+    RepositoryVersionEntity repositoryVersionEntity = repositoryVersionDAO.findByStackAndVersion(
+        stackId, version);
     if (repositoryVersionEntity == null) {
-      LOG.warn("Could not find repository version for stack=" + stack + ", version=" + version);
+      LOG.warn("Could not find repository version for stack=" + stackId
+          + ", version=" + version);
       return;
     }
 
@@ -1432,23 +1456,28 @@ public class ClusterImpl implements Cluster {
 
   /**
    * Transition an existing cluster version from one state to another.
-   * @param stack Stack name
-   * @param version Stack version
-   * @param state Desired state
+   *
+   * @param stackId
+   *          Stack ID
+   * @param version
+   *          Stack version
+   * @param state
+   *          Desired state
    * @throws AmbariException
    */
   @Override
   @Transactional
-  public void transitionClusterVersion(String stack, String version, RepositoryVersionState state) throws AmbariException {
+  public void transitionClusterVersion(StackId stackId, String version,
+      RepositoryVersionState state) throws AmbariException {
     Set<RepositoryVersionState> allowedStates = new HashSet<RepositoryVersionState>();
     clusterGlobalLock.writeLock().lock();
     try {
       ClusterVersionEntity existingClusterVersion = clusterVersionDAO.findByClusterAndStackAndVersion(
-          getClusterName(), stack, version);
+          getClusterName(), stackId, version);
       if (existingClusterVersion == null) {
         throw new AmbariException(
             "Existing cluster version not found for cluster="
-                + getClusterName() + ", stack=" + stack + ", version="
+                + getClusterName() + ", stack=" + stackId + ", version="
                 + version);
       }
 
@@ -1547,7 +1576,7 @@ public class ClusterImpl implements Cluster {
         }
       }
     } catch (RollbackException e) {
-      String message = "Unable to transition stack " + stack + " at version "
+      String message = "Unable to transition stack " + stackId + " at version "
           + version + " for cluster " + getClusterName() + " to state " + state;
       LOG.warn(message);
       throw new AmbariException(message, e);
@@ -1581,29 +1610,32 @@ public class ClusterImpl implements Cluster {
   }
 
   @Override
-  public void setCurrentStackVersion(StackId stackVersion)
+  public void setCurrentStackVersion(StackId stackId)
     throws AmbariException {
     clusterGlobalLock.writeLock().lock();
     try {
+      StackEntity stackEntity = stackDAO.find(stackId.getStackName(),
+          stackId.getStackVersion());
+
       ClusterStateEntity clusterStateEntity = clusterStateDAO.findByPK(clusterEntity.getClusterId());
       if (clusterStateEntity == null) {
         clusterStateEntity = new ClusterStateEntity();
         clusterStateEntity.setClusterId(clusterEntity.getClusterId());
-        clusterStateEntity.setCurrentStackVersion(gson.toJson(stackVersion));
+        clusterStateEntity.setCurrentStack(stackEntity);
         clusterStateEntity.setClusterEntity(clusterEntity);
         clusterStateDAO.create(clusterStateEntity);
         clusterStateEntity = clusterStateDAO.merge(clusterStateEntity);
         clusterEntity.setClusterStateEntity(clusterStateEntity);
         clusterEntity = clusterDAO.merge(clusterEntity);
       } else {
-        clusterStateEntity.setCurrentStackVersion(gson.toJson(stackVersion));
+        clusterStateEntity.setCurrentStack(stackEntity);
         clusterStateDAO.merge(clusterStateEntity);
         clusterEntity = clusterDAO.merge(clusterEntity);
       }
     } catch (RollbackException e) {
-      LOG.warn("Unable to set version " + stackVersion + " for cluster "
+      LOG.warn("Unable to set version " + stackId + " for cluster "
           + getClusterName());
-      throw new AmbariException("Unable to set" + " version=" + stackVersion
+      throw new AmbariException("Unable to set" + " version=" + stackId
           + " for cluster " + getClusterName(), e);
     } finally {
       clusterGlobalLock.writeLock().unlock();
@@ -1911,6 +1943,7 @@ public class ClusterImpl implements Cluster {
     serviceConfigEntity.setVersion(configVersionHelper.getNextVersion(serviceName));
     serviceConfigEntity.setUser(user);
     serviceConfigEntity.setNote(note);
+    serviceConfigEntity.setStack(clusterEntity.getDesiredStack());
 
     if (configGroup != null) {
       serviceConfigEntity.setGroupId(configGroup.getId());
@@ -2186,6 +2219,7 @@ public class ClusterImpl implements Cluster {
     serviceConfigEntityClone.setUser(user);
     serviceConfigEntityClone.setServiceName(serviceName);
     serviceConfigEntityClone.setClusterEntity(clusterEntity);
+    serviceConfigEntityClone.setStack(serviceConfigEntity.getStack());
     serviceConfigEntityClone.setClusterConfigEntities(serviceConfigEntity.getClusterConfigEntities());
     serviceConfigEntityClone.setClusterId(serviceConfigEntity.getClusterId());
     serviceConfigEntityClone.setHostNames(serviceConfigEntity.getHostNames());

http://git-wip-us.apache.org/repos/asf/ambari/blob/746df034/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
index c7a8ddb..70788ff 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
@@ -49,6 +49,7 @@ import org.apache.ambari.server.orm.dao.HostDAO;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.dao.KerberosPrincipalHostDAO;
 import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
+import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
 import org.apache.ambari.server.orm.entities.HostEntity;
@@ -57,6 +58,7 @@ import org.apache.ambari.server.orm.entities.PermissionEntity;
 import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
+import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.security.SecurityHelper;
 import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority;
 import org.apache.ambari.server.state.AgentVersion;
@@ -74,7 +76,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.security.core.GrantedAuthority;
 
-import com.google.gson.Gson;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import com.google.inject.persist.Transactional;
@@ -118,11 +119,15 @@ public class ClustersImpl implements Clusters {
   @Inject
   AmbariMetaInfo ambariMetaInfo;
   @Inject
-  Gson gson;
-  @Inject
   private SecurityHelper securityHelper;
 
   /**
+   * Data access object for stacks.
+   */
+  @Inject
+  private StackDAO stackDAO;
+
+  /**
    * Used to publish events relating to cluster CRUD operations.
    */
   @Inject
@@ -178,10 +183,12 @@ public class ClustersImpl implements Clusters {
   }
 
   @Override
-  public void addCluster(String clusterName)
+  public void addCluster(String clusterName, StackId stackId)
       throws AmbariException {
     checkLoaded();
 
+    Cluster cluster = null;
+
     w.lock();
     try {
       if (clusters.containsKey(clusterName)) {
@@ -201,11 +208,14 @@ public class ClustersImpl implements Clusters {
       ResourceEntity resourceEntity = new ResourceEntity();
       resourceEntity.setResourceType(resourceTypeEntity);
 
+      StackEntity stackEntity = stackDAO.find(stackId.getStackName(),
+          stackId.getStackVersion());
+
       // retrieve new cluster id
       // add cluster id -> cluster mapping into clustersById
       ClusterEntity clusterEntity = new ClusterEntity();
       clusterEntity.setClusterName(clusterName);
-      clusterEntity.setDesiredStackVersion(gson.toJson(new StackId()));
+      clusterEntity.setDesiredStack(stackEntity);
       clusterEntity.setResource(resourceEntity);
 
       try {
@@ -216,13 +226,15 @@ public class ClustersImpl implements Clusters {
         throw new AmbariException("Unable to create cluster " + clusterName, e);
       }
 
-      Cluster cluster = clusterFactory.create(clusterEntity);
+      cluster = clusterFactory.create(clusterEntity);
       clusters.put(clusterName, cluster);
       clustersById.put(cluster.getClusterId(), cluster);
       clusterHostMap.put(clusterName, new HashSet<Host>());
     } finally {
       w.unlock();
     }
+
+    cluster.setCurrentStackVersion(stackId);
   }
 
   @Override
@@ -261,16 +273,21 @@ public class ClustersImpl implements Clusters {
     }
 
     checkLoaded();
+
+    Cluster cluster = null;
+
     r.lock();
     try {
       if (!clusters.containsKey(clusterName)) {
         throw new ClusterNotFoundException(clusterName);
       }
-      Cluster cluster = clusters.get(clusterName);
-      cluster.setCurrentStackVersion(stackId);
+
+      cluster = clusters.get(clusterName);
     } finally {
       r.unlock();
     }
+
+    cluster.setCurrentStackVersion(stackId);
   }
 
   @Override


Mime
View raw message