You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2017/05/31 20:12:52 UTC

[21/50] [abbrv] ambari git commit: AMBARI-21022 - Upgrades Should Be Associated With Repositories Instead of String Versions (jonathanhurley)

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/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 e5e2de3..42d2a98 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
@@ -17,6 +17,7 @@
  */
 package org.apache.ambari.server.orm.entities;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.persistence.CascadeType;
@@ -39,6 +40,8 @@ import javax.persistence.TableGenerator;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 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 org.apache.hadoop.metrics2.sink.relocated.google.common.base.Objects;
 
 /**
  * Models the data representation of an upgrade
@@ -60,7 +63,7 @@ import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
   @NamedQuery(name = "UpgradeEntity.findUpgrade",
       query = "SELECT u FROM UpgradeEntity u WHERE u.upgradeId = :upgradeId"),
   @NamedQuery(name = "UpgradeEntity.findUpgradeByRequestId",
-      query = "SELECT u FROM UpgradeEntity u WHERE u.requestId = :requestId"),  
+      query = "SELECT u FROM UpgradeEntity u WHERE u.requestId = :requestId"),
   @NamedQuery(name = "UpgradeEntity.findLatestForClusterInDirection",
       query = "SELECT u FROM UpgradeEntity u JOIN RequestEntity r ON u.requestId = r.requestId WHERE u.clusterId = :clusterId AND u.direction = :direction ORDER BY r.startTime DESC, u.upgradeId DESC"),
   @NamedQuery(name = "UpgradeEntity.findLatestForCluster",
@@ -91,12 +94,6 @@ public class UpgradeEntity {
   @JoinColumn(name = "request_id", nullable = false, insertable = true, updatable = false)
   private RequestEntity requestEntity = null;
 
-  @Column(name="from_version", nullable = false)
-  private String fromVersion = null;
-
-  @Column(name="to_version", nullable = false)
-  private String toVersion = null;
-
   @Column(name="direction", nullable = false)
   @Enumerated(value = EnumType.STRING)
   private Direction direction = Direction.UPGRADE;
@@ -108,6 +105,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;
 
@@ -127,6 +127,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,34 +192,6 @@ public class UpgradeEntity {
   }
 
   /**
-   * @return the "from" version
-   */
-  public String getFromVersion() {
-    return fromVersion;
-  }
-
-  /**
-   * @param version the "from" version
-   */
-  public void setFromVersion(String version) {
-    fromVersion = version;
-  }
-
-  /**
-   * @return the "to" version
-   */
-  public String getToVersion() {
-    return toVersion;
-  }
-
-  /**
-   * @param version the "to" version
-   */
-  public void setToVersion(String version) {
-    toVersion = version;
-  }
-
-  /**
    * @return the direction of the upgrade
    */
   public Direction getDirection() {
@@ -333,60 +313,95 @@ 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;
+  }
+
+  /**
+   * {@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 (fromVersion != null ? !fromVersion.equals(that.fromVersion) : that.fromVersion != null) {
-      return false;
-    }
-    if (toVersion != null ? !toVersion.equals(that.toVersion) : that.toVersion != 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 + (fromVersion != null ? fromVersion.hashCode() : 0);
-    result = 31 * result + (toVersion != null ? toVersion.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/522039eb/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..8bfafd3
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java
@@ -0,0 +1,232 @@
+/**
+ * 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 org.apache.hadoop.metrics2.sink.relocated.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/522039eb/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
index de0f282..4942f27 100644
--- 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
@@ -17,10 +17,6 @@
  */
 package org.apache.ambari.server.serveraction.upgrades;
 
-import java.util.Collections;
-import java.util.Set;
-
-import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.serveraction.AbstractServerAction;
 import org.apache.ambari.server.state.Cluster;
@@ -28,11 +24,7 @@ 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 org.apache.ambari.server.state.stack.upgrade.Direction;
-import org.apache.ambari.server.state.stack.upgrade.UpgradeScope;
-import org.apache.commons.lang.StringUtils;
 
