You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2014/11/07 01:47:33 UTC

ambari git commit: AMBARI-8148. Rolling Upgrade Bootstrap - Create new tables and populate during the installation of a new cluster (alejandro)

Repository: ambari
Updated Branches:
  refs/heads/trunk 5172bdf2a -> 41cf385ff


AMBARI-8148. Rolling Upgrade Bootstrap - Create new tables and populate during the installation of a new cluster (alejandro)


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

Branch: refs/heads/trunk
Commit: 41cf385ffe59c297f4a1a7c4c72866186fcc4cea
Parents: 5172bdf
Author: Alejandro Fernandez <af...@hortonworks.com>
Authored: Mon Nov 3 19:10:29 2014 -0800
Committer: Alejandro Fernandez <af...@hortonworks.com>
Committed: Thu Nov 6 16:47:12 2014 -0800

----------------------------------------------------------------------
 .../server/orm/entities/ClusterEntity.java      |   9 +
 .../orm/entities/ClusterVersionEntity.java      | 177 +++++++++++++++++++
 .../orm/entities/HostComponentStateEntity.java  |  15 ++
 .../ambari/server/orm/entities/HostEntity.java  |  24 ++-
 .../server/orm/entities/HostVersionEntity.java  | 143 +++++++++++++++
 .../server/state/ClusterVersionState.java       |  81 +++++++++
 .../ambari/server/state/HostVersionState.java   |  49 +++++
 .../server/state/ServiceComponentHost.java      |   2 +
 .../svccomphost/ServiceComponentHostImpl.java   |  25 +++
 .../server/upgrade/UpgradeCatalog200.java       |  65 ++++++-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  39 +++-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  38 +++-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  40 ++++-
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |  38 +++-
 .../src/main/resources/META-INF/persistence.xml |   2 +
 .../server/upgrade/UpgradeCatalog200Test.java   |  47 +++++
 .../src/test/python/TestAmbariServer.py         |   2 +-
 17 files changed, 780 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
