You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2017/07/13 19:14:47 UTC

[29/37] ambari git commit: AMBARI-21450. Initial cherry-picking for feature branch (ncole)

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/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 9b93517..e0f52c6 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
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -20,6 +20,7 @@ package org.apache.ambari.server.orm.entities;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Objects;
 
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -40,7 +41,9 @@ import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 import javax.persistence.UniqueConstraint;
 
+import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.State;
+import org.apache.commons.lang.builder.EqualsBuilder;
 
 @Entity
 @Table(
@@ -84,19 +87,21 @@ public class ServiceComponentDesiredStateEntity {
   @Column(name = "recovery_enabled", nullable = false, insertable = true, updatable = true)
   private Integer recoveryEnabled = 0;
 
-  /**
-   * 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 = "repo_state", nullable = false, insertable = true, updatable = true)
+  @Enumerated(EnumType.STRING)
+  private RepositoryVersionState repoState = RepositoryVersionState.NOT_REQUIRED;
 
   /**
-   * Version string that should be followed by instances
-   * of component on hosts. Includes both stack version and build
+   * Unidirectional one-to-one association to {@link RepositoryVersionEntity}
    */
-  @Column(name = "desired_version", nullable = false, insertable = true, updatable = true)
-  private String desiredVersion = State.UNKNOWN.toString();
+  @OneToOne
+  @JoinColumn(
+      name = "desired_repo_version_id",
+      unique = false,
+      nullable = false,
+      insertable = true,
+      updatable = true)
+  private RepositoryVersionEntity desiredRepositoryVersion;
 
   @ManyToOne
   @JoinColumns({@javax.persistence.JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false), @JoinColumn(name = "service_name", referencedColumnName = "service_name", nullable = false)})
@@ -108,17 +113,8 @@ public class ServiceComponentDesiredStateEntity {
   @OneToMany(mappedBy = "serviceComponentDesiredStateEntity")
   private Collection<HostComponentDesiredStateEntity> hostComponentDesiredStateEntities;
 
-  /**
-   * All of the upgrades and downgrades which have occurred for this component.
-   * Can be {@code null} for none.
-   */
-  @OneToMany(
-      mappedBy = "m_serviceComponentDesiredStateEntity",
-      cascade = { CascadeType.ALL })
-  private Collection<ServiceComponentHistoryEntity> serviceComponentHistory;
-
   @OneToMany(mappedBy = "m_serviceComponentDesiredStateEntity", cascade = { CascadeType.ALL })
-  private Collection<ServiceComponentVersionEntity> serviceComponentVersion;
+  private Collection<ServiceComponentVersionEntity> serviceComponentVersions;
 
   public Long getId() {
     return id;
@@ -156,66 +152,39 @@ public class ServiceComponentDesiredStateEntity {
     this.desiredState = desiredState;
   }
 
-  public StackEntity getDesiredStack() {
-    return desiredStack;
-  }
-
-  public void setDesiredStack(StackEntity desiredStack) {
-    this.desiredStack = desiredStack;
+  public RepositoryVersionEntity getDesiredRepositoryVersion() {
+    return desiredRepositoryVersion;
   }
 
-  public String getDesiredVersion() {
-    return desiredVersion;
+  public void setDesiredRepositoryVersion(RepositoryVersionEntity desiredRepositoryVersion) {
+    this.desiredRepositoryVersion = desiredRepositoryVersion;
   }
 
-  public void setDesiredVersion(String desiredVersion) {
-    this.desiredVersion = desiredVersion;
-  }
-
-  /**
-   * Adds a historical entry for the version of this service component. New
-   * entries are automatically created when this entity is merged via a
-   * {@link CascadeType#MERGE}.
-   *
-   * @param historicalEntry
-   *          the entry to add.
-   */
-  public void addHistory(ServiceComponentHistoryEntity historicalEntry) {
-    if (null == serviceComponentHistory) {
-      serviceComponentHistory = new ArrayList<>();
-    }
-
-    serviceComponentHistory.add(historicalEntry);
-    historicalEntry.setServiceComponentDesiredState(this);
+  public StackEntity getDesiredStack() {
+    return desiredRepositoryVersion.getStack();
   }
 
-  /**
-   * Gets the history of this component's upgrades and downgrades.
-   *
-   * @return the component history, or {@code null} if none.
-   */
-  public Collection<ServiceComponentHistoryEntity> getHistory() {
-    return serviceComponentHistory;
+  public String getDesiredVersion() {
+    return desiredRepositoryVersion.getVersion();
   }
 
-
   /**
-   * @param versionEntry the version to add
+   * @param versionEntity the version to add
    */
-  public void addVersion(ServiceComponentVersionEntity versionEntry) {
-    if (null == serviceComponentVersion) {
-      serviceComponentVersion = new ArrayList<>();
+  public void addVersion(ServiceComponentVersionEntity versionEntity) {
+    if (null == serviceComponentVersions) {
+      serviceComponentVersions = new ArrayList<>();
     }
 
-    serviceComponentVersion.add(versionEntry);
-    versionEntry.setServiceComponentDesiredState(this);
+    serviceComponentVersions.add(versionEntity);
+    versionEntity.setServiceComponentDesiredState(this);
   }
 
   /**
    * @return the collection of versions for the component
    */
   public Collection<ServiceComponentVersionEntity> getVersions() {
-    return serviceComponentVersion;
+    return serviceComponentVersions;
   }
 
 
@@ -227,6 +196,9 @@ public class ServiceComponentDesiredStateEntity {
     this.recoveryEnabled = (recoveryEnabled == false) ? 0 : 1;
   }
 
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public boolean equals(Object o) {
     if (this == o) {
@@ -238,39 +210,21 @@ public class ServiceComponentDesiredStateEntity {
     }
 
     ServiceComponentDesiredStateEntity that = (ServiceComponentDesiredStateEntity) o;
-
-    if (id != null ? !id.equals(that.id) : that.id != null) {
-      return false;
-    }
-    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;
+    EqualsBuilder equalsBuilder = new EqualsBuilder();
+    equalsBuilder.append(id, that.id);
+    equalsBuilder.append(clusterId, that.clusterId);
+    equalsBuilder.append(componentName, that.componentName);
+    equalsBuilder.append(desiredState, that.desiredState);
+    equalsBuilder.append(serviceName, that.serviceName);
+    equalsBuilder.append(desiredRepositoryVersion, that.desiredRepositoryVersion);
+
+    return equalsBuilder.isEquals();
   }
 
   @Override
   public int hashCode() {
-    int result = id != null ? id.hashCode() : 0;
-    result = 31 * result + (clusterId != null ? clusterId.hashCode() : 0);
-    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 + (desiredStack != null ? desiredStack.hashCode() : 0);
-
-    return result;
+    return Objects.hash(id, clusterId, serviceName, componentName, desiredState,
+        desiredRepositoryVersion);
   }
 
   public ClusterServiceEntity getClusterServiceEntity() {
@@ -297,4 +251,18 @@ public class ServiceComponentDesiredStateEntity {
     this.hostComponentDesiredStateEntities = hostComponentDesiredStateEntities;
   }
 
+  /**
+   * @param state the repository state for {@link #getDesiredVersion()}
+   */
+  public void setRepositoryState(RepositoryVersionState state) {
+    repoState = state;
+  }
+
+  /**
+   * @return the state of the repository for {@link #getDesiredVersion()}
+   */
+  public RepositoryVersionState getRepositoryState() {
+    return repoState;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java
index 5085d18..ffb3b82 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentVersionEntity.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -49,9 +49,22 @@ import org.apache.ambari.server.state.RepositoryVersionState;
     valueColumnName = "sequence_value",
     pkColumnValue = "servicecomponent_version_id_seq",
     initialValue = 0)
-@NamedQueries({ @NamedQuery(
+@NamedQueries({
+  @NamedQuery(
     name = "ServiceComponentVersionEntity.findByComponent",
-    query = "SELECT version FROM ServiceComponentVersionEntity version WHERE version.m_serviceComponentDesiredStateEntity.clusterId = :clusterId AND version.m_serviceComponentDesiredStateEntity.serviceName = :serviceName AND version.m_serviceComponentDesiredStateEntity.componentName = :componentName") })
+    query = "SELECT version FROM ServiceComponentVersionEntity version WHERE " +
+      "version.m_serviceComponentDesiredStateEntity.clusterId = :clusterId AND " +
+      "version.m_serviceComponentDesiredStateEntity.serviceName = :serviceName AND " +
+      "version.m_serviceComponentDesiredStateEntity.componentName = :componentName"),
+  @NamedQuery(
+    name = "ServiceComponentVersionEntity.findByComponentAndVersion",
+    query = "SELECT version FROM ServiceComponentVersionEntity version WHERE " +
+        "version.m_serviceComponentDesiredStateEntity.clusterId = :clusterId AND " +
+        "version.m_serviceComponentDesiredStateEntity.serviceName = :serviceName AND " +
+        "version.m_serviceComponentDesiredStateEntity.componentName = :componentName AND " +
+        "version.m_repositoryVersion.version = :repoVersion")
+})
+
 public class ServiceComponentVersionEntity {
 
   @Id
@@ -66,7 +79,7 @@ public class ServiceComponentVersionEntity {
   private ServiceComponentDesiredStateEntity m_serviceComponentDesiredStateEntity;
 
   @ManyToOne
-  @JoinColumn(name = "repo_version_id", referencedColumnName = "repo_version_id", nullable = false)
+  @JoinColumn(name  = "repo_version_id", referencedColumnName = "repo_version_id", nullable = false)
   private RepositoryVersionEntity m_repositoryVersion;
 
   @Column(name = "state", nullable = false, insertable = true, updatable = true)
@@ -99,6 +112,13 @@ public class ServiceComponentVersionEntity {
   }
 
   /**
+   * @return the repository
+   */
+  public RepositoryVersionEntity getRepositoryVersion() {
+    return m_repositoryVersion;
+  }
+
+  /**
    * @return the id
    */
   public long getId() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/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 885f995..0124d3e 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
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.orm.entities;
 
+import java.util.Objects;
+
 import javax.persistence.Basic;
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -25,11 +27,13 @@ import javax.persistence.EnumType;
 import javax.persistence.Enumerated;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
 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.builder.EqualsBuilder;
 
 @javax.persistence.IdClass(ServiceDesiredStateEntityPK.class)
 @javax.persistence.Table(name = "servicedesiredstate")
@@ -52,13 +56,6 @@ public class ServiceDesiredStateEntity {
   @Basic
   private int desiredHostRoleMapping = 0;
 
-  /**
-   * 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;
@@ -78,6 +75,13 @@ public class ServiceDesiredStateEntity {
       })
   private ClusterServiceEntity clusterServiceEntity;
 
+  /**
+   * The desired repository that the service should be on.
+   */
+  @ManyToOne
+  @JoinColumn(name = "desired_repo_version_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private RepositoryVersionEntity desiredRepositoryVersion;
+
   public Long getClusterId() {
     return clusterId;
   }
@@ -111,11 +115,7 @@ public class ServiceDesiredStateEntity {
   }
 
   public StackEntity getDesiredStack() {
-    return desiredStack;
-  }
-
-  public void setDesiredStack(StackEntity desiredStack) {
-    this.desiredStack = desiredStack;
+    return desiredRepositoryVersion.getStack();
   }
 
   public MaintenanceState getMaintenanceState() {
@@ -152,6 +152,9 @@ public class ServiceDesiredStateEntity {
     this.credentialStoreEnabled = (short)((credentialStoreEnabled == false) ? 0 : 1);
   }
 
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public boolean equals(Object o) {
     if (this == o) {
@@ -163,37 +166,23 @@ public class ServiceDesiredStateEntity {
     }
 
     ServiceDesiredStateEntity that = (ServiceDesiredStateEntity) o;
+    EqualsBuilder equalsBuilder = new EqualsBuilder();
+    equalsBuilder.append(clusterId, that.clusterId);
+    equalsBuilder.append(desiredState, that.desiredState);
+    equalsBuilder.append(desiredHostRoleMapping, that.desiredHostRoleMapping);
+    equalsBuilder.append(serviceName, that.serviceName);
+    equalsBuilder.append(desiredRepositoryVersion, that.desiredRepositoryVersion);
 
-    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;
+    return equalsBuilder.isEquals();
   }
 
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public int hashCode() {
-    int result = clusterId != null ? clusterId.intValue() : 0;
-    result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
-    result = 31 * result + (desiredState != null ? desiredState.hashCode() : 0);
-    result = 31 * result + desiredHostRoleMapping;
-    result = 31 * result + (desiredStack != null ? desiredStack.hashCode() : 0);
-    return result;
+    return Objects.hash(clusterId, serviceName, desiredState, desiredHostRoleMapping,
+        desiredRepositoryVersion);
   }
 
   public ClusterServiceEntity getClusterServiceEntity() {
@@ -203,4 +192,24 @@ public class ServiceDesiredStateEntity {
   public void setClusterServiceEntity(ClusterServiceEntity clusterServiceEntity) {
     this.clusterServiceEntity = clusterServiceEntity;
   }
+
+  /**
+   * Gets the desired repository version.
+   *
+   * @return the desired repository (never {@code null}).
+   */
+  public RepositoryVersionEntity getDesiredRepositoryVersion() {
+    return desiredRepositoryVersion;
+  }
+
+  /**
+   * Sets the desired repository for this service.
+   *
+   * @param desiredRepositoryVersion
+   *          the desired repository (not {@code null}).
+   */
+  public void setDesiredRepositoryVersion(RepositoryVersionEntity desiredRepositoryVersion) {
+    this.desiredRepositoryVersion = desiredRepositoryVersion;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntityPK.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntityPK.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntityPK.java
index 54dc8b6..3fa5289 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntityPK.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceDesiredStateEntityPK.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -18,9 +18,10 @@
 
 package org.apache.ambari.server.orm.entities;
 
+import java.io.Serializable;
+
 import javax.persistence.Column;
 import javax.persistence.Id;
-import java.io.Serializable;
 
 @SuppressWarnings("serial")
 public class ServiceDesiredStateEntityPK implements Serializable {

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
index 8c37b51..7f4824f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -17,6 +17,7 @@
  */
 package org.apache.ambari.server.orm.entities;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.persistence.CascadeType;
@@ -37,8 +38,12 @@ import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
+import org.apache.ambari.server.state.RepositoryType;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
+import org.apache.commons.lang.builder.EqualsBuilder;
+
+import com.google.common.base.Objects;
 
 /**
  * Models the data representation of an upgrade
@@ -91,18 +96,6 @@ public class UpgradeEntity {
   @JoinColumn(name = "request_id", nullable = false, insertable = true, updatable = false)
   private RequestEntity requestEntity = null;
 
-  @JoinColumn(
-      name = "from_repo_version_id",
-      referencedColumnName = "repo_version_id",
-      nullable = false)
-  private RepositoryVersionEntity fromRepositoryVersion;
-
-  @JoinColumn(
-      name = "to_repo_version_id",
-      referencedColumnName = "repo_version_id",
-      nullable = false)
-  private RepositoryVersionEntity toRepositoryVersion;
-
   @Column(name="direction", nullable = false)
   @Enumerated(value = EnumType.STRING)
   private Direction direction = Direction.UPGRADE;
@@ -114,6 +107,9 @@ public class UpgradeEntity {
   @Enumerated(value = EnumType.STRING)
   private UpgradeType upgradeType;
 
+  @JoinColumn(name = "repo_version_id", referencedColumnName = "repo_version_id", nullable = false)
+  private RepositoryVersionEntity repositoryVersion;
+
   @Column(name = "skip_failures", nullable = false)
   private Integer skipFailures = 0;
 
@@ -123,6 +119,10 @@ public class UpgradeEntity {
   @Column(name="downgrade_allowed", nullable = false)
   private Short downgrade_allowed = 1;
 
+  @Column(name="orchestration", nullable = false)
+  @Enumerated(value = EnumType.STRING)
+  private RepositoryType orchestration = RepositoryType.STANDARD;
+
   /**
    * {@code true} if the upgrade has been marked as suspended.
    */
@@ -133,6 +133,14 @@ public class UpgradeEntity {
   private List<UpgradeGroupEntity> upgradeGroupEntities;
 
   /**
+   * Uni-directional relationship between an upgrade an all of the components in
+   * that upgrade.
+   */
+  @OneToMany(orphanRemoval=true, cascade = { CascadeType.ALL })
+  @JoinColumn(name = "upgrade_id")
+  private List<UpgradeHistoryEntity> upgradeHistory;
+
+  /**
    * @return the id
    */
   public Long getId() {
@@ -184,45 +192,12 @@ public class UpgradeEntity {
     return requestId;
   }
 
-  /**
-   * @param id the request id
-   */
   public void setRequestEntity(RequestEntity requestEntity) {
     this.requestEntity = requestEntity;
     requestId = requestEntity.getRequestId();
   }
 
   /**
-   * @return the "from" version
-   */
-  public RepositoryVersionEntity getFromRepositoryVersion() {
-    return fromRepositoryVersion;
-  }
-
-  /**
-   * @param repositoryVersion
-   *          the "from" version
-   */
-  public void setFromRepositoryVersion(RepositoryVersionEntity repositoryVersion) {
-    fromRepositoryVersion = repositoryVersion;
-  }
-
-  /**
-   * @return the "to" version
-   */
-  public RepositoryVersionEntity getToRepositoryVersion() {
-    return toRepositoryVersion;
-  }
-
-  /**
-   * @param repositoryVersion
-   *          the "to" version
-   */
-  public void setToRepositoryVersion(RepositoryVersionEntity repositoryVersion) {
-    toRepositoryVersion = repositoryVersion;
-  }
-
-  /**
    * @return the direction of the upgrade
    */
   public Direction getDirection() {
@@ -344,60 +319,112 @@ public class UpgradeEntity {
     this.suspended = suspended ? (short) 1 : (short) 0;
   }
 
+  /**
+   * Adds a historical entry for a service component in this upgrade.
+   *
+   * @param historicalEntry
+   *          the entry to add.
+   */
+  public void addHistory(UpgradeHistoryEntity historicalEntry) {
+    if (null == upgradeHistory) {
+      upgradeHistory = new ArrayList<>();
+    }
+
+    upgradeHistory.add(historicalEntry);
+  }
+
+  /**
+   * Gets the history of this component's upgrades and downgrades.
+   *
+   * @return the component history, or {@code null} if none.
+   */
+  public List<UpgradeHistoryEntity> getHistory() {
+    return upgradeHistory;
+  }
+
+  /**
+   * Upgrades will always have a single version being upgraded to and downgrades
+   * will have a single version being downgraded from. This repository
+   * represents that version.
+   * <p/>
+   * When the direction is {@link Direction#UPGRADE}, this represents the target
+   * repository. <br/>
+   * When the direction is {@link Direction#DOWNGRADE}, this represents the
+   * repository being downgraded from.
+   *
+   * @return the repository version being upgraded to or downgraded from (never
+   *         {@code null}).
+   */
+  public RepositoryVersionEntity getRepositoryVersion() {
+    return repositoryVersion;
+  }
+
+  /**
+   * Sets the repository version for this upgrade. This value will change
+   * depending on the direction of the upgrade.
+   * <p/>
+   * When the direction is {@link Direction#UPGRADE}, this represents the target
+   * repository. <br/>
+   * When the direction is {@link Direction#DOWNGRADE}, this represents the
+   * repository being downgraded from.
+   *
+   * @param repositoryVersion
+   *          the repository version being upgraded to or downgraded from (not
+   *          {@code null}).
+   */
+  public void setRepositoryVersion(RepositoryVersionEntity repositoryVersion) {
+    this.repositoryVersion = repositoryVersion;
+  }
+
+  /**
+   * Sets the orchestration for the upgrade.  Only different when an upgrade is a revert of a patch.
+   * In that case, the orchestration is set to PATCH even if the target repository is type STANDARD.
+   *
+   * @param type  the orchestration
+   */
+  public void setOrchestration(RepositoryType type) {
+    orchestration = type;
+  }
+
+  /**
+   * @return  the orchestration type
+   */
+  public RepositoryType getOrchestration() {
+    return orchestration;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public boolean equals(Object o) {
     if (this == o) {
       return true;
     }
+
     if (o == null || getClass() != o.getClass()) {
       return false;
     }
 
     UpgradeEntity that = (UpgradeEntity) o;
-
-    if (upgradeId != null ? !upgradeId.equals(that.upgradeId) : that.upgradeId != null) {
-      return false;
-    }
-    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) {
-      return false;
-    }
-    if (requestId != null ? !requestId.equals(that.requestId) : that.requestId != null) {
-      return false;
-    }
-    if (fromRepositoryVersion != null ? !fromRepositoryVersion.equals(that.fromRepositoryVersion) : that.fromRepositoryVersion != null) {
-      return false;
-    }
-    if (toRepositoryVersion != null ? !toRepositoryVersion.equals(that.toRepositoryVersion) : that.toRepositoryVersion != null) {
-      return false;
-    }
-    if (direction != null ? !direction.equals(that.direction) : that.direction != null) {
-      return false;
-    }
-    if (suspended != null ? !suspended.equals(that.suspended) : that.suspended != null) {
-      return false;
-    }
-    if (upgradeType != null ? !upgradeType.equals(that.upgradeType) : that.upgradeType != null) {
-      return false;
-    }
-    if (upgradePackage != null ? !upgradePackage.equals(that.upgradePackage) : that.upgradePackage != null) {
-      return false;
-    }
-
-    return true;
+    return new EqualsBuilder()
+        .append(upgradeId, that.upgradeId)
+        .append(clusterId, that.clusterId)
+        .append(requestId, that.requestId)
+        .append(direction, that.direction)
+        .append(suspended, that.suspended)
+        .append(upgradeType, that.upgradeType)
+        .append(upgradePackage, that.upgradePackage)
+        .isEquals();
   }
 
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public int hashCode() {
-    int result = upgradeId != null ? upgradeId.hashCode() : 0;
-    result = 31 * result + (clusterId != null ? clusterId.hashCode() : 0);
-    result = 31 * result + (requestId != null ? requestId.hashCode() : 0);
-    result = 31 * result + (fromRepositoryVersion != null ? fromRepositoryVersion.hashCode() : 0);
-    result = 31 * result + (toRepositoryVersion != null ? toRepositoryVersion.hashCode() : 0);
-    result = 31 * result + (direction != null ? direction.hashCode() : 0);
-    result = 31 * result + (suspended != null ? suspended.hashCode() : 0);
-    result = 31 * result + (upgradeType != null ? upgradeType.hashCode() : 0);
-    result = 31 * result + (upgradePackage != null ? upgradePackage.hashCode() : 0);
-    return result;
+    return Objects.hashCode(upgradeId, clusterId, requestId, direction, suspended, upgradeType,
+        upgradePackage);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java
new file mode 100644
index 0000000..0f7ac72
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java
@@ -0,0 +1,233 @@
+/**
+ * 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 javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+
+import com.google.common.base.Objects;
+
+/**
+ * The {@link UpgradeHistoryEntity} represents the version history of components
+ * participating in an upgrade or a downgrade.
+ */
+@Entity
+@Table(
+    name = "upgrade_history",
+    uniqueConstraints = @UniqueConstraint(
+        columnNames = { "upgrade_id", "component_name", "service_name" }))
+@TableGenerator(
+    name = "upgrade_history_id_generator",
+    table = "ambari_sequences",
+    pkColumnName = "sequence_name",
+    valueColumnName = "sequence_value",
+    pkColumnValue = "upgrade_history_id_seq",
+    initialValue = 0)
+@NamedQueries({
+    @NamedQuery(
+        name = "UpgradeHistoryEntity.findAll",
+        query = "SELECT upgradeHistory FROM UpgradeHistoryEntity upgradeHistory"),
+    @NamedQuery(
+        name = "UpgradeHistoryEntity.findByUpgradeId",
+        query = "SELECT upgradeHistory FROM UpgradeHistoryEntity upgradeHistory WHERE upgradeHistory.upgradeId = :upgradeId")
+})
+public class UpgradeHistoryEntity {
+
+  @Id
+  @Column(name = "id", nullable = false, insertable = true, updatable = false)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "upgrade_history_id_generator")
+  private Long id;
+
+  @Column(name = "upgrade_id", nullable = false, insertable = false, updatable = false)
+  private Long upgradeId;
+
+  @JoinColumn(name = "upgrade_id", nullable = false)
+  private UpgradeEntity upgrade;
+
+  @Column(name = "service_name", nullable = false, insertable = true, updatable = true)
+  private String serviceName;
+
+  @Column(name = "component_name", nullable = false, insertable = true, updatable = true)
+  private String componentName;
+
+  @ManyToOne
+  @JoinColumn(name = "from_repo_version_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private RepositoryVersionEntity fromRepositoryVersion = null;
+
+  @ManyToOne
+  @JoinColumn(name = "target_repo_version_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private RepositoryVersionEntity targetRepositoryVersion = null;
+
+  /**
+   * @return the id
+   */
+  public Long getId() {
+    return id;
+  }
+
+  /**
+   * Gets the ID of the upgrade associated with this historical entry.
+   *
+   * @return the upgrade ID (never {@code null}).
+   */
+  public Long getUpgradeId() {
+    return upgradeId;
+  }
+
+  /**
+   * @return
+   */
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  /**
+   * @param serviceName
+   */
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  /**
+   * @return
+   */
+  public String getComponentName() {
+    return componentName;
+  }
+
+  /**
+   * @param componentName
+   */
+  public void setComponentName(String componentName) {
+    this.componentName = componentName;
+  }
+
+  /**
+   * Gets the repository that the upgrade is coming from.
+   *
+   * @return the repository that the upgrade is coming from (not {@code null}).
+   */
+  public RepositoryVersionEntity getFromReposistoryVersion() {
+    return fromRepositoryVersion;
+  }
+
+  /**
+   * Sets the repository that the services in the upgrade are CURRENT on.
+   *
+   * @param repositoryVersionEntity
+   *          the repository entity (not {@code null}).
+   */
+  public void setFromRepositoryVersion(RepositoryVersionEntity repositoryVersionEntity) {
+    fromRepositoryVersion = repositoryVersionEntity;
+  }
+
+  /**
+   * Gets the target repository version for this upgrade.
+   *
+   * @return the target repository for the services in the upgrade (not
+   *         {@code null}).
+   */
+  public RepositoryVersionEntity getTargetRepositoryVersion() {
+    return targetRepositoryVersion;
+  }
+
+  /**
+   * Gets the version of the target repository.
+   *
+   * @return the target version string (never {@code null}).
+   * @see #getTargetRepositoryVersion()
+   */
+  public String getTargetVersion() {
+    return targetRepositoryVersion.getVersion();
+  }
+
+  /**
+   * Sets the target repository of the upgrade.
+   *
+   * @param repositoryVersionEntity
+   *          the target repository (not {@code null}).
+   */
+  public void setTargetRepositoryVersion(RepositoryVersionEntity repositoryVersionEntity) {
+    targetRepositoryVersion = repositoryVersionEntity;
+  }
+
+  /**
+   * Sets the associated upgrade entity.
+   *
+   * @param upgrade
+   */
+  public void setUpgrade(UpgradeEntity upgrade) {
+    this.upgrade = upgrade;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    UpgradeHistoryEntity that = (UpgradeHistoryEntity) o;
+    return new EqualsBuilder()
+        .append(id, that.id)
+        .append(upgradeId, that.upgradeId)
+        .append(serviceName, that.serviceName)
+        .append(componentName, that.componentName)
+        .isEquals();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(id, upgradeId, serviceName, componentName);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString() {
+    return Objects.toStringHelper(this)
+        .add("id", id)
+        .add("upgradeId", upgradeId)
+        .add("serviceName", serviceName)
+        .add("componentName", componentName)
+        .add("from", fromRepositoryVersion)
+        .add("to", targetRepositoryVersion).toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
index e0d16af..54ba784 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/PrepareDisableKerberosServerAction.java
@@ -91,7 +91,7 @@ public class PrepareDisableKerberosServerAction extends AbstractPrepareKerberosS
           }
         });
 
-    Map<String, Map<String, String>> kerberosConfigurations = new HashMap<String, Map<String, String>>();
+    Map<String, Map<String, String>> kerberosConfigurations = new HashMap<>();
     Map<String, String> commandParameters = getCommandParameters();
     String dataDirectory = getCommandParameterValue(commandParameters, DATA_DIRECTORY);
 
@@ -143,7 +143,7 @@ public class PrepareDisableKerberosServerAction extends AbstractPrepareKerberosS
     // Ensure the cluster-env/security_enabled flag is set properly
     Map<String, String> clusterEnvProperties = kerberosConfigurations.get(KerberosHelper.SECURITY_ENABLED_CONFIG_TYPE);
     if (clusterEnvProperties == null) {
-      clusterEnvProperties = new HashMap<String, String>();
+      clusterEnvProperties = new HashMap<>();
       kerberosConfigurations.put(KerberosHelper.SECURITY_ENABLED_CONFIG_TYPE, clusterEnvProperties);
     }
     clusterEnvProperties.put(KerberosHelper.SECURITY_ENABLED_PROPERTY_NAME, "false");
@@ -157,13 +157,13 @@ public class PrepareDisableKerberosServerAction extends AbstractPrepareKerberosS
         throw new AmbariException(message);
       }
 
-      Map<String, Set<String>> configurationsToRemove = new HashMap<String, Set<String>>();
+      Map<String, Set<String>> configurationsToRemove = new HashMap<>();
 
       // Fill the configurationsToRemove map with all Kerberos-related configurations.  Values
       // needed to be kept will have new values from the stack definition and thus pruned from
       // this map.
       for (Map.Entry<String, Map<String, String>> entry : kerberosConfigurations.entrySet()) {
-        configurationsToRemove.put(entry.getKey(), new HashSet<String>(entry.getValue().keySet()));
+        configurationsToRemove.put(entry.getKey(), new HashSet<>(entry.getValue().keySet()));
       }
 
       // Remove cluster-env from the set of configurations to remove since it has no default set
@@ -171,13 +171,13 @@ public class PrepareDisableKerberosServerAction extends AbstractPrepareKerberosS
       configurationsToRemove.remove("cluster-env");
 
       if (!schToProcess.isEmpty()) {
-        Set<String> visitedServices = new HashSet<String>();
+        Set<String> visitedServices = new HashSet<>();
 
         for (ServiceComponentHost sch : schToProcess) {
           String serviceName = sch.getServiceName();
 
           if (!visitedServices.contains(serviceName)) {
-            StackId stackVersion = sch.getStackVersion();
+            StackId stackVersion = sch.getDesiredStackId();
 
             visitedServices.add(serviceName);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java
index 2177c04..1307f23 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/UpdateKerberosConfigsServerAction.java
@@ -18,7 +18,15 @@
 
 package org.apache.ambari.server.serveraction.kerberos;
 
-import com.google.inject.Inject;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.agent.CommandReport;
@@ -31,14 +39,7 @@ import org.apache.ambari.server.state.SecurityType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
+import com.google.inject.Inject;
 
 /**
  * UpdateKerberosConfigServerAction is implementation of ServerAction that updates service configs
@@ -85,8 +86,8 @@ public class UpdateKerberosConfigsServerAction extends AbstractServerAction {
 
     String authenticatedUserName = getCommandParameterValue(getCommandParameters(), KerberosServerAction.AUTHENTICATED_USER_NAME);
     String dataDirectoryPath = getCommandParameterValue(getCommandParameters(), KerberosServerAction.DATA_DIRECTORY);
-    HashMap<String, Map<String, String>> propertiesToSet = new HashMap<String, Map<String, String>>();
-    HashMap<String, Collection<String>> propertiesToRemove = new HashMap<String, Collection<String>>();
+    HashMap<String, Map<String, String>> propertiesToSet = new HashMap<>();
+    HashMap<String, Collection<String>> propertiesToRemove = new HashMap<>();
 
     // If the data directory path is set, attempt to process further, else assume there is no work to do
     if (dataDirectoryPath != null) {
@@ -95,7 +96,7 @@ public class UpdateKerberosConfigsServerAction extends AbstractServerAction {
       // If the data directory exists, attempt to process further, else assume there is no work to do
       if (dataDirectory.exists()) {
         KerberosConfigDataFileReader configReader = null;
-        Set<String> configTypes = new HashSet<String>();
+        Set<String> configTypes = new HashSet<>();
 
         try {
           // If the config data file exists, iterate over the records to find the (explicit)
@@ -146,7 +147,7 @@ public class UpdateKerberosConfigsServerAction extends AbstractServerAction {
             }
 
             for (String configType : configTypes) {
-              configHelper.updateConfigType(cluster, controller, configType,
+              configHelper.updateConfigType(cluster, cluster.getDesiredStackVersion(), controller, configType,
                   propertiesToSet.get(configType),
                   propertiesToRemove.get(configType),
                   authenticatedUserName, configNote);
@@ -200,7 +201,7 @@ public class UpdateKerberosConfigsServerAction extends AbstractServerAction {
   private void addConfigTypePropVal(HashMap<String, Map<String, String>> configurations, String configType, String prop, String val) {
     Map<String, String> configTypePropsVal = configurations.get(configType);
     if (configTypePropsVal == null) {
-      configTypePropsVal = new HashMap<String, String>();
+      configTypePropsVal = new HashMap<>();
       configurations.put(configType, configTypePropsVal);
     }
     configTypePropsVal.put(prop, val);
@@ -217,7 +218,7 @@ public class UpdateKerberosConfigsServerAction extends AbstractServerAction {
   private void removeConfigTypeProp(HashMap<String, Collection<String>> configurations, String configType, String prop) {
     Collection<String> configTypeProps = configurations.get(configType);
     if (configTypeProps == null) {
-      configTypeProps = new HashSet<String>();
+      configTypeProps = new HashSet<>();
       configurations.put(configType, configTypeProps);
     }
     configTypeProps.add(prop);

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java
new file mode 100644
index 0000000..e012dac
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java
@@ -0,0 +1,59 @@
+/*
+ * 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.serveraction.upgrades;
+
+import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.serveraction.AbstractServerAction;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.UpgradeContext;
+import org.apache.ambari.server.state.UpgradeContextFactory;
+import org.apache.ambari.server.state.UpgradeHelper;
+
+import com.google.inject.Inject;
+
+/**
+ * Abstract class that reads values from command params in a consistent way.
+ */
+public abstract class AbstractUpgradeServerAction extends AbstractServerAction {
+
+  @Inject
+  protected Clusters m_clusters;
+
+  /**
+   * Used to move desired repo versions forward.
+   */
+  @Inject
+  protected UpgradeHelper m_upgradeHelper;
+
+  /**
+   * Used to create instances of {@link UpgradeContext} with injected
+   * dependencies.
+   */
+  @Inject
+  private UpgradeContextFactory m_upgradeContextFactory;
+
+  /**
+   * Gets an initialized {@link UpgradeContext} for the in-progress upgrade.
+   */
+  protected UpgradeContext getUpgradeContext(Cluster cluster) {
+    UpgradeEntity upgrade = cluster.getUpgradeInProgress();
+    UpgradeContext upgradeContext = m_upgradeContextFactory.create(cluster, upgrade);
+    return upgradeContext;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java
index 9ae9844..44d2b4d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java
@@ -1,4 +1,4 @@
-/**
+/*
  * 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
@@ -18,7 +18,6 @@
 package org.apache.ambari.server.serveraction.upgrades;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -28,16 +27,13 @@ import java.util.concurrent.ConcurrentMap;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.agent.CommandReport;
-import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.UpgradeContext;
-import org.apache.ambari.server.state.UpgradeContextFactory;
 import org.apache.commons.lang.StringUtils;
 
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonPrimitive;
-import com.google.inject.Inject;
 
 /**
  * Action that checks component versions to ensure {@link FinalizeUpgradeAction} will
@@ -45,30 +41,23 @@ import com.google.inject.Inject;
  */
 public class ComponentVersionCheckAction extends FinalizeUpgradeAction {
 
-  /**
-   * Used for building {@link UpgradeContext} instances.
-   */
-  @Inject
-  private UpgradeContextFactory upgradeContextFactory;
 
   @Override
   public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext)
       throws AmbariException, InterruptedException {
 
     String clusterName = getExecutionCommand().getClusterName();
-    Cluster cluster = clusters.getCluster(clusterName);
-    UpgradeContext context = upgradeContextFactory.create(cluster, cluster.getUpgradeInProgress());
-    RepositoryVersionEntity targetRepositoryVersion = context.getTargetRepositoryVersion();
 
-    List<InfoTuple> errors = checkHostComponentVersions(cluster,
-        targetRepositoryVersion.getVersion(), context.getTargetStackId());
+    Cluster cluster = m_clusters.getCluster(clusterName);
+
+    UpgradeContext upgradeContext = getUpgradeContext(cluster);
+    Set<InfoTuple> errors = validateComponentVersions(upgradeContext);
 
     StringBuilder outSB = new StringBuilder();
     StringBuilder errSB = new StringBuilder();
 
     if (errors.isEmpty()) {
-      outSB.append("No version mismatches found for components");
-      errSB.append("No errors found for components");
+      outSB.append("All service components are reporting the correct version.");
       return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outSB.toString(), errSB.toString());
     } else {
       String structuredOut = getErrors(outSB, errSB, errors);
@@ -76,19 +65,21 @@ public class ComponentVersionCheckAction extends FinalizeUpgradeAction {
     }
   }
 
-  private String getErrors(StringBuilder outSB, StringBuilder errSB, List<InfoTuple> errors) {
+  private String getErrors(StringBuilder outSB, StringBuilder errSB, Set<InfoTuple> errors) {
 
-    errSB.append("The following components were found to have version mismatches.  ");
-    errSB.append("Finalize will not complete successfully:\n");
+    errSB.append("Finalization will not be able to completed because of the following version inconsistencies:");
 
     Set<String> hosts = new TreeSet<>();
     Map<String, JsonArray> hostDetails = new HashMap<>();
 
     for (InfoTuple tuple : errors) {
+      errSB.append("  ");
       errSB.append(tuple.hostName).append(": ");
+      errSB.append(System.lineSeparator()).append("    ");
       errSB.append(tuple.serviceName).append('/').append(tuple.componentName);
       errSB.append(" reports ").append(StringUtils.trimToEmpty(tuple.currentVersion));
-      errSB.append('\n');
+      errSB.append(" but expects ").append(tuple.targetVersion);
+      errSB.append(System.lineSeparator());
 
       hosts.add(tuple.hostName);
 
@@ -100,6 +91,7 @@ public class ComponentVersionCheckAction extends FinalizeUpgradeAction {
       obj.addProperty("service", tuple.serviceName);
       obj.addProperty("component", tuple.componentName);
       obj.addProperty("version", tuple.currentVersion);
+      obj.addProperty("targetVersion", tuple.targetVersion);
 
       hostDetails.get(tuple.hostName).add(obj);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java
index a42e667..eb432df 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ConfigureAction.java
@@ -536,7 +536,7 @@ public class ConfigureAction extends AbstractServerAction {
       auditName = m_configuration.getAnonymousAuditName();
     }
 
-    m_configHelper.createConfigType(cluster, m_controller, configType,
+    m_configHelper.createConfigType(cluster, cluster.getDesiredStackVersion(), m_controller, configType,
         newValues, auditName, serviceVersionNote);
 
     String message = "Finished updating configuration ''{0}''";