-import com.google.common.collect.Sets;
 import com.google.inject.Inject;
 
 /**
@@ -42,25 +34,8 @@ public abstract class AbstractUpgradeServerAction extends AbstractServerAction {
 
   public static final String CLUSTER_NAME_KEY = UpgradeContext.COMMAND_PARAM_CLUSTER_NAME;
   public static final String UPGRADE_DIRECTION_KEY = UpgradeContext.COMMAND_PARAM_DIRECTION;
-  public static final String VERSION_KEY = UpgradeContext.COMMAND_PARAM_VERSION;
   protected static final String REQUEST_ID = UpgradeContext.COMMAND_PARAM_REQUEST_ID;
 
-  /**
-   * The original "current" stack of the cluster before the upgrade started.
-   * This is the same regardless of whether the current direction is
-   * {@link Direction#UPGRADE} or {@link Direction#DOWNGRADE}.
-   */
-  protected static final String ORIGINAL_STACK_KEY = UpgradeContext.COMMAND_PARAM_ORIGINAL_STACK;
-
-  /**
-   * The target upgrade stack before the upgrade started. This is the same
-   * regardless of whether the current direction is {@link Direction#UPGRADE} or
-   * {@link Direction#DOWNGRADE}.
-   */
-  protected static final String TARGET_STACK_KEY = UpgradeContext.COMMAND_PARAM_TARGET_STACK;
-
-  protected static final String SUPPORTED_SERVICES_KEY = UpgradeResourceProvider.COMMAND_PARAM_SUPPORTED_SERVICES;
-
   @Inject
   protected Clusters m_clusters;
 