index b030ea1..69a2a9d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
@@ -121,6 +121,9 @@ public class ClusterEntity {
   @OneToMany(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
   private Collection<AlertDefinitionEntity> alertDefinitionEntities;
 
+  @OneToMany(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
+  private Collection<ClusterVersionEntity> clusterVersionEntities;
+
   @OneToOne(cascade = CascadeType.ALL)
   @JoinColumns({
       @JoinColumn(name = "resource_id", referencedColumnName = "resource_id", nullable = false)
@@ -285,6 +288,12 @@ public class ClusterEntity {
     return alertDefinitionEntities;
   }
 
+  public Collection<ClusterVersionEntity> getClusterVersionEntities() {
+    return clusterVersionEntities;
+  }
+
+  public void setClusterVersionEntities(Collection<ClusterVersionEntity> clusterVersionEntities) { this.clusterVersionEntities = clusterVersionEntities; }
+
   /**
    * Get the admin resource entity.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/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
new file mode 100644
index 0000000..9daa70e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterVersionEntity.java
@@ -0,0 +1,177 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import org.apache.ambari.server.state.ClusterVersionState;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Enumerated;
+import javax.persistence.EnumType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.TableGenerator;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import java.util.Date;
+
+import static org.apache.commons.lang.StringUtils.defaultString;
+
+@Table(name = "cluster_version")
+@Entity
+@TableGenerator(name = "cluster_version_id_generator",
+    table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
+    , pkColumnValue = "cluster_version_id_seq"
+    , initialValue = 0
+    , allocationSize = 1
+)
+public class ClusterVersionEntity {
+
+  @Id
+  @Column(name = "id", nullable = false, insertable = true, updatable = false)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "cluster_version_id_generator")
+  private Long id;
+
+  @Id
+  @Column(name = "cluster_id", nullable = false, insertable = false, updatable = false)
+  private Long clusterId;
+
+  @ManyToOne
+  @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false)
+  private ClusterEntity clusterEntity;
+
+  @Basic
+  @Column(name = "stack", nullable = false, insertable = true, updatable = true)
+  private String stack = "";
+
+  @Basic
+  @Column(name = "version", nullable = false, insertable = true, updatable = true)
+  private String version = "";
+
+  @Column(name = "state", nullable = false, insertable = true, updatable = true)
+  @Enumerated(value = EnumType.STRING)
+  private ClusterVersionState state = ClusterVersionState.CURRENT;
+
+  @Basic
+  @Column(name = "start_time", nullable = false, insertable = true, updatable = true)
+  private Long startTime = System.currentTimeMillis();
+
+  @Basic
+  @Column(name = "end_time", insertable = true, updatable = true)
+  private Long endTime;
+
+  @Basic
+  @Column(name = "user_name", insertable = true, updatable = true)
+  private String userName = "";
+
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Long getClusterId() {
+    return clusterId;
+  }
+
+  public void setClusterId(Long clusterId) {
+    this.clusterId = clusterId;
+  }
+
+  public ClusterEntity getClusterEntity() {
+    return clusterEntity;
+  }
+
+  public void setClusterEntity(ClusterEntity clusterEntity) {
+    this.clusterEntity = clusterEntity;
+  }
+
+  public String getStack() {
+    return defaultString(stack);
+  }
+
+  public void setStack(String stack) {
+    this.stack = stack;
+  }
+
+  public String getVersion() {
+    return defaultString(version);
+  }
+
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  public ClusterVersionState getState() {
+    return state;
+  }
+
+  public void setState(ClusterVersionState state) {
+    this.state = state;
+  }
+
+  public Long getStartTime() { return startTime; }
+
+  public void setStartTime(Long startTime) { this.startTime = startTime; }
+
+  public Long getEndTime() { return endTime; }
+
+  public void setEndTime(Long endTime) { this.endTime = endTime; }
+
+  public String getUserName() { return defaultString(userName); }
+
+  public void setUserName(String userName) { this.userName = userName; }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ClusterVersionEntity that = (ClusterVersionEntity) o;
+
+    if (this.id != that.id || this.clusterId != that.clusterId || !this.stack.equals(that.stack)
+        || !this.version.equals(that.version) || !this.state.equals(that.state)
+        || !this.startTime.equals(that.startTime) || !this.endTime.equals(that.endTime)
+        || !this.userName.equals(that.userName)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = id !=null ? id.intValue() : 0;
+    result = 31 * result + (clusterId != null ? clusterId.hashCode() : 0);
+    result = 31 * result + (stack != null ? stack.hashCode() : 0);
+    result = 31 * result + (version != null ? version.hashCode() : 0);
+    result = 31 * result + (state != null ? state.hashCode() : 0);
+    result = 31 * result + (startTime != null ? startTime.hashCode() : 0);
+    result = 31 * result + (endTime != null ? stack.hashCode() : 0);
+    result = 31 * result + (userName != null ? userName.hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/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 7dce204..81de777 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
@@ -21,6 +21,7 @@ package org.apache.ambari.server.orm.entities;
 import java.util.Collection;
 
 import org.apache.ambari.server.state.State;
+import org.apache.ambari.server.state.UpgradeState;
 
 import javax.persistence.*;
 
@@ -51,6 +52,10 @@ public class HostComponentStateEntity {
   @Column(name = "current_state", nullable = false, insertable = true, updatable = true)
   private State currentState = State.INIT;
 
+  @Enumerated(value = EnumType.STRING)
+  @Column(name = "upgrade_state", nullable = false, insertable = true, updatable = true)
+  private UpgradeState upgradeState = UpgradeState.NONE;
+
   @Basic
   @Column(name = "current_stack_version", nullable = false, insertable = true, updatable = true)
   private String currentStackVersion;
@@ -106,6 +111,14 @@ public class HostComponentStateEntity {
     this.currentState = currentState;
   }
 
+  public UpgradeState getUpgradeState() {
+    return upgradeState;
+  }
+
+  public void setUpgradeState(UpgradeState upgradeState) {
+    this.upgradeState = upgradeState;
+  }
+
   public String getCurrentStackVersion() {
     return currentStackVersion;
   }
@@ -126,6 +139,7 @@ public class HostComponentStateEntity {
     if (currentStackVersion != null ? !currentStackVersion.equals(that.currentStackVersion) : that.currentStackVersion != 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 (hostName != null ? !hostName.equals(that.hostName) : that.hostName != null) return false;
     if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
 
@@ -138,6 +152,7 @@ public class HostComponentStateEntity {
     result = 31 * result + (hostName != null ? hostName.hashCode() : 0);
     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 + (serviceName != null ? serviceName.hashCode() : 0);
     return result;

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/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 a71fddb..8f850e0 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,7 +18,18 @@
 
 package org.apache.ambari.server.orm.entities;
 
-import javax.persistence.*;
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.Lob;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
 import java.util.Collection;
 
 import static org.apache.commons.lang.StringUtils.defaultString;
@@ -97,6 +108,9 @@ public class HostEntity {
   @OneToMany(mappedBy = "hostEntity", cascade = {CascadeType.REMOVE, CascadeType.PERSIST})
   private Collection<HostComponentStateEntity> hostComponentStateEntities;
 
+  @OneToMany(mappedBy = "hostEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
+  private Collection<HostVersionEntity> hostVersionEntities;
+
   @ManyToMany
   @JoinTable(name = "ClusterHostMapping",
       joinColumns = {@JoinColumn(name = "host_name", referencedColumnName = "host_name")},
@@ -287,4 +301,12 @@ public class HostEntity {
     this.hostRoleCommandEntities = hostRoleCommandEntities;
   }
 
+  public Collection<HostVersionEntity> getHostVersionEntities() {
+    return hostVersionEntities;
+  }
+
+  public void setHostVersionEntities(Collection<HostVersionEntity> hostVersionEntities) { 
+    this.hostVersionEntities = hostVersionEntities;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/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
new file mode 100644
index 0000000..f0a0695
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
@@ -0,0 +1,143 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.orm.entities;
+
+import org.apache.ambari.server.state.HostVersionState;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Enumerated;
+import javax.persistence.EnumType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import static org.apache.commons.lang.StringUtils.defaultString;
+
+@Table(name = "host_version")
+@Entity
+@TableGenerator(name = "host_version_id_generator",
+    table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value"
+    , pkColumnValue = "host_version_id_seq"
+    , initialValue = 0
+    , allocationSize = 1
+)
+public class HostVersionEntity {
+
+  @Id
+  @Column(name = "id", nullable = false, insertable = true, updatable = false)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "host_version_id_generator")
+  private Long id;
+
+  @Column(name = "host_name", nullable = false, insertable = false, updatable = false)
+  @Id
+  private String hostName;
+
+  @ManyToOne
+  @JoinColumn(name = "host_name", referencedColumnName = "host_name", nullable = false)
+  private HostEntity hostEntity;
+
+  @Basic
+  @Column(name = "stack", nullable = false, insertable = true, updatable = true)
+  private String stack = "";
+
+  @Basic
+  @Column(name = "version", nullable = false, insertable = true, updatable = true)
+  private String version = "";
+
+  @Column(name = "state", nullable = false, insertable = true, updatable = true)
+  @Enumerated(value = EnumType.STRING)
+  private HostVersionState state = HostVersionState.CURRENT;
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public String getHostName() {
+    return hostName;
+  }
+
+  public void setHostName(String hostName) {
+    this.hostName = hostName;
+  }
+
+  public HostEntity getHostEntity() {
+    return hostEntity;
+  }
+
+  public void setHostEntity(HostEntity hostEntity) {
+    this.hostEntity = hostEntity;
+  }
+
+  public String getStack() {
+    return defaultString(stack);
+  }
+
+  public void setStack(String stack) {
+    this.stack = stack;
+  }
+
+  public String getVersion() {
+    return defaultString(version);
+  }
+
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  public HostVersionState getState() {
+    return state;
+  }
+
+  public void setState(HostVersionState state) {
+    this.state = state;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    HostVersionEntity that = (HostVersionEntity) o;
+
+    if (this.id != that.id || !this.hostName.equals(that.hostName) || !this.stack.equals(that.stack)
+        || !this.version.equals(that.version) || !this.state.equals(that.state)) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = id !=null ? id.intValue() : 0;
+    result = 31 * result + (hostName != null ? hostName.hashCode() : 0);
+    result = 31 * result + (stack != null ? stack.hashCode() : 0);
+    result = 31 * result + (version != null ? version.hashCode() : 0);
+    result = 31 * result + (state != null ? state.hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterVersionState.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterVersionState.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterVersionState.java
new file mode 100644
index 0000000..72cd541
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ClusterVersionState.java
@@ -0,0 +1,81 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.state;
+
+/**
+ * There must be exactly one cluster version that is in a CURRENT state.
+ * There may be 0 or more cluster versions in an INSTALLED state.
+ * A new cluster version transitions from UPGRADING -> CURRENT | UPGRADE_FAILED
+ * The operation to transition a new cluster version into CURRENT must be atomic and change the existing cluster version
+ * from CURRENT to INSTALLED.
+ *
+ * <pre>
+ * Step 1: Initial Configuration
+ * Version 1 is CURRENT
+ *
+ * Step 2: Add another repository and start an upgrade from Version 1 to Version 2
+ * Version 1: CURRENT
+ * Version 2: UPGRADING
+ *
+ * Step 3: Upgrade can either complete successfully or fail
+ * Version 1: CURRENT
+ * Version 2: UPGRADE_FAILED (a retry can set this back to UPGRADING)
+ *
+ * or
+ *
+ * Version 1: INSTALLED
+ * Version 2: CURRENT
+ *
+ * Step 4: May revert to the original version via a downgrade, which is technically still an upgrade to a version.
+ * Version 1: UPGRADING
+ * Version 2: CURRENT
+ *
+ * and eventually becomes
+ *
+ * Version 1: CURRENT
+ * Version 2: INSTALLED
+ *
+ * *********************************************
+ * Start states: CURRENT, UPGRADING
+ * Allowed Transitions:
+ * UPGRADING -> CURRENT | UPGRADE_FAILED
+ * UPGRADE_FAILED -> UPGRADING
+ * CURRENT -> INSTALLED
+ * INSTALLED -> UPGRADING
+ * </pre>
+ */
+public enum ClusterVersionState {
+  /**
+   * Cluster version that is installed and supported but not the active version.
+   */
+  INSTALLED,
+  /**
+   * Cluster version that is installed and supported and is the active version.
+   */
+  CURRENT,
+  /**
+   * Cluster version that is in the process of upgrading to become the CURRENT active version,
+   * and the previous active version transitions to an INSTALLED state.
+   */
+  UPGRADING,
+  /**
+   * Cluster version that during the upgrade process failed to become the active version and must be remedied.
+   */
+  UPGRADE_FAILED;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/java/org/apache/ambari/server/state/HostVersionState.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/HostVersionState.java b/ambari-server/src/main/java/org/apache/ambari/server/state/HostVersionState.java
new file mode 100644
index 0000000..b0a0ee2
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/HostVersionState.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.server.state;
+
+/**
+ * There must be exactly one stack version that is in the CURRENT state.
+ * There may be 0 or more stack versions in an INSTALLED state.
+ * Installing a new stack version on a host transitions from NOT_INSTALLED to CURRENT once the upgrade finishes.
+ * The operation to transition a new stack version on the host from the NOT_INSTALLED state to CURRENT must be atomic
+ * and change the existing stack version on the host from CURRENT to INSTALLED.
+ *
+ * <pre>
+ * Start states: CURRENT, NOT_INSTALLED
+ * Allowed Transitions:
+ * NOT_INSTALLED -> CURRENT
+ * CURRENT -> INSTALLED
+ * INSTALLED -> CURRENT
+ * </pre>
+ */
+public enum HostVersionState {
+  /**
+   * Stack version that is installed on this host for all of its components but is not the active stack version on the host.
+   */
+  INSTALLED,
+  /**
+   * Stack version that is installed on this host for all of its components and is the active stack version on the host.
+   */
+  CURRENT,
+  /**
+   * Stack version that remains to be installed on this host, potentially because it is in the process of being installed.
+   */
+  NOT_INSTALLED;
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java
index 3718556..3142974 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceComponentHost.java
@@ -77,6 +77,8 @@ public interface ServiceComponentHost {
   public State getState();
 
   public void setState(State state);
+
+  public void setUpgradeState(UpgradeState upgradeState);
   
   public StackId getStackVersion();
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
index bc97936..606751d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
@@ -58,6 +58,7 @@ import org.apache.ambari.server.state.ServiceComponentHostEvent;
 import org.apache.ambari.server.state.ServiceComponentHostEventType;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
+import org.apache.ambari.server.state.UpgradeState;
 import org.apache.ambari.server.state.alert.AlertDefinitionHash;
 import org.apache.ambari.server.state.configgroup.ConfigGroup;
 import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
@@ -677,6 +678,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
     stateEntity.setServiceName(serviceComponent.getServiceName());
     stateEntity.setHostName(hostName);
     stateEntity.setCurrentState(stateMachine.getCurrentState());
+    stateEntity.setUpgradeState(UpgradeState.NONE);
     stateEntity.setCurrentStackVersion(gson.toJson(new StackId()));
 
     desiredStateEntity = new HostComponentDesiredStateEntity();
@@ -766,7 +768,30 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
     } finally {
       clusterGlobalLock.readLock().unlock();
     }
+  }
 
+  /***
+   * To be called during the upgrade of a specific Component in a host.
+   * The potential upgrade states are NONE (default), PENDING, IN_PROGRESS, FAILED.
+   * If the upgrade completes successfully, the upgradeState should be set back to NONE.
+   * If the upgrade fails, then the user can retry to set it back into PENDING or IN_PROGRESS.
+   * If the upgrade is aborted, then the upgradeState should be set back to NONE.
+   * @param upgradeState
+   */
+  @Override
+  public void setUpgradeState(UpgradeState upgradeState) {
+    clusterGlobalLock.readLock().lock();
+    try {
+      writeLock.lock();
+      try {
+        stateEntity.setUpgradeState(upgradeState);
+        saveIfPersisted();
+      } finally {
+        writeLock.unlock();
+      }
+    } finally {
+      clusterGlobalLock.readLock().unlock();
+    }
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
index 14c385d..b1523fe 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog200.java
@@ -18,16 +18,18 @@
 
 package org.apache.ambari.server.upgrade;
 
-import java.sql.SQLException;
-
+import com.google.inject.Inject;
+import com.google.inject.Injector;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.orm.DBAccessor.DBColumnInfo;
+import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.dao.DaoUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
 
-import com.google.inject.Inject;
-import com.google.inject.Injector;
 
 /**
  * Upgrade catalog for version 2.0.0.
@@ -52,7 +54,7 @@ public class UpgradeCatalog200 extends AbstractUpgradeCatalog {
    */
   @Override
   public String getTargetVersion() {
-    return "1.2.0";
+    return "2.0.0";
   }
 
   /**
@@ -61,10 +63,11 @@ public class UpgradeCatalog200 extends AbstractUpgradeCatalog {
   private static final Logger LOG = LoggerFactory.getLogger
       (UpgradeCatalog200.class);
 
+  // ----- Constructors ------------------------------------------------------
+
   /**
-   * Constructor.
-   *
-   * @param injector
+   * Don't forget to register new UpgradeCatalogs in {@link org.apache.ambari.server.upgrade.SchemaUpgradeHelper.UpgradeHelperModule#configure()}
+   * @param injector Guice injector to track dependencies and uses bindings to inject them.
    */
   @Inject
   public UpgradeCatalog200(Injector injector) {
@@ -72,20 +75,66 @@ public class UpgradeCatalog200 extends AbstractUpgradeCatalog {
     this.injector = injector;
   }
 
+  // ----- AbstractUpgradeCatalog --------------------------------------------
+
   /**
    * {@inheritDoc}
    */
   @Override
   protected void executeDDLUpdates() throws AmbariException, SQLException {
+    prepareRollingUpgradesDDL();
+
     // add ignore_host column to alert_definition
     dbAccessor.addColumn(ALERT_TABLE_DEFINITION, new DBColumnInfo(
         "ignore_host", Short.class, 1, 0, false));
   }
 
   /**
+   * Add any columns, tables, and keys needed for Rolling Upgrades.
+   * @throws SQLException
+   */
+  private void prepareRollingUpgradesDDL() throws SQLException {
+    List<DBAccessor.DBColumnInfo> columns = new ArrayList<DBAccessor.DBColumnInfo>();
+
+    // New columns
+    dbAccessor.addColumn("hostcomponentstate", new DBAccessor.DBColumnInfo("upgrade_state",
+        String.class, 32, "NONE", false));
+
+    // New tables
+    columns.add(new DBAccessor.DBColumnInfo("id", Long.class, null, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("cluster_id", Long.class, null, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("stack", String.class, 255, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("version", String.class, 255, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("state", String.class, 32, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("start_time", Long.class, null, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("end_time", Long.class, null, null, true));
+    columns.add(new DBAccessor.DBColumnInfo("user_name", String.class, 32, null, true));
+    dbAccessor.createTable("cluster_version", columns, "id");
+
+    columns = new ArrayList<DBColumnInfo>();
+    columns.add(new DBAccessor.DBColumnInfo("id", Long.class, null, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("host_name", String.class, 255, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("stack", String.class, 255, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("version", String.class, 255, null, false));
+    columns.add(new DBAccessor.DBColumnInfo("state", String.class, 32, null, false));
+    dbAccessor.createTable("host_version", columns, "id");
+
+    // Foreign Key Constraints
+    dbAccessor.addFKConstraint("cluster_version", "FK_cluster_version_cluster_id", "cluster_id", "clusters", "cluster_id", false);
+    dbAccessor.addFKConstraint("host_version", "FK_host_version_host_name", "host_name", "hosts", "host_name", false);
+
+    // New sequences
+    dbAccessor.executeQuery("INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES('cluster_version_id_seq', 0)", false);
+    dbAccessor.executeQuery("INSERT INTO ambari_sequences(sequence_name, sequence_value) VALUES('host_version_id_seq', 0)", false);
+  }
+
+  // ----- UpgradeCatalog ----------------------------------------------------
+
+  /**
    * {@inheritDoc}
    */
   @Override
   protected void executeDMLUpdates() throws AmbariException, SQLException {
+
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 9054b3f..7646b73 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -33,10 +33,42 @@ CREATE TABLE serviceconfighosts (service_config_id BIGINT NOT NULL, hostname VAR
 CREATE TABLE serviceconfigmapping (service_config_id BIGINT NOT NULL, config_id BIGINT NOT NULL, PRIMARY KEY(service_config_id, config_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));
+
+CREATE TABLE cluster_version (
+  id BIGINT NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  stack VARCHAR(255) NOT NULL,
+  state VARCHAR(32) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  start_time BIGINT NOT NULL,
+  end_time BIGINT,
+  user_name VARCHAR(32),
+  PRIMARY KEY (id));
+
 CREATE TABLE hostcomponentdesiredstate (cluster_id BIGINT NOT NULL, component_name VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, host_name VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, admin_state VARCHAR(32), maintenance_state VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', restart_required TINYINT(1) NOT NULL DEFAULT 0, PRIMARY KEY (cluster_id, component_name, host_name, service_name));
-CREATE TABLE hostcomponentstate (cluster_id BIGINT NOT NULL, component_name VARCHAR(255) NOT NULL, current_stack_version VARCHAR(255) NOT NULL, current_state VARCHAR(255) NOT NULL, host_name VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id, component_name, host_name, service_name));
+
+CREATE TABLE hostcomponentstate (
+  cluster_id BIGINT NOT NULL,
+  component_name VARCHAR(255) NOT NULL,
+  current_stack_version VARCHAR(255) NOT NULL,
+  current_state VARCHAR(255) NOT NULL,
+  host_name VARCHAR(255) NOT NULL,
+  service_name VARCHAR(255) NOT NULL,
+  upgrade_state VARCHAR(32) NOT NULL DEFAULT 'NONE',
+  PRIMARY KEY (cluster_id, component_name, host_name, service_name));
+
 CREATE TABLE hosts (host_name VARCHAR(255) NOT NULL, cpu_count INTEGER NOT NULL, cpu_info VARCHAR(255) NOT NULL, discovery_status VARCHAR(2000) NOT NULL, host_attributes LONGTEXT NOT NULL, ipv4 VARCHAR(255), ipv6 VARCHAR(255), last_registration_time BIGINT NOT NULL, os_arch VARCHAR(255) NOT NULL, os_info VARCHAR(1000) NOT NULL, os_type VARCHAR(255) NOT NULL, ph_cpu_count INTEGER, public_host_name VARCHAR(255), rack_info VARCHAR(255) NOT NULL, total_mem BIGINT NOT NULL, PRIMARY KEY (host_name));
 CREATE TABLE hoststate (agent_version VARCHAR(255) NOT NULL, available_mem BIGINT NOT NULL, current_state VARCHAR(255) NOT NULL, health_status VARCHAR(255), host_name VARCHAR(255) NOT NULL, time_in_state BIGINT NOT NULL, maintenance_state VARCHAR(512), PRIMARY KEY (host_name));
+
+CREATE TABLE host_version (
+  id BIGINT NOT NULL,
+  host_name VARCHAR(255) NOT NULL,
+  stack VARCHAR(255) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  state VARCHAR(32) NOT NULL,
+  PRIMARY KEY (id));
+
+
 CREATE TABLE servicecomponentdesiredstate (component_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, PRIMARY KEY (component_name, cluster_id, service_name));
 CREATE TABLE servicedesiredstate (cluster_id BIGINT NOT NULL, desired_host_role_mapping INTEGER NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, maintenance_state VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', PRIMARY KEY (cluster_id, service_name));
 CREATE TABLE users (user_id INTEGER, principal_id BIGINT NOT NULL, create_time TIMESTAMP DEFAULT NOW(), ldap_user INTEGER NOT NULL DEFAULT 0, user_name VARCHAR(255) NOT NULL, user_password VARCHAR(255), active INTEGER NOT NULL DEFAULT 1, PRIMARY KEY (user_id));
@@ -97,11 +129,13 @@ ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY
 ALTER TABLE clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE clusterstate ADD CONSTRAINT FK_clusterstate_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
+ALTER TABLE cluster_version ADD CONSTRAINT FK_cluster_version_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE hostcomponentdesiredstate ADD CONSTRAINT hstcmponentdesiredstatehstname FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE hostcomponentdesiredstate ADD CONSTRAINT hstcmpnntdesiredstatecmpnntnme FOREIGN KEY (component_name, cluster_id, service_name) REFERENCES servicecomponentdesiredstate (component_name, cluster_id, service_name);
 ALTER TABLE hostcomponentstate ADD CONSTRAINT hstcomponentstatecomponentname FOREIGN KEY (component_name, cluster_id, service_name) REFERENCES servicecomponentdesiredstate (component_name, cluster_id, service_name);
 ALTER TABLE hostcomponentstate ADD CONSTRAINT hostcomponentstate_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE hoststate ADD CONSTRAINT FK_hoststate_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
+ALTER TABLE host_version ADD CONSTRAINT FK_host_version_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE servicecomponentdesiredstate ADD CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id);
 ALTER TABLE servicedesiredstate ADD CONSTRAINT servicedesiredstateservicename FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id);
 ALTER TABLE execution_command ADD CONSTRAINT FK_execution_command_task_id FOREIGN KEY (task_id) REFERENCES host_role_command (task_id);
@@ -251,6 +285,7 @@ CREATE INDEX idx_alert_history_state on alert_history(alert_state);
 CREATE INDEX idx_alert_group_name on alert_group(group_name);
 CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 
+-- In order for the first ID to be 1, must initialize the ambari_sequences table with a sequence_value of 0.
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_role_command_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('user_id_seq', 2);
@@ -269,6 +304,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_i
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('permission_id_seq', 5);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('privilege_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('config_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_version_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_version_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_config_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_definition_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_group_id_seq', 0);

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index abe8b39..6e5e68b 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -24,10 +24,41 @@ CREATE TABLE serviceconfighosts (service_config_id NUMBER(19) NOT NULL, hostname
 CREATE TABLE serviceconfigmapping (service_config_id NUMBER(19) NOT NULL, config_id NUMBER(19) NOT NULL, PRIMARY KEY(service_config_id, config_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));
+
+CREATE TABLE cluster_version (
+  id BIGINT NUMBER(19) NULL,
+  cluster_id NUMBER(19) NOT NULL,
+  stack VARCHAR2(255) NOT NULL,
+  version VARCHAR2(255) NOT NULL,
+  state VARCHAR2(32) NOT NULL,
+  start_time NUMBER(19) NOT NULL,
+  end_time NUMBER(19),
+  user_name VARCHAR2(32),
+  PRIMARY KEY (id));
+
 CREATE TABLE hostcomponentdesiredstate (cluster_id NUMBER(19) NOT NULL, component_name VARCHAR2(255) NOT NULL, desired_stack_version VARCHAR2(255) NULL, desired_state VARCHAR2(255) NOT NULL, host_name VARCHAR2(255) NOT NULL, service_name VARCHAR2(255) NOT NULL, admin_state VARCHAR2(32) NULL, maintenance_state VARCHAR2(32) NOT NULL, restart_required NUMBER(1) DEFAULT 0 NOT NULL, PRIMARY KEY (cluster_id, component_name, host_name, service_name));
-CREATE TABLE hostcomponentstate (cluster_id NUMBER(19) NOT NULL, component_name VARCHAR2(255) NOT NULL, current_stack_version VARCHAR2(255) NOT NULL, current_state VARCHAR2(255) NOT NULL, host_name VARCHAR2(255) NOT NULL, service_name VARCHAR2(255) NOT NULL, PRIMARY KEY (cluster_id, component_name, host_name, service_name));
+
+CREATE TABLE hostcomponentstate (
+  cluster_id NUMBER(19) NOT NULL,
+  component_name VARCHAR2(255) NOT NULL,
+  current_stack_version VARCHAR2(255) NOT NULL,
+  current_state VARCHAR2(255) NOT NULL,
+  host_name VARCHAR2(255) NOT NULL,
+  service_name VARCHAR2(255) NOT NULL,
+  upgrade_state VARCHAR2(255) NOT NULL DEFAULT 'NONE',
+  PRIMARY KEY (cluster_id, component_name, host_name, service_name));
+
 CREATE TABLE hosts (host_name VARCHAR2(255) NOT NULL, cpu_count INTEGER NOT NULL, cpu_info VARCHAR2(255) NULL, discovery_status VARCHAR2(2000) NULL, host_attributes CLOB NULL, ipv4 VARCHAR2(255) NULL, ipv6 VARCHAR2(255) NULL, last_registration_time INTEGER NOT NULL, os_arch VARCHAR2(255) NULL, os_info VARCHAR2(1000) NULL, os_type VARCHAR2(255) NULL, ph_cpu_count INTEGER NOT NULL, public_host_name VARCHAR2(255) NULL, rack_info VARCHAR2(255) NOT NULL, total_mem INTEGER NOT NULL, PRIMARY KEY (host_name));
 CREATE TABLE hoststate (agent_version VARCHAR2(255) NULL, available_mem NUMBER(19) NOT NULL, current_state VARCHAR2(255) NOT NULL, health_status VARCHAR2(255) NULL, host_name VARCHAR2(255) NOT NULL, time_in_state NUMBER(19) NOT NULL, maintenance_state VARCHAR2(512), PRIMARY KEY (host_name));
+
+CREATE TABLE host_version (
+  id NUMBER(19) NOT NULL,
+  host_name VARCHAR2(255) NOT NULL,
+  stack VARCHAR2(255) NOT NULL,
+  version VARCHAR2(255) NOT NULL,
+  state VARCHAR2(32) NOT NULL,
+  PRIMARY KEY (id));
+
 CREATE TABLE servicecomponentdesiredstate (component_name VARCHAR2(255) NOT NULL, cluster_id NUMBER(19) NOT NULL, desired_stack_version VARCHAR2(255) NULL, desired_state VARCHAR2(255) NOT NULL, service_name VARCHAR2(255) NOT NULL, PRIMARY KEY (component_name, cluster_id, service_name));
 CREATE TABLE servicedesiredstate (cluster_id NUMBER(19) NOT NULL, desired_host_role_mapping NUMBER(10) NOT NULL, desired_stack_version VARCHAR2(255) NULL, desired_state VARCHAR2(255) NOT NULL, service_name VARCHAR2(255) NOT NULL, maintenance_state VARCHAR2(32) NOT NULL, PRIMARY KEY (cluster_id, service_name));
 CREATE TABLE users (user_id NUMBER(10) NOT NULL, principal_id NUMBER(19) NOT NULL, create_time TIMESTAMP NULL, ldap_user NUMBER(10) DEFAULT 0, user_name VARCHAR2(255) NULL, user_password VARCHAR2(255) NULL, active INTEGER DEFAULT 1 NOT NULL, PRIMARY KEY (user_id));
@@ -89,11 +120,13 @@ ALTER TABLE serviceconfighosts ADD CONSTRAINT  FK_scvhosts_scv FOREIGN KEY (serv
 ALTER TABLE clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE clusterstate ADD CONSTRAINT FK_clusterstate_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
+ALTER TABLE cluster_version ADD CONSTRAINT FK_cluster_version_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE hostcomponentdesiredstate ADD CONSTRAINT hstcmponentdesiredstatehstname FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE hostcomponentdesiredstate ADD CONSTRAINT hstcmpnntdesiredstatecmpnntnme FOREIGN KEY (component_name, cluster_id, service_name) REFERENCES servicecomponentdesiredstate (component_name, cluster_id, service_name);
 ALTER TABLE hostcomponentstate ADD CONSTRAINT hstcomponentstatecomponentname FOREIGN KEY (component_name, cluster_id, service_name) REFERENCES servicecomponentdesiredstate (component_name, cluster_id, service_name);
 ALTER TABLE hostcomponentstate ADD CONSTRAINT hostcomponentstate_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE hoststate ADD CONSTRAINT FK_hoststate_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
+ALTER TABLE host_version ADD CONSTRAINT FK_host_version_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE servicecomponentdesiredstate ADD CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id);
 ALTER TABLE servicedesiredstate ADD CONSTRAINT servicedesiredstateservicename FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id);
 ALTER TABLE execution_command ADD CONSTRAINT FK_execution_command_task_id FOREIGN KEY (task_id) REFERENCES host_role_command (task_id);
@@ -243,6 +276,7 @@ CREATE INDEX idx_alert_group_name on alert_group(group_name);
 CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 
 ---------inserting some data-----------
+-- In order for the first ID to be 1, must initialize the ambari_sequences table with a sequence_value of 0.
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_role_command_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('user_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('group_id_seq', 0);
@@ -261,6 +295,8 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('principal_i
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('permission_id_seq', 5);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('privilege_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('config_id_seq', 1);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('cluster_version_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('host_version_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('service_config_id_seq', 1);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_definition_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('alert_group_id_seq', 0);

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 0bea067..226b9b5 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -16,7 +16,7 @@
 -- limitations under the License.
 --
 
-------create tables ang grant privileges to db user---------
+------create tables and grant privileges to db user---------
 CREATE TABLE clusters (cluster_id BIGINT NOT NULL, resource_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 (config_id BIGINT NOT NULL, version_tag VARCHAR(255) NOT NULL, version BIGINT NOT NULL, type_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, config_data TEXT NOT NULL, config_attributes VARCHAR(32000), create_timestamp BIGINT NOT NULL, PRIMARY KEY (config_id));
@@ -33,19 +33,46 @@ CREATE TABLE clusterservices (service_name VARCHAR(255) NOT NULL, cluster_id BIG
 
 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));
 
+CREATE TABLE cluster_version (
+  id BIGINT NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  stack VARCHAR(255) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  state VARCHAR(32) NOT NULL,
+  start_time BIGINT NOT NULL,
+  end_time BIGINT,
+  user_name VARCHAR(32),
+  PRIMARY KEY (id));
+
 CREATE TABLE hostcomponentdesiredstate (cluster_id BIGINT NOT NULL, component_name VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, host_name VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, admin_state VARCHAR(32), maintenance_state VARCHAR(32) NOT NULL, restart_required SMALLINT NOT NULL DEFAULT 0, PRIMARY KEY (cluster_id, component_name, host_name, service_name));
 
-CREATE TABLE hostcomponentstate (cluster_id BIGINT NOT NULL, component_name VARCHAR(255) NOT NULL, current_stack_version VARCHAR(255) NOT NULL, current_state VARCHAR(255) NOT NULL, host_name VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id, component_name, host_name, service_name));
+CREATE TABLE hostcomponentstate (
+  cluster_id BIGINT NOT NULL,
+  component_name VARCHAR(255) NOT NULL,
+  current_stack_version VARCHAR(255) NOT NULL,
+  current_state VARCHAR(255) NOT NULL,
+  host_name VARCHAR(255) NOT NULL,
+  service_name VARCHAR(255) NOT NULL,
+  upgrade_state VARCHAR(32) NOT NULL DEFAULT 'NONE',
+  PRIMARY KEY (cluster_id, component_name, host_name, service_name));
 
 CREATE TABLE hosts (host_name VARCHAR(255) NOT NULL, cpu_count INTEGER NOT NULL, ph_cpu_count INTEGER, cpu_info VARCHAR(255) NOT NULL, discovery_status VARCHAR(2000) NOT NULL, host_attributes VARCHAR(20000) NOT NULL, ipv4 VARCHAR(255), ipv6 VARCHAR(255), public_host_name VARCHAR(255), last_registration_time BIGINT NOT NULL, os_arch VARCHAR(255) NOT NULL, os_info VARCHAR(1000) NOT NULL, os_type VARCHAR(255) NOT NULL, rack_info VARCHAR(255) NOT NULL, total_mem BIGINT NOT NULL, PRIMARY KEY (host_name));
 
 CREATE TABLE hoststate (agent_version VARCHAR(255) NOT NULL, available_mem BIGINT NOT NULL, current_state VARCHAR(255) NOT NULL, health_status VARCHAR(255), host_name VARCHAR(255) NOT NULL, time_in_state BIGINT NOT NULL, maintenance_state VARCHAR(512), PRIMARY KEY (host_name));
 
+CREATE TABLE host_version (
+  id BIGINT NOT NULL,
+  host_name VARCHAR(255) NOT NULL,
+  stack VARCHAR(255) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  state VARCHAR(32) NOT NULL,
+  PRIMARY KEY (id));
+
 CREATE TABLE servicecomponentdesiredstate (component_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, PRIMARY KEY (component_name, cluster_id, service_name));
 
 CREATE TABLE servicedesiredstate (cluster_id BIGINT NOT NULL, desired_host_role_mapping INTEGER NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, maintenance_state VARCHAR(32) NOT NULL, PRIMARY KEY (cluster_id, service_name));
 
-CREATE TABLE users (user_id INTEGER, principal_id BIGINT NOT NULL, ldap_user INTEGER NOT NULL DEFAULT 0, user_name VARCHAR(255) NOT NULL, create_time TIMESTAMP DEFAULT NOW(), user_password VARCHAR(255), PRIMARY KEY (user_id), active INTEGER NOT NULL DEFAULT 1, UNIQUE (ldap_user, user_name));
+CREATE TABLE users (user_id INTEGER, principal_id BIGINT NOT NULL, ldap_user INTEGER NOT NULL DEFAULT 0, user_name VARCHAR(255) NOT NULL, create_time TIMESTAMP DEFAULT NOW(), user_password VARCHAR(255), active INTEGER NOT NULL DEFAULT 1, PRIMARY KEY (user_id), UNIQUE (ldap_user, user_name));
 
 CREATE TABLE groups (group_id INTEGER, principal_id BIGINT NOT NULL, group_name VARCHAR(255) NOT NULL, ldap_group INTEGER NOT NULL DEFAULT 0, PRIMARY KEY (group_id), UNIQUE (ldap_group, group_name));
 
@@ -121,11 +148,13 @@ ALTER TABLE clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FOREIGN KEY
 ALTER TABLE clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE clusterstate ADD CONSTRAINT FK_clusterstate_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
+ALTER TABLE cluster_version ADD CONSTRAINT FK_cluster_version_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id);
 ALTER TABLE hostcomponentdesiredstate ADD CONSTRAINT hstcmponentdesiredstatehstname FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE hostcomponentdesiredstate ADD CONSTRAINT hstcmpnntdesiredstatecmpnntnme FOREIGN KEY (component_name, cluster_id, service_name) REFERENCES servicecomponentdesiredstate (component_name, cluster_id, service_name);
 ALTER TABLE hostcomponentstate ADD CONSTRAINT hstcomponentstatecomponentname FOREIGN KEY (component_name, cluster_id, service_name) REFERENCES servicecomponentdesiredstate (component_name, cluster_id, service_name);
 ALTER TABLE hostcomponentstate ADD CONSTRAINT hostcomponentstate_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE hoststate ADD CONSTRAINT FK_hoststate_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
+ALTER TABLE host_version ADD CONSTRAINT FK_host_version_host_name FOREIGN KEY (host_name) REFERENCES hosts (host_name);
 ALTER TABLE servicecomponentdesiredstate ADD CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id);
 ALTER TABLE servicedesiredstate ADD CONSTRAINT servicedesiredstateservicename FOREIGN KEY (service_name, cluster_id) REFERENCES clusterservices (service_name, cluster_id);
 ALTER TABLE execution_command ADD CONSTRAINT FK_execution_command_task_id FOREIGN KEY (task_id) REFERENCES host_role_command (task_id);
@@ -275,6 +304,7 @@ CREATE INDEX idx_alert_group_name on alert_group(group_name);
 CREATE INDEX idx_alert_notice_state on alert_notice(notify_state);
 
 ---------inserting some data-----------
+-- In order for the first ID to be 1, must initialize the ambari_sequences table with a sequence_value of 0.
 BEGIN;
   INSERT INTO ambari_sequences (sequence_name, sequence_value)
   SELECT 'cluster_id_seq', 1
@@ -325,6 +355,10 @@ BEGIN;
   union all
   select 'config_id_seq', 1
   union all
+  select 'cluster_version_id_seq', 0
+  union all
+  select 'host_version_id_seq', 0
+  union all
   select 'service_config_id_seq', 1;
 
   INSERT INTO adminresourcetype (resource_type_id, resource_type_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index ebc8f5c..0996ab1 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -52,10 +52,30 @@ GRANT ALL PRIVILEGES ON TABLE ambari.clusterservices TO :username;
 CREATE TABLE ambari.clusterstate (cluster_id BIGINT NOT NULL, current_cluster_state VARCHAR(255) NOT NULL, current_stack_version VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id));
 GRANT ALL PRIVILEGES ON TABLE ambari.clusterstate TO :username;
 
+CREATE TABLE cluster_version (
+  id BIGINT NOT NULL,
+  cluster_id BIGINT NOT NULL,
+  stack VARCHAR(255) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  state VARCHAR(32) NOT NULL,
+  start_time BIGINT NOT NULL,
+  end_time BIGINT,
+  user_name VARCHAR(32),
+  PRIMARY KEY (id));
+GRANT ALL PRIVILEGES ON TABLE ambari.cluster_version TO :username;
+
 CREATE TABLE ambari.hostcomponentdesiredstate (cluster_id BIGINT NOT NULL, component_name VARCHAR(255) NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, host_name VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, admin_state VARCHAR(32), maintenance_state VARCHAR(32) NOT NULL, restart_required SMALLINT NOT NULL DEFAULT 0, PRIMARY KEY (cluster_id, component_name, host_name, service_name));
 GRANT ALL PRIVILEGES ON TABLE ambari.hostcomponentdesiredstate TO :username;
 
-CREATE TABLE ambari.hostcomponentstate (cluster_id BIGINT NOT NULL, component_name VARCHAR(255) NOT NULL, current_stack_version VARCHAR(255) NOT NULL, current_state VARCHAR(255) NOT NULL, host_name VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, PRIMARY KEY (cluster_id, component_name, host_name, service_name));
+CREATE TABLE ambari.hostcomponentstate (
+  cluster_id BIGINT NOT NULL,
+  component_name VARCHAR(255) NOT NULL,
+  current_stack_version VARCHAR(255) NOT NULL,
+  current_state VARCHAR(255) NOT NULL,
+  host_name VARCHAR(255) NOT NULL,
+  service_name VARCHAR(255) NOT NULL,
+  upgrade_state VARCHAR(32) NOT NULL DEFAULT 'NONE',
+  PRIMARY KEY (cluster_id, component_name, host_name, service_name));
 GRANT ALL PRIVILEGES ON TABLE ambari.hostcomponentstate TO :username;
 
 CREATE TABLE ambari.hosts (host_name VARCHAR(255) NOT NULL, cpu_count INTEGER NOT NULL, ph_cpu_count INTEGER, cpu_info VARCHAR(255) NOT NULL, discovery_status VARCHAR(2000) NOT NULL, host_attributes VARCHAR(20000) NOT NULL, ipv4 VARCHAR(255), ipv6 VARCHAR(255), public_host_name VARCHAR(255), last_registration_time BIGINT NOT NULL, os_arch VARCHAR(255) NOT NULL, os_info VARCHAR(1000) NOT NULL, os_type VARCHAR(255) NOT NULL, rack_info VARCHAR(255) NOT NULL, total_mem BIGINT NOT NULL, PRIMARY KEY (host_name));
@@ -64,6 +84,15 @@ GRANT ALL PRIVILEGES ON TABLE ambari.hosts TO :username;
 CREATE TABLE ambari.hoststate (agent_version VARCHAR(255) NOT NULL, available_mem BIGINT NOT NULL, current_state VARCHAR(255) NOT NULL, health_status VARCHAR(255), host_name VARCHAR(255) NOT NULL, time_in_state BIGINT NOT NULL, maintenance_state VARCHAR(512), PRIMARY KEY (host_name));
 GRANT ALL PRIVILEGES ON TABLE ambari.hoststate TO :username;
 
+CREATE TABLE host_version (
+  id BIGINT NOT NULL,
+  host_name VARCHAR(255) NOT NULL,
+  stack VARCHAR(255) NOT NULL,
+  version VARCHAR(255) NOT NULL,
+  state VARCHAR(32) NOT NULL,
+  PRIMARY KEY (id));
+GRANT ALL PRIVILEGES ON TABLE ambari.host_version TO :username;
+
 CREATE TABLE ambari.servicecomponentdesiredstate (component_name VARCHAR(255) NOT NULL, cluster_id BIGINT NOT NULL, desired_stack_version VARCHAR(255) NOT NULL, desired_state VARCHAR(255) NOT NULL, service_name VARCHAR(255) NOT NULL, PRIMARY KEY (component_name, cluster_id, service_name));
 GRANT ALL PRIVILEGES ON TABLE ambari.servicecomponentdesiredstate TO :username;
 
@@ -184,11 +213,13 @@ ALTER TABLE ambari.clusterconfig ADD CONSTRAINT FK_clusterconfig_cluster_id FORE
 ALTER TABLE ambari.clusterservices ADD CONSTRAINT FK_clusterservices_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.clusterconfigmapping ADD CONSTRAINT clusterconfigmappingcluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.clusterstate ADD CONSTRAINT FK_clusterstate_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
+ALTER TABLE ambari.cluster_version ADD CONSTRAINT FK_cluster_version_cluster_id FOREIGN KEY (cluster_id) REFERENCES ambari.clusters (cluster_id);
 ALTER TABLE ambari.hostcomponentdesiredstate ADD CONSTRAINT hstcmponentdesiredstatehstname FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
 ALTER TABLE ambari.hostcomponentdesiredstate ADD CONSTRAINT hstcmpnntdesiredstatecmpnntnme FOREIGN KEY (component_name, cluster_id, service_name) REFERENCES ambari.servicecomponentdesiredstate (component_name, cluster_id, service_name);
 ALTER TABLE ambari.hostcomponentstate ADD CONSTRAINT hstcomponentstatecomponentname FOREIGN KEY (component_name, cluster_id, service_name) REFERENCES ambari.servicecomponentdesiredstate (component_name, cluster_id, service_name);
 ALTER TABLE ambari.hostcomponentstate ADD CONSTRAINT hostcomponentstate_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
 ALTER TABLE ambari.hoststate ADD CONSTRAINT FK_hoststate_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
+ALTER TABLE ambari.host_version ADD CONSTRAINT FK_host_version_host_name FOREIGN KEY (host_name) REFERENCES ambari.hosts (host_name);
 ALTER TABLE ambari.servicecomponentdesiredstate ADD CONSTRAINT srvccmponentdesiredstatesrvcnm FOREIGN KEY (service_name, cluster_id) REFERENCES ambari.clusterservices (service_name, cluster_id);
 ALTER TABLE ambari.servicedesiredstate ADD CONSTRAINT servicedesiredstateservicename FOREIGN KEY (service_name, cluster_id) REFERENCES ambari.clusterservices (service_name, cluster_id);
 ALTER TABLE ambari.execution_command ADD CONSTRAINT FK_execution_command_task_id FOREIGN KEY (task_id) REFERENCES ambari.host_role_command (task_id);
@@ -348,6 +379,7 @@ CREATE INDEX idx_alert_group_name on ambari.alert_group(group_name);
 CREATE INDEX idx_alert_notice_state on ambari.alert_notice(notify_state);
 
 ---------inserting some data-----------
+-- In order for the first ID to be 1, must initialize the ambari_sequences table with a sequence_value of 0.
 BEGIN;
 INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value)
   SELECT 'cluster_id_seq', 1
@@ -398,6 +430,10 @@ INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value)
   union all
   select 'config_id_seq', 1
   union all
+  select 'cluster_version_id_seq', 0
+  union all
+  select 'host_version_id_seq', 0
+  union all
   select 'service_config_id_seq', 1;
 
 INSERT INTO ambari.adminresourcetype (resource_type_id, resource_type_name)

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index 2d8fedb..77b50f8 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -18,10 +18,12 @@
     <class>org.apache.ambari.server.orm.entities.ClusterConfigEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterServiceEntity</class>
     <class>org.apache.ambari.server.orm.entities.ClusterStateEntity</class>
+    <class>org.apache.ambari.server.orm.entities.ClusterVersionEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostComponentStateEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostEntity</class>
     <class>org.apache.ambari.server.orm.entities.HostStateEntity</class>
+    <class>org.apache.ambari.server.orm.entities.HostVersionEntity</class>
     <class>org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity</class>
     <class>org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity</class>
     <class>org.apache.ambari.server.orm.entities.UserEntity</class>

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
index 16b4d44..f9f2708 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog200Test.java
@@ -18,6 +18,10 @@
 
 package org.apache.ambari.server.upgrade;
 
+import java.util.List;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
 import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.createStrictMock;
@@ -82,10 +86,26 @@ public class UpgradeCatalog200Test {
     expect(configuration.getDatabaseUrl()).andReturn(Configuration.JDBC_IN_MEMORY_URL).anyTimes();
 
     Capture<DBAccessor.DBColumnInfo> alertDefinitionIgnoreColumnCapture = new Capture<DBAccessor.DBColumnInfo>();
+    Capture<DBAccessor.DBColumnInfo> hostComponentStateColumnCapture = new Capture<DBAccessor.DBColumnInfo>();
+    Capture<List<DBAccessor.DBColumnInfo>> clusterVersionCapture = new Capture<List<DBAccessor.DBColumnInfo>>();
+    Capture<List<DBAccessor.DBColumnInfo>> hostVersionCapture = new Capture<List<DBAccessor.DBColumnInfo>>();
 
+    // Alert Definition
     dbAccessor.addColumn(eq("alert_definition"),
         capture(alertDefinitionIgnoreColumnCapture));
 
+    // Host Component State
+    dbAccessor.addColumn(eq("hostcomponentstate"),
+        capture(hostComponentStateColumnCapture));
+
+    // Cluster Version
+    dbAccessor.createTable(eq("cluster_version"),
+        capture(clusterVersionCapture), eq("id"));
+
+    // Host Version
+    dbAccessor.createTable(eq("host_version"),
+        capture(hostVersionCapture), eq("id"));
+
     replay(dbAccessor, configuration, resultSet);
 
     AbstractUpgradeCatalog upgradeCatalog = getUpgradeCatalog(dbAccessor);
@@ -99,6 +119,18 @@ public class UpgradeCatalog200Test {
 
     // verify ignore column for alert_definition
     verifyAlertDefinitionIgnoreColumn(alertDefinitionIgnoreColumnCapture);
+
+    // Verify added column in hostcomponentstate table
+    DBAccessor.DBColumnInfo upgradeStateColumn = hostComponentStateColumnCapture.getValue();
+    assertEquals("upgrade_state", upgradeStateColumn.getName());
+    assertEquals(32, (int) upgradeStateColumn.getLength());
+    assertEquals(String.class, upgradeStateColumn.getType());
+    assertEquals("NONE", upgradeStateColumn.getDefaultValue());
+    assertFalse(upgradeStateColumn.isNullable());
+
+    // Verify capture group sizes
+    assertEquals(8, clusterVersionCapture.getValue().size());
+    assertEquals(5, hostVersionCapture.getValue().size());
   }
 
   @Test
@@ -134,4 +166,19 @@ public class UpgradeCatalog200Test {
     Assert.assertEquals(Short.class, column.getType());
     Assert.assertEquals("ignore_host", column.getName());
   }
+
+  @Test
+  public void testGetSourceVersion() {
+    final DBAccessor dbAccessor = createNiceMock(DBAccessor.class);
+    UpgradeCatalog upgradeCatalog = getUpgradeCatalog(dbAccessor);
+    Assert.assertEquals("1.7.0", upgradeCatalog.getSourceVersion());
+  }
+
+  @Test
+  public void testGetTargetVersion() throws Exception {
+    final DBAccessor dbAccessor = createNiceMock(DBAccessor.class);
+    UpgradeCatalog upgradeCatalog = getUpgradeCatalog(dbAccessor);
+
+    Assert.assertEquals("2.0.0", upgradeCatalog.getTargetVersion());
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/41cf385f/ambari-server/src/test/python/TestAmbariServer.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/python/TestAmbariServer.py b/ambari-server/src/test/python/TestAmbariServer.py
index c3651eb..48820b4 100644
--- a/ambari-server/src/test/python/TestAmbariServer.py
+++ b/ambari-server/src/test/python/TestAmbariServer.py
@@ -44,7 +44,7 @@ with patch("platform.linux_distribution", return_value = ('Suse','11','Final')):
 
 FatalException = ambari_server.FatalException
 NonFatalException = ambari_server.NonFatalException
-CURR_AMBARI_VERSION = "1.7.0"
+CURR_AMBARI_VERSION = "2.0.0"
 
 class TestAmbariServer(TestCase):
   def setUp(self):