@@ -83,22 +58,6 @@ public abstract class AbstractUpgradeServerAction extends AbstractServerAction {
   protected UpgradeContext getUpgradeContext(Cluster cluster) {
     UpgradeEntity upgrade = cluster.getUpgradeInProgress();
     UpgradeContext upgradeContext = m_upgradeContextFactory.create(cluster, upgrade);
-
-    final UpgradeScope scope;
-    final Set<String> supportedServices;
-    String services = getCommandParameterValue(SUPPORTED_SERVICES_KEY);
-    if (StringUtils.isBlank(services)) {
-      scope = UpgradeScope.COMPLETE;
-      supportedServices = Collections.emptySet();
-
-    } else {
-      scope = UpgradeScope.PARTIAL;
-      supportedServices = Sets.newHashSet(StringUtils.split(services, ','));
-    }
-
-    upgradeContext.setSupportedServices(supportedServices);
-    upgradeContext.setScope(scope);
-
     return upgradeContext;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/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 4a3bd9b..dc7bc10 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
@@ -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;
@@ -54,7 +53,7 @@ public class ComponentVersionCheckAction extends FinalizeUpgradeAction {
     Cluster cluster = m_clusters.getCluster(clusterName);
 
     UpgradeContext upgradeContext = getUpgradeContext(cluster);
-    List<InfoTuple> errors = getHostComponentsWhichDidNotUpgrade(upgradeContext);
+    Set<InfoTuple> errors = validateComponentVersions(upgradeContext);
 
     StringBuilder outSB = new StringBuilder();
     StringBuilder errSB = new StringBuilder();
@@ -69,19 +68,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);
 
@@ -93,6 +94,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/522039eb/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java
index 1b9fb23..c4e073c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java
@@ -20,11 +20,13 @@ package org.apache.ambari.server.serveraction.upgrades;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.text.MessageFormat;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.ambari.server.AmbariException;
@@ -35,17 +37,12 @@ import org.apache.ambari.server.events.StackUpgradeFinishEvent;
 import org.apache.ambari.server.events.publishers.VersionEventPublisher;
 import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
-import org.apache.ambari.server.orm.dao.ServiceComponentDesiredStateDAO;
-import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.HostVersionEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
-import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
-import org.apache.ambari.server.orm.entities.ServiceComponentHistoryEntity;
-import org.apache.ambari.server.orm.entities.StackEntity;
-import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.RepositoryType;
 import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
@@ -55,6 +52,7 @@ import org.apache.ambari.server.state.UpgradeContext;
 import org.apache.ambari.server.state.UpgradeState;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.builder.EqualsBuilder;
 import org.apache.commons.lang.text.StrBuilder;
 
 import com.google.inject.Inject;
@@ -73,18 +71,6 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction {
   @Inject
   private HostComponentStateDAO hostComponentStateDAO;
 
-  /**
-   * Gets {@link StackEntity} instances from {@link StackId}.
-   */
-  @Inject
-  private StackDAO stackDAO;
-
-  /**
-   * Gets desired state entities for service components.
-   */
-  @Inject
-  private ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO;
-
   @Inject
   private AmbariMetaInfo ambariMetaInfo;
 
@@ -120,26 +106,26 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction {
     StringBuilder errSB = new StringBuilder();
 
     try {
+      Cluster cluster = upgradeContext.getCluster();
+      RepositoryVersionEntity repositoryVersion = upgradeContext.getRepositoryVersion();
+      String version = repositoryVersion.getVersion();
+
       String message;
-      Set<String> servicesInUpgrade = upgradeContext.getSupportedServices();
-      if (servicesInUpgrade.isEmpty()) {
-        message = MessageFormat.format("Finalizing the upgrade to {0} for all cluster services.",
-            upgradeContext.getVersion());
+      if (upgradeContext.getRepositoryType() == RepositoryType.STANDARD) {
+        message = MessageFormat.format("Finalizing the upgrade to {0} for all cluster services.", version);
       } else {
+        Set<String> servicesInUpgrade = upgradeContext.getSupportedServices();
+
         message = MessageFormat.format(
             "Finalizing the upgrade to {0} for the following services: {1}",
-            upgradeContext.getVersion(), StringUtils.join(servicesInUpgrade, ','));
+            version, StringUtils.join(servicesInUpgrade, ','));
       }
 
       outSB.append(message).append(System.lineSeparator());
 
-      Cluster cluster = upgradeContext.getCluster();
-      String version = upgradeContext.getVersion();
-      RepositoryVersionEntity repositoryVersion = upgradeContext.getTargetRepositoryVersion();
-
       // iterate through all host components and make sure that they are on the
       // correct version; if they are not, then this will throw an exception
-      List<InfoTuple> errors = getHostComponentsWhichDidNotUpgrade(upgradeContext);
+      Set<InfoTuple> errors = validateComponentVersions(upgradeContext);
       if (!errors.isEmpty()) {
         StrBuilder messageBuff = new StrBuilder(String.format(
             "The following %d host component(s) "
@@ -181,10 +167,10 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction {
 
       // throw an exception if there are hosts which are not not fully upgraded
       if (hostsWithoutCorrectVersionState.size() > 0) {
-        message = String.format("The following %d host(s) have not been upgraded to version %s. " +
-                "Please install and upgrade the Stack Version on those hosts and try again.\nHosts: %s",
-            hostsWithoutCorrectVersionState.size(),
-            version,
+        message = String.format(
+            "The following %d host(s) have not been upgraded to version %s. "
+                + "Please install and upgrade the Stack Version on those hosts and try again.\nHosts: %s",
+            hostsWithoutCorrectVersionState.size(), version,
             StringUtils.join(hostsWithoutCorrectVersionState, ", "));
         outSB.append(message);
         outSB.append(System.lineSeparator());
@@ -211,13 +197,10 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction {
 
       versionEventPublisher.publish(new StackUpgradeFinishEvent(cluster));
 
-      outSB.append("Creating upgrade history...").append(System.lineSeparator());
-      writeComponentHistory(upgradeContext);
-
       // Reset upgrade state
       cluster.setUpgradeEntity(null);
 
-      message = String.format("The upgrade to %s has completed.", upgradeContext.getVersion());
+      message = String.format("The upgrade to %s has completed.", version);
       outSB.append(message).append(System.lineSeparator());
       return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outSB.toString(), errSB.toString());
     } catch (Exception e) {
@@ -241,17 +224,20 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction {
 
     try {
       Cluster cluster = upgradeContext.getCluster();
-      RepositoryVersionEntity repositoryVersion = upgradeContext.getTargetRepositoryVersion();
+      RepositoryVersionEntity downgradeFromRepositoryVersion = upgradeContext.getRepositoryVersion();
+      String downgradeFromVersion = downgradeFromRepositoryVersion.getVersion();
 
       String message;
-      Set<String> servicesInUpgrade = upgradeContext.getSupportedServices();
-      if (servicesInUpgrade.isEmpty()) {
-        message = MessageFormat.format("Finalizing the downgrade to {0} for all cluster services.",
-            upgradeContext.getVersion());
+
+      if (downgradeFromRepositoryVersion.getType() == RepositoryType.STANDARD) {
+        message = MessageFormat.format(
+            "Finalizing the downgrade from {0} for all cluster services.",
+            downgradeFromVersion);
       } else {
+        Set<String> servicesInUpgrade = upgradeContext.getSupportedServices();
         message = MessageFormat.format(
-            "Finalizing the downgrade to {0} for the following services: {1}",
-            upgradeContext.getVersion(), StringUtils.join(servicesInUpgrade, ','));
+            "Finalizing the downgrade from {0} for the following services: {1}",
+            downgradeFromVersion, StringUtils.join(servicesInUpgrade, ','));
       }
 
       outSB.append(message).append(System.lineSeparator());
@@ -259,41 +245,50 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction {
 
       // iterate through all host components and make sure that they are on the
       // correct version; if they are not, then this will throw an exception
-      List<InfoTuple> errors = getHostComponentsWhichDidNotUpgrade(upgradeContext);
+      Set<InfoTuple> errors = validateComponentVersions(upgradeContext);
       if (!errors.isEmpty()) {
         StrBuilder messageBuff = new StrBuilder(String.format(
-            "The following %d host component(s) " + "have not been downgraded to version %s\n",
-            errors.size(), upgradeContext.getVersion())).append(System.lineSeparator());
+            "The following %d host component(s) have not been downgraded to their desired versions:",
+            errors.size())).append(System.lineSeparator());
 
         for (InfoTuple error : errors) {
-          messageBuff.append(String.format("%s on host %s", error.componentName, error.hostName));
+          messageBuff.append(String.format("%s: $s (current = %s, desired = %s ", error.hostName,
+              error.componentName, error.currentVersion, error.targetVersion));
+
           messageBuff.append(System.lineSeparator());
         }
 
         throw new AmbariException(messageBuff.toString());
       }
 
-      // find host versions
-      List<HostVersionEntity> hostVersions = hostVersionDAO.findHostVersionByClusterAndRepository(
-          cluster.getClusterId(), repositoryVersion);
+      // for every repository being downgraded to, ensure the host versions are correct
+      Map<String, RepositoryVersionEntity> targetVersionsByService = upgradeContext.getTargetVersions();
+      Set<RepositoryVersionEntity> targetRepositoryVersions = new HashSet<>();
+      for (String service : targetVersionsByService.keySet()) {
+        targetRepositoryVersions.add(targetVersionsByService.get(service));
+      }
 
-      outSB.append(
-          String.format("Finalizing the downgrade state of %d host(s).",
-              hostVersions.size())).append(
-              System.lineSeparator());
-
-      for( HostVersionEntity hostVersion : hostVersions ){
-        if (hostVersion.getState() != RepositoryVersionState.CURRENT) {
-          hostVersion.setState(RepositoryVersionState.CURRENT);
-          hostVersionDAO.merge(hostVersion);
-        }
+      for (RepositoryVersionEntity targetRepositoryVersion : targetRepositoryVersions) {
+        // find host versions
+        List<HostVersionEntity> hostVersions = hostVersionDAO.findHostVersionByClusterAndRepository(
+            cluster.getClusterId(), targetRepositoryVersion);
 
-        List<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findByHost(
-            hostVersion.getHostName());
+        outSB.append(String.format("Finalizing %d host(s) back to %s", hostVersions.size(),
+            targetRepositoryVersion.getVersion())).append(System.lineSeparator());
 
-        for (HostComponentStateEntity hostComponentState : hostComponentStates) {
-          hostComponentState.setUpgradeState(UpgradeState.NONE);
-          hostComponentStateDAO.merge(hostComponentState);
+        for (HostVersionEntity hostVersion : hostVersions) {
+          if (hostVersion.getState() != RepositoryVersionState.CURRENT) {
+            hostVersion.setState(RepositoryVersionState.CURRENT);
+            hostVersionDAO.merge(hostVersion);
+          }
+
+          List<HostComponentStateEntity> hostComponentStates = hostComponentStateDAO.findByHost(
+              hostVersion.getHostName());
+
+          for (HostComponentStateEntity hostComponentState : hostComponentStates) {
+            hostComponentState.setUpgradeState(UpgradeState.NONE);
+            hostComponentStateDAO.merge(hostComponentState);
+          }
         }
       }
 
@@ -304,7 +299,7 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction {
       // Reset upgrade state
       cluster.setUpgradeEntity(null);
 
-      message = String.format("The downgrade to %s has completed.", upgradeContext.getVersion());
+      message = String.format("The downgrade from %s has completed.", downgradeFromVersion);
       outSB.append(message).append(System.lineSeparator());
 
       return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", outSB.toString(), errSB.toString());
@@ -317,114 +312,133 @@ public class FinalizeUpgradeAction extends AbstractUpgradeServerAction {
     }
   }
 
-
   /**
-   * Gets any host components which have not been propertly upgraded.
+   * Gets any host components which have not been propertly upgraded or
+   * downgraded.
    *
    * @param upgradeContext
    *          the upgrade context (not {@code null}).
    * @return a list of {@link InfoTuple} representing components which should
    *         have been upgraded but did not.
    */
-  protected List<InfoTuple> getHostComponentsWhichDidNotUpgrade(UpgradeContext upgradeContext)
-          throws AmbariException {
+  protected Set<InfoTuple> validateComponentVersions(UpgradeContext upgradeContext)
+      throws AmbariException {
 
-    ArrayList<InfoTuple> errors = new ArrayList<>();
+    Set<InfoTuple> errors = new TreeSet<>();
 
     Cluster cluster = upgradeContext.getCluster();
-    Set<String> supportedServices = upgradeContext.getSupportedServices();
-    RepositoryVersionEntity repositoryVersionEntity = upgradeContext.getTargetRepositoryVersion();
+    RepositoryVersionEntity repositoryVersionEntity = upgradeContext.getRepositoryVersion();
     StackId targetStackId = repositoryVersionEntity.getStackId();
 
-    for (Service service : cluster.getServices().values()) {
-
-      // !!! if there are supported services for upgrade, and the cluster service is NOT in the list, skip
-      if (!supportedServices.isEmpty() && !supportedServices.contains(service.getName())) {
-        continue;
-      }
+    Set<String> servicesParticipating = upgradeContext.getSupportedServices();
+    for( String serviceName : servicesParticipating ){
+      Service service = cluster.getService(serviceName);
+      String targetVersion = upgradeContext.getTargetVersion(serviceName);
 
       for (ServiceComponent serviceComponent : service.getServiceComponents().values()) {
         for (ServiceComponentHost serviceComponentHost : serviceComponent.getServiceComponentHosts().values()) {
           ComponentInfo componentInfo = ambariMetaInfo.getComponent(targetStackId.getStackName(),
                   targetStackId.getStackVersion(), service.getName(), serviceComponent.getName());
 
-          if (componentInfo.isVersionAdvertised()) {
-            if (!StringUtils.equals(upgradeContext.getVersion(),
-                serviceComponentHost.getVersion())) {
-              errors.add(new InfoTuple(service.getName(), serviceComponent.getName(),
-                  serviceComponentHost.getHostName(), serviceComponentHost.getVersion()));
-            }
+          if (!componentInfo.isVersionAdvertised()) {
+            continue;
+          }
+
+          if (!StringUtils.equals(targetVersion, serviceComponentHost.getVersion())) {
+            errors.add(new InfoTuple(service.getName(), serviceComponent.getName(),
+                serviceComponentHost.getHostName(), serviceComponentHost.getVersion(),
+                targetVersion));
           }
         }
       }
     }
 
+
     return errors;
   }
 
-  /**
-   * Writes the upgrade history for all components which participated in the
-   * upgrade.
-   *
-   * @param upgradeContext  the upgrade context (not {@code null}).
-   */
-  private void writeComponentHistory(UpgradeContext upgradeContext) throws AmbariException {
-    Cluster cluster = upgradeContext.getCluster();
-    UpgradeEntity upgradeEntity = cluster.getUpgradeInProgress();
-    Collection<Service> services = cluster.getServices().values();
-    RepositoryVersionEntity repositoryVersion = upgradeContext.getTargetRepositoryVersion();
-    StackId sourcceStackId = upgradeContext.getOriginalStackId();
-    StackId targetStackId = repositoryVersion.getStackId();
+  protected static class InfoTuple implements Comparable<InfoTuple> {
+    protected final String serviceName;
+    protected final String componentName;
+    protected final String hostName;
+    protected final String currentVersion;
+    protected final String targetVersion;
 
-    StackEntity fromStack = stackDAO.find(sourcceStackId.getStackName(), sourcceStackId.getStackVersion());
-    StackEntity toStack = stackDAO.find(targetStackId.getStackName(), targetStackId.getStackVersion());
+    protected InfoTuple(String service, String component, String host, String version,
+        String desiredVersion) {
+      serviceName = service;
+      componentName = component;
+      hostName = host;
+      currentVersion = version;
+      targetVersion = desiredVersion;
+    }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int compareTo(InfoTuple that) {
+      int compare = hostName.compareTo(that.hostName);
+      if (compare != 0) {
+        return compare;
+      }
 
-    if (!upgradeContext.getSupportedServices().isEmpty()) {
-      services = new ArrayList<>();
+      compare = serviceName.compareTo(that.serviceName);
+      if (compare != 0) {
+        return compare;
+      }
 
-      Set<String> serviceNames = upgradeContext.getSupportedServices();
-      for (String serviceName : serviceNames) {
-        services.add(cluster.getService(serviceName));
+      compare = componentName.compareTo(that.componentName);
+      if (compare != 0) {
+        return compare;
       }
+
+      return compare;
     }
 
-    // for every service component, if it was included in the upgrade then
-    // create a historical entry
-    for (Service service : services) {
-      for (ServiceComponent serviceComponent : service.getServiceComponents().values()) {
-        if (serviceComponent.isVersionAdvertised()) {
-          // create the historical entry
-          ServiceComponentHistoryEntity historyEntity = new ServiceComponentHistoryEntity();
-          historyEntity.setUpgrade(upgradeEntity);
-          historyEntity.setFromStack(fromStack);
-          historyEntity.setToStack(toStack);
-
-          // get the service component
-          ServiceComponentDesiredStateEntity desiredStateEntity = serviceComponentDesiredStateDAO.findByName(
-              cluster.getClusterId(), serviceComponent.getServiceName(),
-              serviceComponent.getName());
-
-          // add the history to the component and save
-          desiredStateEntity.addHistory(historyEntity);
-          serviceComponentDesiredStateDAO.merge(desiredStateEntity);
-        }
-      }
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+      return Objects.hash(hostName, serviceName, componentName, currentVersion, targetVersion);
     }
-  }
 
-  protected static class InfoTuple {
-    protected final String serviceName;
-    protected final String componentName;
-    protected final String hostName;
-    protected final String currentVersion;
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean equals(Object object) {
+      if (this == object) {
+        return true;
+      }
 
-    protected InfoTuple(String service, String component, String host, String version) {
-      serviceName = service;
-      componentName = component;
-      hostName = host;
-      currentVersion = version;
+      if (object == null || getClass() != object.getClass()) {
+        return false;
+      }
+
+      InfoTuple that = (InfoTuple) object;
+
+      EqualsBuilder equalsBuilder = new EqualsBuilder();
+      equalsBuilder.append(hostName, that.hostName);
+      equalsBuilder.append(serviceName, that.serviceName);
+      equalsBuilder.append(componentName, that.componentName);
+      equalsBuilder.append(currentVersion, that.currentVersion);
+      equalsBuilder.append(targetVersion, that.targetVersion);
+      ;
+      return equalsBuilder.isEquals();
     }
-  }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+      return com.google.common.base.Objects.toStringHelper(this)
+          .add("host", hostName)
+          .add("component", componentName)
+          .add("current", currentVersion)
+          .add("target", targetVersion).toString();
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java
index 4500b5d..657cb07 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/UpdateDesiredStackAction.java
@@ -17,8 +17,6 @@
  */
 package org.apache.ambari.server.serveraction.upgrades;
 
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.VERSION;
-
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.text.MessageFormat;
@@ -30,21 +28,18 @@ 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.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariServer;
 import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.entities.HostVersionEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
-import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.serveraction.ServerAction;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.RepositoryType;
 import org.apache.ambari.server.state.RepositoryVersionState;
-import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.UpgradeContext;
-import org.apache.ambari.server.state.stack.UpgradePack;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
@@ -66,8 +61,6 @@ public class UpdateDesiredStackAction extends AbstractUpgradeServerAction {
    */
   private static final Logger LOG = LoggerFactory.getLogger(UpdateDesiredStackAction.class);
 
-  public static final String COMMAND_PARAM_VERSION = VERSION;
-  public static final String COMMAND_DOWNGRADE_FROM_VERSION = "downgrade_from_version";
   public static final String COMMAND_PARAM_DIRECTION = "upgrade_direction";
   public static final String COMMAND_PARAM_UPGRADE_PACK = "upgrade_pack";
 
@@ -91,9 +84,6 @@ public class UpdateDesiredStackAction extends AbstractUpgradeServerAction {
   @Inject
   private Clusters clusters;
 
-  @Inject
-  private AmbariMetaInfo ambariMetaInfo;
-
   /**
    * The Ambari configuration.
    */
@@ -113,21 +103,10 @@ public class UpdateDesiredStackAction extends AbstractUpgradeServerAction {
   public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext)
       throws AmbariException, InterruptedException {
 
-    Map<String, String> commandParams = getExecutionCommand().getCommandParams();
     String clusterName = getExecutionCommand().getClusterName();
     Cluster cluster = clusters.getCluster(clusterName);
-    UpgradeEntity upgrade = cluster.getUpgradeInProgress();
-
     UpgradeContext upgradeContext = getUpgradeContext(cluster);
 
-    StackId originalStackId = new StackId(commandParams.get(COMMAND_PARAM_ORIGINAL_STACK));
-    StackId targetStackId = new StackId(commandParams.get(COMMAND_PARAM_TARGET_STACK));
-
-    String upgradePackName = upgrade.getUpgradePackage();
-
-    UpgradePack upgradePack = ambariMetaInfo.getUpgradePacks(originalStackId.getStackName(),
-        originalStackId.getStackVersion()).get(upgradePackName);
-
     Map<String, String> roleParams = getExecutionCommand().getRoleParams();
 
     // Make a best attempt at setting the username
@@ -142,8 +121,7 @@ public class UpdateDesiredStackAction extends AbstractUpgradeServerAction {
     // invalidate any cached effective ID
     cluster.invalidateUpgradeEffectiveVersion();
 
-    return updateDesiredRepositoryVersion(cluster, originalStackId, targetStackId, upgradeContext,
-        upgradePack, userName);
+    return updateDesiredRepositoryVersion(cluster, upgradeContext, userName);
   }
 
   /**
@@ -152,49 +130,62 @@ public class UpdateDesiredStackAction extends AbstractUpgradeServerAction {
    *
    * @param cluster
    *          the cluster
-   * @param originalStackId
-   *          the stack Id of the cluster before the upgrade.
-   * @param targetStackId
-   *          the stack Id that was desired for this upgrade.
-   * @param direction
-   *          direction, either upgrade or downgrade
-   * @param upgradePack
-   *          Upgrade Pack to use
+   * @param upgradeContext
+   *          the upgrade context
    * @param userName
    *          username performing the action
    * @return the command report to return
    */
   @Transactional
   CommandReport updateDesiredRepositoryVersion(
-      Cluster cluster, StackId originalStackId, StackId targetStackId,
-      UpgradeContext upgradeContext, UpgradePack upgradePack, String userName)
+      Cluster cluster, UpgradeContext upgradeContext, String userName)
       throws AmbariException, InterruptedException {
 
     StringBuilder out = new StringBuilder();
     StringBuilder err = new StringBuilder();
 
     try {
-      UpgradeResourceProvider upgradeResourceProvider = new UpgradeResourceProvider(AmbariServer.getController());
-      upgradeResourceProvider.applyStackAndProcessConfigurations(upgradeContext);
-      m_upgradeHelper.putComponentsToUpgradingState(upgradeContext);
+      // the desired repository message to put in the command report - this will
+      // change based on the type of upgrade and the services participating
+      if (upgradeContext.getDirection() == Direction.UPGRADE) {
+        final String message;
+        RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getRepositoryVersion();
+
+        if (upgradeContext.getRepositoryType() == RepositoryType.STANDARD) {
+          message = MessageFormat.format(
+              "Updating the desired repository version to {0} for all cluster services.",
+              targetRepositoryVersion.getVersion());
+        } else {
+          Set<String> servicesInUpgrade = upgradeContext.getSupportedServices();
+          message = MessageFormat.format(
+              "Updating the desired repository version to {0} for the following services: {1}",
+              targetRepositoryVersion.getVersion(), StringUtils.join(servicesInUpgrade, ','));
+        }
 
-      final String message;
-      Set<String> servicesInUpgrade = upgradeContext.getSupportedServices();
-      if (servicesInUpgrade.isEmpty()) {
-        message = MessageFormat.format(
-            "Updating the desired repository version to {0} for all cluster services.",
-            upgradeContext.getVersion());
-      } else {
-        message = MessageFormat.format(
-            "Updating the desired repository version to {0} for the following services: {1}",
-            upgradeContext.getVersion(), StringUtils.join(servicesInUpgrade, ','));
+        out.append(message).append(System.lineSeparator());
       }
 
-      out.append(message).append(System.lineSeparator());
+      if( upgradeContext.getDirection() == Direction.DOWNGRADE ){
+        String message = "Updating the desired repository back their original values for the following services:";
+        out.append(message).append(System.lineSeparator());
+
+        Map<String, RepositoryVersionEntity> targetVersionsByService = upgradeContext.getTargetVersions();
+        for (String serviceName : targetVersionsByService.keySet()) {
+          RepositoryVersionEntity repositoryVersion = targetVersionsByService.get(serviceName);
+
+          message = String.format("  %s to %s", serviceName, repositoryVersion.getVersion());
+          out.append(message).append(System.lineSeparator());
+        }
+      }
+
+      UpgradeResourceProvider upgradeResourceProvider = new UpgradeResourceProvider(AmbariServer.getController());
+      upgradeResourceProvider.applyStackAndProcessConfigurations(upgradeContext);
+      m_upgradeHelper.putComponentsToUpgradingState(upgradeContext);
 
-      // a downgrade must force host versions back to INSTALLED, but only if it's required
+      // a downgrade must force host versions back to INSTALLED for the
+      // repository which failed to be upgraded.
       if (upgradeContext.getDirection() == Direction.DOWNGRADE) {
-        RepositoryVersionEntity downgradeFromRepositoryVersion = upgradeContext.getDowngradeFromRepositoryVersion();
+        RepositoryVersionEntity downgradeFromRepositoryVersion = upgradeContext.getRepositoryVersion();
         out.append(String.format("Setting host versions back to %s for repository version %s",
             RepositoryVersionState.INSTALLED, downgradeFromRepositoryVersion.getVersion()));
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/stack/MasterHostResolver.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/MasterHostResolver.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/MasterHostResolver.java
index ce10568..3f1d859 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/MasterHostResolver.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/MasterHostResolver.java
@@ -30,13 +30,15 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
-import org.apache.ambari.server.state.UpgradeState;
+import org.apache.ambari.server.state.UpgradeContext;
+import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.utils.HTTPUtils;
 import org.apache.ambari.server.utils.HostAndPort;
 import org.apache.ambari.server.utils.StageUtils;
@@ -51,9 +53,9 @@ public class MasterHostResolver {
 
   private static Logger LOG = LoggerFactory.getLogger(MasterHostResolver.class);
 
-  private Cluster m_cluster;
-  private String m_version;
-  private ConfigHelper m_configHelper;
+  private final UpgradeContext m_upgradeContext;
+  private final Cluster m_cluster;
+  private final ConfigHelper m_configHelper;
 
   public enum Service {
     HDFS,
@@ -71,29 +73,17 @@ public class MasterHostResolver {
   }
 
   /**
-   * Create a resolver that does not consider HostComponents' version when
-   * resolving hosts.  Common use case is creating an upgrade that should
-   * include an entire cluster.
-   * @param configHelper Configuration Helper
-   * @param cluster the cluster
-   */
-  public MasterHostResolver(ConfigHelper configHelper, Cluster cluster) {
-    this(configHelper, cluster, null);
-  }
-
-  /**
-   * Create a resolver that compares HostComponents' version when calculating
-   * hosts for the stage.  Common use case is for downgrades when only some
-   * HostComponents need to be downgraded, and HostComponents already at the
-   * correct version are skipped.
-   * @param configHelper Configuration Helper
-   * @param cluster the cluster
-   * @param version the version, or {@code null} to not compare versions
+   * Constructor.
+   *
+   * @param configHelper
+   *          Configuration Helper
+   * @param upgradeContext
+   *          the upgrade context
    */
-  public MasterHostResolver(ConfigHelper configHelper, Cluster cluster, String version) {
+  public MasterHostResolver(ConfigHelper configHelper, UpgradeContext upgradeContext) {
     m_configHelper = configHelper;
-    m_cluster = cluster;
-    m_version = version;
+    m_upgradeContext = upgradeContext;
+    m_cluster = upgradeContext.getCluster();
   }
 
   /**
@@ -216,10 +206,20 @@ public class MasterHostResolver {
         // possible
         if (maintenanceState != MaintenanceState.OFF) {
           unhealthyHosts.add(sch);
-        } else if (null == m_version || null == sch.getVersion() ||
-            !sch.getVersion().equals(m_version) ||
-            sch.getUpgradeState() == UpgradeState.FAILED) {
+          continue;
+        }
+
+        if(m_upgradeContext.getDirection() == Direction.UPGRADE){
+          upgradeHosts.add(hostName);
+          continue;
+        }
+
+        // it's a downgrade ...
+        RepositoryVersionEntity downgradeToRepositoryVersion = m_upgradeContext.getTargetRepositoryVersion(service);
+        String downgradeToVersion = downgradeToRepositoryVersion.getVersion();
+        if (!StringUtils.equals(downgradeToVersion, sch.getVersion())) {
           upgradeHosts.add(hostName);
+          continue;
         }
       }