ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nc...@apache.org
Subject [31/37] ambari git commit: AMBARI-21450. Initial cherry-picking for feature branch (ncole)
Date Thu, 13 Jul 2017 19:14:49 GMT
http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
index 1130026..5d02de3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.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
@@ -23,13 +23,10 @@ import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_P
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -65,32 +62,24 @@ import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
-import org.apache.ambari.server.controller.utilities.PredicateBuilder;
-import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
 import org.apache.ambari.server.orm.dao.HostRoleCommandStatusSummaryDTO;
-import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.RequestEntity;
-import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
+import org.apache.ambari.server.orm.entities.UpgradeHistoryEntity;
 import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
-import org.apache.ambari.server.serveraction.upgrades.UpdateDesiredStackAction;
-import org.apache.ambari.server.stack.MasterHostResolver;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
-import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigHelper;
-import org.apache.ambari.server.state.DesiredConfig;
-import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceInfo;
@@ -101,32 +90,26 @@ import org.apache.ambari.server.state.UpgradeContextFactory;
 import org.apache.ambari.server.state.UpgradeHelper;
 import org.apache.ambari.server.state.UpgradeHelper.UpgradeGroupHolder;
 import org.apache.ambari.server.state.stack.ConfigUpgradePack;
-import org.apache.ambari.server.state.stack.PrereqCheckStatus;
 import org.apache.ambari.server.state.stack.UpgradePack;
 import org.apache.ambari.server.state.stack.upgrade.ConfigureTask;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
-import org.apache.ambari.server.state.stack.upgrade.Grouping;
-import org.apache.ambari.server.state.stack.upgrade.HostOrderGrouping;
-import org.apache.ambari.server.state.stack.upgrade.HostOrderItem;
-import org.apache.ambari.server.state.stack.upgrade.HostOrderItem.HostOrderActionType;
 import org.apache.ambari.server.state.stack.upgrade.ManualTask;
 import org.apache.ambari.server.state.stack.upgrade.ServerSideActionTask;
 import org.apache.ambari.server.state.stack.upgrade.StageWrapper;
 import org.apache.ambari.server.state.stack.upgrade.Task;
 import org.apache.ambari.server.state.stack.upgrade.TaskWrapper;
 import org.apache.ambari.server.state.stack.upgrade.UpdateStackGrouping;
-import org.apache.ambari.server.state.stack.upgrade.UpgradeScope;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.apache.ambari.server.state.svccomphost.ServiceComponentHostServerActionEvent;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
+import org.codehaus.jackson.annotate.JsonProperty;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
 import com.google.inject.Inject;
@@ -141,14 +124,13 @@ import com.google.inject.persist.Transactional;
 public class UpgradeResourceProvider extends AbstractControllerResourceProvider {
 
   public static final String UPGRADE_CLUSTER_NAME = "Upgrade/cluster_name";
-  public static final String UPGRADE_REPO_ID = "Upgrade/repository_id";
-  public static final String UPGRADE_REPO_NAME = "Upgrade/repository_name";
-  public static final String UPGRADE_REPO_VERSION = "Upgrade/repository_version";
+  public static final String UPGRADE_REPO_VERSION_ID = "Upgrade/repository_version_id";
   public static final String UPGRADE_TYPE = "Upgrade/upgrade_type";
   public static final String UPGRADE_PACK = "Upgrade/pack";
+  public static final String UPGRADE_ID = "Upgrade/upgrade_id";
   public static final String UPGRADE_REQUEST_ID = "Upgrade/request_id";
-  public static final String UPGRADE_FROM_VERSION = "Upgrade/from_version";
-  public static final String UPGRADE_TO_VERSION = "Upgrade/to_version";
+  public static final String UPGRADE_ASSOCIATED_VERSION = "Upgrade/associated_version";
+  public static final String UPGRADE_VERSIONS = "Upgrade/versions";
   public static final String UPGRADE_DIRECTION = "Upgrade/direction";
   public static final String UPGRADE_DOWNGRADE_ALLOWED = "Upgrade/downgrade_allowed";
   public static final String UPGRADE_REQUEST_STATUS = "Upgrade/request_status";
@@ -157,32 +139,20 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   public static final String UPGRADE_SKIP_PREREQUISITE_CHECKS = "Upgrade/skip_prerequisite_checks";
   public static final String UPGRADE_FAIL_ON_CHECK_WARNINGS = "Upgrade/fail_on_check_warnings";
 
-
-  /**
-   * Names that appear in the Upgrade Packs that are used by
-   * {@link org.apache.ambari.server.state.cluster.ClusterImpl#isNonRollingUpgradePastUpgradingStack}
-   * to determine if an upgrade has already changed the version to use.
-   * For this reason, DO NOT CHANGE the name of these since they represent historic values.
-   */
-  public static final String CONST_UPGRADE_GROUP_NAME = "UPDATE_DESIRED_STACK_ID";
-  public static final String CONST_UPGRADE_ITEM_TEXT = "Update Target Stack";
-  public static final String CONST_CUSTOM_COMMAND_NAME = UpdateDesiredStackAction.class.getName();
-
-
   /**
    * Skip slave/client component failures if the tasks are skippable.
    */
-  protected static final String UPGRADE_SKIP_FAILURES = "Upgrade/skip_failures";
+  public static final String UPGRADE_SKIP_FAILURES = "Upgrade/skip_failures";
 
   /**
    * Skip service check failures if the tasks are skippable.
    */
-  protected static final String UPGRADE_SKIP_SC_FAILURES = "Upgrade/skip_service_check_failures";
+  public static final String UPGRADE_SKIP_SC_FAILURES = "Upgrade/skip_service_check_failures";
 
   /**
    * Skip manual verification tasks for hands-free upgrade/downgrade experience.
    */
-  protected static final String UPGRADE_SKIP_MANUAL_VERIFICATION = "Upgrade/skip_manual_verification";
+  public static final String UPGRADE_SKIP_MANUAL_VERIFICATION = "Upgrade/skip_manual_verification";
 
   /**
    * When creating an upgrade of type {@link UpgradeType#HOST_ORDERED}, this
@@ -203,7 +173,12 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
    * </pre>
    *
    */
-  protected static final String UPGRADE_HOST_ORDERED_HOSTS = "Upgrade/host_order";
+  public static final String UPGRADE_HOST_ORDERED_HOSTS = "Upgrade/host_order";
+
+  /**
+   * Allows reversion of a successful upgrade of a patch.
+   */
+  public static final String UPGRADE_REVERT_UPGRADE_ID = "Upgrade/revert_upgrade_id";
 
   /**
    * The role that will be used when creating HRC's for the type
@@ -226,8 +201,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
   private static final Set<String> PK_PROPERTY_IDS = new HashSet<>(
       Arrays.asList(UPGRADE_REQUEST_ID, UPGRADE_CLUSTER_NAME));
-  private static final Set<String> PROPERTY_IDS = new HashSet<>();
 
+  private static final Set<String> PROPERTY_IDS = new HashSet<>();
 
   private static final String DEFAULT_REASON_TEMPLATE = "Aborting upgrade %s";
 
@@ -240,9 +215,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   private static Provider<AmbariMetaInfo> s_metaProvider = null;
 
   @Inject
-  private static RepositoryVersionDAO s_repoVersionDAO = null;
-
-  @Inject
   private static Provider<RequestFactory> s_requestFactory;
 
   @Inject
@@ -272,9 +244,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   @Inject
   private static Configuration s_configuration;
 
-  @Inject
-  private static Gson s_gson;
-
   /**
    * Used to create instances of {@link UpgradeContext} with injected
    * dependencies.
@@ -285,14 +254,13 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   static {
     // properties
     PROPERTY_IDS.add(UPGRADE_CLUSTER_NAME);
-    PROPERTY_IDS.add(UPGRADE_REPO_ID);
-    PROPERTY_IDS.add(UPGRADE_REPO_NAME);
-    PROPERTY_IDS.add(UPGRADE_REPO_VERSION);
+    PROPERTY_IDS.add(UPGRADE_REPO_VERSION_ID);
     PROPERTY_IDS.add(UPGRADE_TYPE);
     PROPERTY_IDS.add(UPGRADE_PACK);
+    PROPERTY_IDS.add(UPGRADE_ID);
     PROPERTY_IDS.add(UPGRADE_REQUEST_ID);
-    PROPERTY_IDS.add(UPGRADE_FROM_VERSION);
-    PROPERTY_IDS.add(UPGRADE_TO_VERSION);
+    PROPERTY_IDS.add(UPGRADE_ASSOCIATED_VERSION);
+    PROPERTY_IDS.add(UPGRADE_VERSIONS);
     PROPERTY_IDS.add(UPGRADE_DIRECTION);
     PROPERTY_IDS.add(UPGRADE_DOWNGRADE_ALLOWED);
     PROPERTY_IDS.add(UPGRADE_SUSPENDED);
@@ -302,6 +270,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     PROPERTY_IDS.add(UPGRADE_SKIP_PREREQUISITE_CHECKS);
     PROPERTY_IDS.add(UPGRADE_FAIL_ON_CHECK_WARNINGS);
     PROPERTY_IDS.add(UPGRADE_HOST_ORDERED_HOSTS);
+    PROPERTY_IDS.add(UPGRADE_REVERT_UPGRADE_ID);
 
     PROPERTY_IDS.add(REQUEST_CONTEXT_ID);
     PROPERTY_IDS.add(REQUEST_CREATE_TIME_ID);
@@ -362,75 +331,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
       @Override
       public UpgradeEntity invoke() throws AmbariException, AuthorizationException {
 
-        final String directionProperty = (String) requestMap.get(UPGRADE_DIRECTION);
-        if (StringUtils.isEmpty(directionProperty)) {
-          throw new AmbariException(String.format("%s is required", UPGRADE_DIRECTION));
-        }
-
-        final Direction direction = Direction.valueOf(directionProperty);
-
-        // Default to ROLLING upgrade, but attempt to read from properties.
-        UpgradeType upgradeType = UpgradeType.ROLLING;
-        if (requestMap.containsKey(UPGRADE_TYPE)) {
-          try {
-            upgradeType = UpgradeType.valueOf(requestMap.get(UPGRADE_TYPE).toString());
-          } catch (Exception e) {
-            throw new AmbariException(String.format("Property %s has an incorrect value of %s.",
-                UPGRADE_TYPE, requestMap.get(UPGRADE_TYPE)));
-          }
-        }
-
-        // use a combination of the supplied information to find the target
-        // repository
-        final String repositoryId = (String) requestMap.get(UPGRADE_REPO_ID);
-        final String repositoryName = (String) requestMap.get(UPGRADE_REPO_NAME);
-        final String repositoryVersion = (String) requestMap.get(UPGRADE_REPO_VERSION);
-
-        RepositoryVersionEntity toRepositoryVersion = null;
-
-        if (null != repositoryId) {
-          toRepositoryVersion = s_repoVersionDAO.findByPK(Long.valueOf(repositoryId));
-        } else {
-          if (StringUtils.isNotBlank(repositoryName)) {
-            toRepositoryVersion = s_repoVersionDAO.findByStackNameAndVersion(repositoryName,
-                repositoryVersion);
-          } else {
-            toRepositoryVersion = s_repoVersionDAO.findByVersion(repositoryVersion);
-          }
-        }
-
-        if (null == toRepositoryVersion) {
-          throw new AmbariException(
-              "Unable to find repository by any combination of id, name, or version");
-        }
-
-        // determine the correct "from" repo version which is based on upgrade
-        // direction
-        RepositoryVersionEntity fromRepositoryVersion = cluster.getCurrentClusterVersion().getRepositoryVersion();
-
-        if (direction.isDowngrade()) {
-          String downgradeFromVersion = (String) requestMap.get(UPGRADE_FROM_VERSION);
-
-          UpgradeEntity lastUpgradeItemForCluster = s_upgradeDAO.findLastUpgradeForCluster(
-              cluster.getClusterId(), Direction.UPGRADE);
-
-          RepositoryVersionEntity lastUpgradeTargetVersion = lastUpgradeItemForCluster.getToRepositoryVersion();
-          String lastUpgradeVersion = lastUpgradeTargetVersion.getVersion();
-          if (null != downgradeFromVersion
-              && !StringUtils.equals(downgradeFromVersion, lastUpgradeVersion)) {
-            throw new AmbariException(
-                "Unable to perform downgrade to " + toRepositoryVersion.getVersion()
-                    + " since there is no prior failed upgrade to " + downgradeFromVersion);
-          }
-
-          fromRepositoryVersion = lastUpgradeTargetVersion;
-        }
-
-        final UpgradeContext upgradeContext = s_upgradeContextFactory.create(cluster, upgradeType,
-            direction, fromRepositoryVersion, toRepositoryVersion, requestMap);
-
-        UpgradePack upgradePack = validateRequest(upgradeContext);
-        upgradeContext.setUpgradePack(upgradePack);
+        // create the context, validating the properties in the process
+        final UpgradeContext upgradeContext = s_upgradeContextFactory.create(cluster, requestMap);
 
         try {
           return createUpgrade(upgradeContext);
@@ -644,53 +546,38 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   private Resource toResource(UpgradeEntity entity, String clusterName, Set<String> requestedIds) {
     ResourceImpl resource = new ResourceImpl(Resource.Type.Upgrade);
 
+    setResourceProperty(resource, UPGRADE_ID, entity.getId(), requestedIds);
     setResourceProperty(resource, UPGRADE_CLUSTER_NAME, clusterName, requestedIds);
     setResourceProperty(resource, UPGRADE_TYPE, entity.getUpgradeType(), requestedIds);
     setResourceProperty(resource, UPGRADE_PACK, entity.getUpgradePackage(), requestedIds);
     setResourceProperty(resource, UPGRADE_REQUEST_ID, entity.getRequestId(), requestedIds);
-    setResourceProperty(resource, UPGRADE_FROM_VERSION, entity.getFromRepositoryVersion().getVersion(), requestedIds);
-    setResourceProperty(resource, UPGRADE_TO_VERSION, entity.getToRepositoryVersion().getVersion(), requestedIds);
     setResourceProperty(resource, UPGRADE_DIRECTION, entity.getDirection(), requestedIds);
     setResourceProperty(resource, UPGRADE_SUSPENDED, entity.isSuspended(), requestedIds);
     setResourceProperty(resource, UPGRADE_DOWNGRADE_ALLOWED, entity.isDowngradeAllowed(), requestedIds);
     setResourceProperty(resource, UPGRADE_SKIP_FAILURES, entity.isComponentFailureAutoSkipped(), requestedIds);
     setResourceProperty(resource, UPGRADE_SKIP_SC_FAILURES, entity.isServiceCheckFailureAutoSkipped(), requestedIds);
 
-    return resource;
-  }
-
-  /**
-   * Validates a singular API request.
-   *
-   * @param upgradeContext details about the upgrade such as direction and type
-   * @return the validated upgrade pack
-   * @throws AmbariException
-   */
-  private UpgradePack validateRequest(UpgradeContext upgradeContext) throws AmbariException {
-    Cluster cluster = upgradeContext.getCluster();
-    Direction direction = upgradeContext.getDirection();
-    String targetStackName = upgradeContext.getTargetStackId().getStackName();
-    Map<String, Object> requestMap = upgradeContext.getUpgradeRequest();
-    UpgradeType upgradeType = upgradeContext.getType();
-    RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion();
+    // set the assocaited to/from version (to/from is dictated by direction)
+    RepositoryVersionEntity repositoryVersion = entity.getRepositoryVersion();
+    setResourceProperty(resource, UPGRADE_ASSOCIATED_VERSION, repositoryVersion.getVersion(), requestedIds);
 
-    /**
-     * For the unit tests tests, there are multiple upgrade packs for the same type, so
-     * allow picking one of them. In prod, this is empty.
-     */
-    String preferredUpgradePackName = (String) requestMap.get(UPGRADE_PACK);
+    // now set the target verison for all services in the upgrade
+    Map<String, RepositoryVersions> repositoryVersions = new HashMap<>();
+    for( UpgradeHistoryEntity history : entity.getHistory() ){
+      RepositoryVersions serviceVersions = repositoryVersions.get(history.getServiceName());
+      if (null != serviceVersions) {
+        continue;
+      }
 
-    String version = targetRepositoryVersion.getVersion();
-    String versionForUpgradePack = (String) requestMap.get(UPGRADE_FROM_VERSION);
+      serviceVersions = new RepositoryVersions(history.getFromReposistoryVersion(),
+          history.getTargetRepositoryVersion());
 
-    UpgradePack pack = s_upgradeHelper.suggestUpgradePack(cluster.getClusterName(),
-        versionForUpgradePack, version, direction, upgradeType, targetStackName, preferredUpgradePackName);
+      repositoryVersions.put(history.getServiceName(), serviceVersions);
+    }
 
-    // the validator will throw an exception if the upgrade request is not valid
-    UpgradeRequestValidator upgradeRequestValidator = buildValidator(upgradeType);
-    upgradeRequestValidator.validate(upgradeContext, pack);
+    setResourceProperty(resource, UPGRADE_VERSIONS, repositoryVersions, requestedIds);
 
-    return pack;
+    return resource;
   }
 
   /**
@@ -750,95 +637,52 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     UpgradePack pack = upgradeContext.getUpgradePack();
     Cluster cluster = upgradeContext.getCluster();
     Direction direction = upgradeContext.getDirection();
-    Map<String, Object> requestMap = upgradeContext.getUpgradeRequest();
-    ConfigHelper configHelper = getManagementController().getConfigHelper();
-
-    // the version being upgraded to or downgraded from (ie 2.2.1.0-1234)
-    final RepositoryVersionEntity repositoryVersion = upgradeContext.getTargetRepositoryVersion();
-
-    MasterHostResolver resolver = null;
-    if (direction.isUpgrade()) {
-      resolver = new MasterHostResolver(configHelper, cluster);
-    } else {
-      resolver = new MasterHostResolver(configHelper, cluster,
-          upgradeContext.getTargetRepositoryVersion().getVersion());
-    }
 
-    Set<String> supportedServices = new HashSet<>();
-    UpgradeScope scope = UpgradeScope.COMPLETE;
-
-    upgradeContext.setResolver(resolver);
-    upgradeContext.setSupportedServices(supportedServices);
-    upgradeContext.setScope(scope);
-
-    if (direction.isDowngrade()) {
-      String downgradeFromVersion = (String) requestMap.get(UPGRADE_FROM_VERSION);
-
-      UpgradeEntity lastUpgradeItemForCluster = s_upgradeDAO.findLastUpgradeForCluster(
-          cluster.getClusterId(), Direction.UPGRADE);
-
-      String lastUpgradeVersion = lastUpgradeItemForCluster.getToRepositoryVersion().getVersion();
-      if (null != downgradeFromVersion
-          && !StringUtils.equals(downgradeFromVersion, lastUpgradeVersion)) {
-        throw new AmbariException("Unable to perform downgrade to " + repositoryVersion.getVersion()
-            + " since there is no prior failed upgrade to " + downgradeFromVersion);
-      }
-    }
-
-    // optionally skip failures - this can be supplied on either the request or
-    // in the upgrade pack explicitely, however the request will always override
-    // the upgrade pack if explicitely specified
-    boolean skipComponentFailures = pack.isComponentFailureAutoSkipped();
-    boolean skipServiceCheckFailures = pack.isServiceCheckFailureAutoSkipped();
-
-    // only override the upgrade pack if set on the request
-    if (requestMap.containsKey(UPGRADE_SKIP_FAILURES)) {
-      skipComponentFailures = Boolean.parseBoolean((String) requestMap.get(UPGRADE_SKIP_FAILURES));
-    }
-
-    // only override the upgrade pack if set on the request
-    if (requestMap.containsKey(UPGRADE_SKIP_SC_FAILURES)) {
-      skipServiceCheckFailures = Boolean.parseBoolean(
-          (String) requestMap.get(UPGRADE_SKIP_SC_FAILURES));
-    }
-
-    boolean skipManualVerification = false;
-    if(requestMap.containsKey(UPGRADE_SKIP_MANUAL_VERIFICATION)) {
-      skipManualVerification = Boolean.parseBoolean((String) requestMap.get(UPGRADE_SKIP_MANUAL_VERIFICATION));
-    }
-
-    upgradeContext.setAutoSkipComponentFailures(skipComponentFailures);
-    upgradeContext.setAutoSkipServiceCheckFailures(skipServiceCheckFailures);
-    upgradeContext.setAutoSkipManualVerification(skipManualVerification);
+    ConfigHelper configHelper = getManagementController().getConfigHelper();
 
     List<UpgradeGroupHolder> groups = s_upgradeHelper.createSequence(pack, upgradeContext);
 
-    if (groups.isEmpty()) {
+    if (1 == 1 || groups.isEmpty()) {
       throw new AmbariException("There are no groupings available");
     }
 
     // Non Rolling Upgrades require a group with name "UPDATE_DESIRED_STACK_ID".
     // This is needed as a marker to indicate which version to use when an upgrade is paused.
     if (pack.getType() == UpgradeType.NON_ROLLING) {
-      boolean foundGroupWithNameUPDATE_DESIRED_STACK_ID = false;
+      boolean foundUpdateDesiredRepositoryIdGrouping = false;
       for (UpgradeGroupHolder group : groups) {
-        if (group.name.equalsIgnoreCase(CONST_UPGRADE_GROUP_NAME)) {
-          foundGroupWithNameUPDATE_DESIRED_STACK_ID = true;
+        if (group.groupClass == UpdateStackGrouping.class) {
+          foundUpdateDesiredRepositoryIdGrouping = true;
           break;
         }
       }
 
-      if (foundGroupWithNameUPDATE_DESIRED_STACK_ID == false) {
-        throw new AmbariException(String.format("NonRolling Upgrade Pack %s requires a Group with name %s",
-            pack.getName(), CONST_UPGRADE_GROUP_NAME));
+      if (!foundUpdateDesiredRepositoryIdGrouping) {
+        throw new AmbariException(String.format(
+            "Express upgrade packs are required to have a group of type %s. The upgrade pack %s is missing this grouping.",
+            "update-stack", pack.getName()));
       }
     }
 
     List<UpgradeGroupEntity> groupEntities = new ArrayList<>();
-    RequestStageContainer req = createRequest(cluster, direction,
-        upgradeContext.getTargetRepositoryVersion().getStackId());
-
-    /**
+    RequestStageContainer req = createRequest(upgradeContext);
+
+    UpgradeEntity upgrade = new UpgradeEntity();
+    upgrade.setRepositoryVersion(upgradeContext.getRepositoryVersion());
+    upgrade.setClusterId(cluster.getClusterId());
+    upgrade.setDirection(direction);
+    upgrade.setUpgradePackage(pack.getName());
+    upgrade.setUpgradeType(pack.getType());
+    upgrade.setAutoSkipComponentFailures(upgradeContext.isComponentFailureAutoSkipped());
+    upgrade.setAutoSkipServiceCheckFailures(upgradeContext.isServiceCheckFailureAutoSkipped());
+    upgrade.setDowngradeAllowed(upgradeContext.isDowngradeAllowed());
+    upgrade.setOrchestration(upgradeContext.getOrchestrationType());
+
+    // create to/from history for this upgrade - this should be done before any
+    // possible changes to the desired version for components
+    addComponentHistoryToUpgrade(cluster, upgrade, upgradeContext);
+
+    /*
     During a Rolling Upgrade, change the desired Stack Id if jumping across
     major stack versions (e.g., HDP 2.2 -> 2.3), and then set config changes
     so they are applied on the newer stack.
@@ -847,59 +691,29 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     stopping all services), and the configs are applied immediately before starting the services.
     The Upgrade Pack is responsible for calling {@link org.apache.ambari.server.serveraction.upgrades.UpdateDesiredStackAction}
     at the appropriate moment during the orchestration.
-    **/
+    */
     if (pack.getType() == UpgradeType.ROLLING) {
-      // Desired configs must be set before creating stages because the config tag
-      // names are read and set on the command for filling in later
-      applyStackAndProcessConfigurations(upgradeContext);
+      s_upgradeHelper.updateDesiredRepositoriesAndConfigs(upgradeContext);
     }
 
+    @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES, comment = "This is wrong")
+    StackId configurationPackSourceStackId = upgradeContext.getSourceVersions().values().iterator().next().getStackId();
+
     // resolve or build a proper config upgrade pack - always start out with the config pack
     // for the current stack and merge into that
     //
     // HDP 2.2 to 2.3 should start with the config-upgrade.xml from HDP 2.2
     // HDP 2.2 to 2.4 should start with HDP 2.2 and merge in HDP 2.3's config-upgrade.xml
     ConfigUpgradePack configUpgradePack = ConfigurationPackBuilder.build(pack,
-        upgradeContext.getOriginalStackId());
-
-    // TODO: for now, all service components are transitioned to upgrading state
-    // TODO: When performing patch upgrade, we should only target supported services/components
-    // from upgrade pack
-    @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
-    Set<Service> services = new HashSet<>(cluster.getServices().values());
-    Map<Service, Set<ServiceComponent>> targetComponents = new HashMap<>();
-    for (Service service: services) {
-      Set<ServiceComponent> serviceComponents =
-        new HashSet<>(service.getServiceComponents().values());
-      targetComponents.put(service, serviceComponents);
-    }
-
-    // !!! determine which stack to check for component isAdvertised
-    StackId componentStack = upgradeContext.getTargetStackId();
-
-    s_upgradeHelper.putComponentsToUpgradingState(repositoryVersion.getStackId(),
-        repositoryVersion.getVersion(), targetComponents, componentStack);
-
-    // keep track of which stack to use when building commands - an express
-    // upgrade switches the stack half way through while other types move it in
-    // the beginning
-    StackId effectiveStackId = upgradeContext.getTargetStackId();
-    if(upgradeContext.getType() == UpgradeType.NON_ROLLING ) {
-      effectiveStackId = upgradeContext.getSourceStackId();
-    }
+        configurationPackSourceStackId);
 
+    // create the upgrade and request
     for (UpgradeGroupHolder group : groups) {
-      boolean skippable = group.skippable;
-      boolean supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
-      boolean allowRetry = group.allowRetry;
-
-      if (upgradeContext.getType() == UpgradeType.NON_ROLLING
-          && UpdateStackGrouping.class.equals(group.groupClass)) {
-        effectiveStackId = upgradeContext.getTargetStackId();
-      }
-
       List<UpgradeItemEntity> itemEntities = new ArrayList<>();
+
       for (StageWrapper wrapper : group.items) {
+        RepositoryVersionEntity effectiveRepositoryVersion = upgradeContext.getRepositoryVersion();
+
         if (wrapper.getType() == StageWrapper.Type.SERVER_SIDE_ACTION) {
           // !!! each stage is guaranteed to be of one type. but because there
           // is a bug that prevents one stage with multiple tasks assigned for
@@ -919,9 +733,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
               itemEntities.add(itemEntity);
 
               injectVariables(configHelper, cluster, itemEntity);
-              makeServerSideStage(upgradeContext, req, effectiveStackId, itemEntity,
-                  (ServerSideActionTask) task, skippable, supportsAutoSkipOnFailure, allowRetry,
-                  pack, configUpgradePack);
+              makeServerSideStage(group, upgradeContext, effectiveRepositoryVersion, req,
+                  itemEntity, (ServerSideActionTask) task, configUpgradePack);
             }
           }
         } else {
@@ -934,8 +747,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
           injectVariables(configHelper, cluster, itemEntity);
 
           // upgrade items match a stage
-          createStage(upgradeContext, req, effectiveStackId, itemEntity, wrapper, skippable,
-              supportsAutoSkipOnFailure, allowRetry);
+          createStage(group, upgradeContext, effectiveRepositoryVersion, req, itemEntity, wrapper);
         }
       }
 
@@ -948,20 +760,11 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
       }
     }
 
-    UpgradeEntity entity = new UpgradeEntity();
-    entity.setFromRepositoryVersion(upgradeContext.getSourceRepositoryVersion());
-    entity.setToRepositoryVersion(upgradeContext.getTargetRepositoryVersion());
-    entity.setUpgradeGroups(groupEntities);
-    entity.setClusterId(cluster.getClusterId());
-    entity.setDirection(direction);
-    entity.setUpgradePackage(pack.getName());
-    entity.setUpgradeType(pack.getType());
-    entity.setAutoSkipComponentFailures(skipComponentFailures);
-    entity.setAutoSkipServiceCheckFailures(skipServiceCheckFailures);
-    entity.setDowngradeAllowed(pack.isDowngradeAllowed());
+    // set all of the groups we just created
+    upgrade.setUpgradeGroups(groupEntities);
 
     req.getRequestStatusResponse();
-    return createUpgradeInsideTransaction(cluster, req, entity);
+    return createUpgradeInsideTransaction(cluster, req, upgrade);
   }
 
   /**
@@ -998,269 +801,19 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     return upgradeEntity;
   }
 
-  /**
-   * Handles the creation or resetting of configurations based on whether an
-   * upgrade or downgrade is occurring. This method will not do anything when
-   * the target stack version is the same as the cluster's current stack version
-   * since, by definition, no new configurations are automatically created when
-   * upgrading with the same stack (ie HDP 2.2.0.0 -> HDP 2.2.1.0).
-   * <p/>
-   * When upgrading or downgrade between stacks (HDP 2.2.0.0 -> HDP 2.3.0.0)
-   * then this will perform the following:
-   * <ul>
-   * <li>Upgrade: Create new configurations that are a merge between the current
-   * stack and the desired stack. If a value has changed between stacks, then
-   * the target stack value should be taken unless the cluster's value differs
-   * from the old stack. This can occur if a property has been customized after
-   * installation.</li>
-   * <li>Downgrade: Reset the latest configurations from the cluster's original
-   * stack. The new configurations that were created on upgrade must be left
-   * intact until all components have been reverted, otherwise heartbeats will
-   * fail due to missing configurations.</li>
-   * </ul>
-   *
-   *
-   * @param context
-   *          the upgrade context (not {@code null}).
-   * @throws AmbariException
-   */
-  public void applyStackAndProcessConfigurations(UpgradeContext context) throws AmbariException {
-    Cluster cluster = context.getCluster();
-    Direction direction = context.getDirection();
-    UpgradePack upgradePack = context.getUpgradePack();
-    RepositoryVersionEntity targetRve = context.getTargetRepositoryVersion();
-    String userName = getManagementController().getAuthName();
-
-    // if the current and target stacks are the same (ie HDP 2.2.0.0 -> 2.2.1.0)
-    // then we should never do anything with configs on either upgrade or
-    // downgrade; however if we are going across stacks, we have to do the stack
-    // checks differently depending on whether this is an upgrade or downgrade
-    StackEntity targetStack = targetRve.getStack();
-    StackId currentStackId = cluster.getCurrentStackVersion();
-    StackId desiredStackId = cluster.getDesiredStackVersion();
-    StackId targetStackId = new StackId(targetStack);
-    // Only change configs if moving to a different stack.
-    switch (direction) {
-      case UPGRADE:
-        if (currentStackId.equals(targetStackId)) {
-          return;
-        }
-        break;
-      case DOWNGRADE:
-        if (desiredStackId.equals(targetStackId)) {
-          return;
-        }
-        break;
-    }
-
-    Map<String, Map<String, String>> newConfigurationsByType = null;
-    ConfigHelper configHelper = getManagementController().getConfigHelper();
-
-    if (direction == Direction.UPGRADE) {
-      // populate a map of default configurations for the old stack (this is
-      // used when determining if a property has been customized and should be
-      // overriden with the new stack value)
-      Map<String, Map<String, String>> oldStackDefaultConfigurationsByType = configHelper.getDefaultProperties(
-          currentStackId, cluster);
-
-      // populate a map with default configurations from the new stack
-      newConfigurationsByType = configHelper.getDefaultProperties(targetStackId, cluster);
-
-      // We want to skip updating config-types of services that are not in the upgrade pack.
-      // Care should be taken as some config-types could be in services that are in and out
-      // of the upgrade pack. We should never ignore config-types of services in upgrade pack.
-      Set<String> skipConfigTypes = new HashSet<>();
-      Set<String> upgradePackServices = new HashSet<>();
-      Set<String> upgradePackConfigTypes = new HashSet<>();
-      AmbariMetaInfo ambariMetaInfo = s_metaProvider.get();
-
-      // ensure that we get the service info from the target stack
-      // (since it could include new configuration types for a service)
-      Map<String, ServiceInfo> stackServicesMap = ambariMetaInfo.getServices(
-          targetStack.getStackName(), targetStack.getStackVersion());
-
-      for (Grouping group : upgradePack.getGroups(direction)) {
-        for (UpgradePack.OrderService service : group.services) {
-          if (service.serviceName == null || upgradePackServices.contains(service.serviceName)) {
-            // No need to re-process service that has already been looked at
-            continue;
-          }
-
-          upgradePackServices.add(service.serviceName);
-          ServiceInfo serviceInfo = stackServicesMap.get(service.serviceName);
-          if (serviceInfo == null) {
-            continue;
-          }
-
-          // add every configuration type for all services defined in the
-          // upgrade pack
-          Set<String> serviceConfigTypes = serviceInfo.getConfigTypeAttributes().keySet();
-          for (String serviceConfigType : serviceConfigTypes) {
-            if (!upgradePackConfigTypes.contains(serviceConfigType)) {
-              upgradePackConfigTypes.add(serviceConfigType);
-            }
-          }
-        }
-      }
-
-      // build a set of configurations that should not be merged since their
-      // services are not installed
-      Set<String> servicesNotInUpgradePack = new HashSet<>(stackServicesMap.keySet());
-      servicesNotInUpgradePack.removeAll(upgradePackServices);
-      for (String serviceNotInUpgradePack : servicesNotInUpgradePack) {
-        ServiceInfo serviceInfo = stackServicesMap.get(serviceNotInUpgradePack);
-        Set<String> configTypesOfServiceNotInUpgradePack = serviceInfo.getConfigTypeAttributes().keySet();
-        for (String configType : configTypesOfServiceNotInUpgradePack) {
-          if (!upgradePackConfigTypes.contains(configType) && !skipConfigTypes.contains(configType)) {
-            skipConfigTypes.add(configType);
-          }
-        }
-      }
-
-      // remove any configurations from the target stack that are not used
-      // because the services are not installed
-      Iterator<String> iterator = newConfigurationsByType.keySet().iterator();
-      while (iterator.hasNext()) {
-        String configType = iterator.next();
-        if (skipConfigTypes.contains(configType)) {
-          LOG.info("Stack Upgrade: Removing configs for config-type {}", configType);
-          iterator.remove();
-        }
-      }
-
-      // now that the map has been populated with the default configurations
-      // from the stack/service, overlay the existing configurations on top
-      Map<String, DesiredConfig> existingDesiredConfigurationsByType = cluster.getDesiredConfigs();
-      for (Map.Entry<String, DesiredConfig> existingEntry : existingDesiredConfigurationsByType.entrySet()) {
-        String configurationType = existingEntry.getKey();
-        if(skipConfigTypes.contains(configurationType)) {
-          LOG.info("Stack Upgrade: Skipping config-type {} as upgrade-pack contains no updates to its service", configurationType);
-          continue;
-        }
-
-        // NPE sanity, although shouldn't even happen since we are iterating
-        // over the desired configs to start with
-        Config currentClusterConfig = cluster.getDesiredConfigByType(configurationType);
-        if (null == currentClusterConfig) {
-          continue;
-        }
-
-        // get current stack default configurations on install
-        Map<String, String> configurationTypeDefaultConfigurations = oldStackDefaultConfigurationsByType.get(
-            configurationType);
-
-        // NPE sanity for current stack defaults
-        if (null == configurationTypeDefaultConfigurations) {
-          configurationTypeDefaultConfigurations = Collections.emptyMap();
-        }
-
-        // get the existing configurations
-        Map<String, String> existingConfigurations = currentClusterConfig.getProperties();
-
-        // if the new stack configurations don't have the type, then simply add
-        // all of the existing in
-        Map<String, String> newDefaultConfigurations = newConfigurationsByType.get(
-            configurationType);
-
-        if (null == newDefaultConfigurations) {
-          newConfigurationsByType.put(configurationType, existingConfigurations);
-          continue;
-        } else {
-          // TODO, should we remove existing configs whose value is NULL even though they don't have a value in the new stack?
-
-          // Remove any configs in the new stack whose value is NULL, unless they currently exist and the value is not NULL.
-          Iterator<Map.Entry<String, String>> iter = newDefaultConfigurations.entrySet().iterator();
-          while (iter.hasNext()) {
-            Map.Entry<String, String> entry = iter.next();
-            if (entry.getValue() == null) {
-              iter.remove();
-            }
-          }
-        }
-
-        // for every existing configuration, see if an entry exists; if it does
-        // not exist, then put it in the map, otherwise we'll have to compare
-        // the existing value to the original stack value to see if its been
-        // customized
-        for (Map.Entry<String, String> existingConfigurationEntry : existingConfigurations.entrySet()) {
-          String existingConfigurationKey = existingConfigurationEntry.getKey();
-          String existingConfigurationValue = existingConfigurationEntry.getValue();
-
-          // if there is already an entry, we now have to try to determine if
-          // the value was customized after stack installation
-          if (newDefaultConfigurations.containsKey(existingConfigurationKey)) {
-            String newDefaultConfigurationValue = newDefaultConfigurations.get(
-                existingConfigurationKey);
-
-            if (!StringUtils.equals(existingConfigurationValue, newDefaultConfigurationValue)) {
-              // the new default is different from the existing cluster value;
-              // only override the default value if the existing value differs
-              // from the original stack
-              String oldDefaultValue = configurationTypeDefaultConfigurations.get(
-                  existingConfigurationKey);
-
-              if (!StringUtils.equals(existingConfigurationValue, oldDefaultValue)) {
-                // at this point, we've determined that there is a difference
-                // between default values between stacks, but the value was
-                // also customized, so keep the customized value
-                newDefaultConfigurations.put(existingConfigurationKey, existingConfigurationValue);
-              }
-            }
-          } else {
-            // there is no entry in the map, so add the existing key/value pair
-            newDefaultConfigurations.put(existingConfigurationKey, existingConfigurationValue);
-          }
-        }
-
-        /*
-        for every new configuration which does not exist in the existing
-        configurations, see if it was present in the current stack
-
-        stack 2.x has foo-site/property (on-ambari-upgrade is false)
-        stack 2.y has foo-site/property
-        the current cluster (on 2.x) does not have it
-
-        In this case, we should NOT add it back as clearly stack advisor has removed it
-        */
-        Iterator<Map.Entry<String, String>> newDefaultConfigurationsIterator = newDefaultConfigurations.entrySet().iterator();
-        while( newDefaultConfigurationsIterator.hasNext() ){
-          Map.Entry<String, String> newConfigurationEntry = newDefaultConfigurationsIterator.next();
-          String newConfigurationPropertyName = newConfigurationEntry.getKey();
-          if (configurationTypeDefaultConfigurations.containsKey(newConfigurationPropertyName)
-              && !existingConfigurations.containsKey(newConfigurationPropertyName)) {
-            LOG.info(
-                "The property {}/{} exists in both {} and {} but is not part of the current set of configurations and will therefore not be included in the configuration merge",
-                configurationType, newConfigurationPropertyName, currentStackId, targetStackId);
-
-            // remove the property so it doesn't get merged in
-            newDefaultConfigurationsIterator.remove();
-          }
-        }
-      }
-    } else {
-      // downgrade
-      cluster.applyLatestConfigurations(cluster.getCurrentStackVersion());
-    }
-
-    // !!! update the stack
-    cluster.setDesiredStackVersion(
-        new StackId(targetStack.getStackName(), targetStack.getStackVersion()), true);
-
-    // !!! configs must be created after setting the stack version
-    if (null != newConfigurationsByType) {
-      configHelper.createConfigTypes(cluster, getManagementController(), newConfigurationsByType,
-          userName, "Configuration created for Upgrade");
-    }
-  }
-
-  private RequestStageContainer createRequest(Cluster cluster, Direction direction, StackId stackId)
-      throws AmbariException {
+  private RequestStageContainer createRequest(UpgradeContext upgradeContext) throws AmbariException {
     ActionManager actionManager = getManagementController().getActionManager();
 
     RequestStageContainer requestStages = new RequestStageContainer(
         actionManager.getNextRequestId(), null, s_requestFactory.get(), actionManager);
-    requestStages.setRequestContext(String.format("%s to %s", direction.getVerb(true), stackId));
 
+    Direction direction = upgradeContext.getDirection();
+    RepositoryVersionEntity repositoryVersion = upgradeContext.getRepositoryVersion();
+
+    requestStages.setRequestContext(String.format("%s %s %s", direction.getVerb(true),
+        direction.getPreposition(), repositoryVersion.getVersion()));
+
+    Cluster cluster = upgradeContext.getCluster();
     Map<String, Set<String>> clusterHostInfo = StageUtils.getClusterHostInfo(cluster);
     String clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo);
     requestStages.setClusterHostInfo(clusterHostInfoJson);
@@ -1268,50 +821,30 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     return requestStages;
   }
 
-  /**
-   * Builds a stage's commands.
-   *
-   * @param context
-   *          the upgrade context (not {@code null}).
-   * @param request
-   *          the request to add the new stage to (not {@code null}).
-   * @param effectiveStackId
-   *          the stack ID to use when building the command. This will determine
-   *          things like stack tools and version information added to the
-   *          command (not {@code null}).
-   * @param entity
-   *          the upgrade entity to add the new items to (not {@code null}).
-   * @param wrapper
-   *          the encapsulation of a stage (not {@code null}).
-   * @param skippable
-   *          {@code true} if the stage is skippable.
-   * @param supportsAutoSkipOnFailure
-   *          {@code true} if a failure will skip the stage automatically.
-   * @param allowRetry
-   *          {@code true} if the stage can be retried on failure.
-   * @throws AmbariException
-   */
-  private void createStage(UpgradeContext context, RequestStageContainer request,
-      StackId effectiveStackId, UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
-      boolean supportsAutoSkipOnFailure, boolean allowRetry) throws AmbariException {
+  private void createStage(UpgradeGroupHolder group, UpgradeContext context,
+      RepositoryVersionEntity effectiveRepositoryVersion,
+      RequestStageContainer request, UpgradeItemEntity entity, StageWrapper wrapper)
+          throws AmbariException {
+
+    boolean skippable = group.skippable;
+    boolean supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
+    boolean allowRetry = group.allowRetry;
 
     switch (wrapper.getType()) {
       case CONFIGURE:
       case START:
       case STOP:
       case RESTART:
-        makeCommandStage(context, request, effectiveStackId, entity, wrapper, skippable,
-            supportsAutoSkipOnFailure,
-            allowRetry);
+        makeCommandStage(context, request, effectiveRepositoryVersion, entity, wrapper, skippable,
+            supportsAutoSkipOnFailure, allowRetry);
         break;
-      case RU_TASKS:
-        makeActionStage(context, request, effectiveStackId, entity, wrapper, skippable,
-            supportsAutoSkipOnFailure,
-            allowRetry);
+      case UPGRADE_TASKS:
+        makeActionStage(context, request, effectiveRepositoryVersion, entity, wrapper, skippable,
+            supportsAutoSkipOnFailure, allowRetry);
         break;
       case SERVICE_CHECK:
-        makeServiceCheckStage(context, request, effectiveStackId, entity, wrapper, skippable,
-            supportsAutoSkipOnFailure, allowRetry);
+        makeServiceCheckStage(context, request, effectiveRepositoryVersion, entity, wrapper,
+            skippable, supportsAutoSkipOnFailure, allowRetry);
         break;
       default:
         break;
@@ -1333,35 +866,10 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     }
   }
 
-  /**
-   * Creates an action stage using the {@link #EXECUTE_TASK_ROLE} custom action
-   * to execute some Python command.
-   *
-   * @param context
-   *          the upgrade context.
-   * @param request
-   *          the request object to add the stage to.
-   * @param effectiveStackId
-   *          the stack ID to use when generating content for the command. On
-   *          some upgrade types, this may change during the course of the
-   *          upgrade orchestration. An express upgrade changes this after
-   *          stopping all services.
-   * @param entity
-   *          the upgrade entity to set the stage information on
-   * @param wrapper
-   *          the stage wrapper containing information to generate the stage.
-   * @param skippable
-   *          {@code true} to mark the stage as being skippable if a failure
-   *          occurs.
-   * @param supportsAutoSkipOnFailure
-   *          {@code true} to automatically skip on a failure.
-   * @param allowRetry
-   *          {@code true} to be able to retry the failed stage.
-   * @throws AmbariException
-   */
   private void makeActionStage(UpgradeContext context, RequestStageContainer request,
-      StackId effectiveStackId, UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
-      boolean supportsAutoSkipOnFailure, boolean allowRetry) throws AmbariException {
+      RepositoryVersionEntity effectiveRepositoryVersion, UpgradeItemEntity entity,
+      StageWrapper wrapper, boolean skippable, boolean supportsAutoSkipOnFailure,
+      boolean allowRetry) throws AmbariException {
 
     if (0 == wrapper.getHosts().size()) {
       throw new AmbariException(
@@ -1370,10 +878,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
     Cluster cluster = context.getCluster();
 
-    // add each host to this stage
-    RequestResourceFilter filter = new RequestResourceFilter("", "",
-        new ArrayList<>(wrapper.getHosts()));
-
     LOG.debug("Analyzing upgrade item {} with tasks: {}.", entity.getText(), entity.getTasks());
     Map<String, String> params = getNewParameterMap(request, context);
     params.put(UpgradeContext.COMMAND_PARAM_TASKS, entity.getTasks());
@@ -1381,30 +885,40 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     // Apply additional parameters to the command that come from the stage.
     applyAdditionalParameters(wrapper, params);
 
-    // the ru_execute_tasks invokes scripts - it needs information about where
-    // the scripts live and for that it should always use the target repository
-    // stack
-    if (CollectionUtils.isNotEmpty(wrapper.getTasks())
-        && wrapper.getTasks().get(0).getService() != null) {
+    // Because custom task may end up calling a script/function inside a
+    // service, it is necessary to set the
+    // service_package_folder and hooks_folder params.
+    AmbariMetaInfo ambariMetaInfo = s_metaProvider.get();
+    StackId stackId = effectiveRepositoryVersion.getStackId();
+
+    StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(),
+        stackId.getStackVersion());
 
-      AmbariMetaInfo ambariMetaInfo = s_metaProvider.get();
+    // if the service/component are specified, then make sure to grab them off
+    // of the wrapper so they can be stored on the command for use later
+    String serviceName = null;
+    String componentName = null;
 
-      StackInfo stackInfo = ambariMetaInfo.getStack(effectiveStackId.getStackName(),
-          effectiveStackId.getStackVersion());
+    if (wrapper.getTasks() != null && wrapper.getTasks().size() > 0
+        && wrapper.getTasks().get(0).getService() != null) {
+      TaskWrapper taskWrapper = wrapper.getTasks().get(0);
+      serviceName = taskWrapper.getService();
+      componentName = taskWrapper.getComponent();
 
-      String serviceName = wrapper.getTasks().get(0).getService();
-      ServiceInfo serviceInfo = ambariMetaInfo.getService(effectiveStackId.getStackName(),
-          effectiveStackId.getStackVersion(), serviceName);
+      ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
+          stackId.getStackVersion(), serviceName);
 
       params.put(SERVICE_PACKAGE_FOLDER, serviceInfo.getServicePackageFolder());
       params.put(HOOKS_FOLDER, stackInfo.getStackHooksFolder());
     }
 
+    // add each host to this stage
+    RequestResourceFilter filter = new RequestResourceFilter(serviceName, componentName,
+        new ArrayList<>(wrapper.getHosts()));
+
     ActionExecutionContext actionContext = new ActionExecutionContext(cluster.getClusterName(),
         EXECUTE_TASK_ROLE, Collections.singletonList(filter), params);
 
-    actionContext.setStackId(effectiveStackId);
-
     // hosts in maintenance mode are excluded from the upgrade
     actionContext.setMaintenanceModeHostExcluded(true);
 
@@ -1413,7 +927,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
-        cluster, effectiveStackId);
+        cluster, effectiveRepositoryVersion);
 
     Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari",
         cluster.getClusterName(), cluster.getClusterId(), entity.getText(), jsons.getCommandParamsForStage(),
@@ -1444,28 +958,18 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
   /**
    * Used to create a stage for restart, start, or stop.
-   *
-   * @param context
-   *          Upgrade Context
-   * @param request
-   *          Container for stage
-   * @param effectiveStackId
-   *          the stack ID to use when building the command. This will determine
-   *          things like stack tools and version information added to the
-   *          command (not {@code null}).
-   * @param entity
-   *          Upgrade Item
-   * @param wrapper
-   *          Stage
-   * @param skippable
-   *          Whether the item can be skipped
-   * @param allowRetry
-   *          Whether the item is allowed to be retried
+   * @param context Upgrade Context
+   * @param request Container for stage
+   * @param entity Upgrade Item
+   * @param wrapper Stage
+   * @param skippable Whether the item can be skipped
+   * @param allowRetry Whether the item is allowed to be retried
    * @throws AmbariException
    */
   private void makeCommandStage(UpgradeContext context, RequestStageContainer request,
-      StackId effectiveStackId, UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
-      boolean supportsAutoSkipOnFailure, boolean allowRetry) throws AmbariException {
+      RepositoryVersionEntity effectiveRepositoryVersion, UpgradeItemEntity entity,
+      StageWrapper wrapper, boolean skippable, boolean supportsAutoSkipOnFailure,
+      boolean allowRetry) throws AmbariException {
 
     Cluster cluster = context.getCluster();
 
@@ -1497,9 +1001,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
     ActionExecutionContext actionContext = new ActionExecutionContext(cluster.getClusterName(),
         function, filters, commandParams);
-
-    actionContext.setStackId(effectiveStackId);
-
     actionContext.setTimeout(wrapper.getMaxTimeout(s_configuration));
     actionContext.setRetryAllowed(allowRetry);
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
@@ -1508,7 +1009,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     actionContext.setMaintenanceModeHostExcluded(true);
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
-        cluster, effectiveStackId);
+        cluster, effectiveRepositoryVersion);
 
     Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari",
         cluster.getClusterName(), cluster.getClusterId(), entity.getText(), jsons.getCommandParamsForStage(),
@@ -1540,8 +1041,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   }
 
   private void makeServiceCheckStage(UpgradeContext context, RequestStageContainer request,
-      StackId effectiveStackId, UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
-      boolean supportsAutoSkipOnFailure, boolean allowRetry) throws AmbariException {
+      RepositoryVersionEntity effectiveRepositoryVersion, UpgradeItemEntity entity,
+      StageWrapper wrapper, boolean skippable, boolean supportsAutoSkipOnFailure,
+      boolean allowRetry) throws AmbariException {
 
     List<RequestResourceFilter> filters = new ArrayList<>();
 
@@ -1559,7 +1061,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     ActionExecutionContext actionContext = new ActionExecutionContext(cluster.getClusterName(),
         "SERVICE_CHECK", filters, commandParams);
 
-    actionContext.setStackId(effectiveStackId);
     actionContext.setTimeout(wrapper.getMaxTimeout(s_configuration));
     actionContext.setRetryAllowed(allowRetry);
     actionContext.setAutoSkipFailures(context.isServiceCheckFailureAutoSkipped());
@@ -1569,7 +1070,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     actionContext.setMaintenanceModeHostExcluded(true);
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
-        cluster, effectiveStackId);
+        cluster, effectiveRepositoryVersion);
 
     Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari",
         cluster.getClusterName(), cluster.getClusterId(), entity.getText(), jsons.getCommandParamsForStage(),
@@ -1594,35 +1095,22 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
   /**
    * Creates a stage consisting of server side actions
-   *
-   * @param context
-   *          upgrade context
-   * @param request
-   *          upgrade request
-   * @param effectiveStackId
-   *          the stack ID to use when building the command. This will determine
-   *          things like stack tools and version information added to the
-   *          command (not {@code null}).
-   * @param entity
-   *          a single of upgrade
-   * @param task
-   *          server-side task (if any)
-   * @param skippable
-   *          if user can skip stage on failure
-   * @param allowRetry
-   *          if user can retry running stage on failure
-   * @param configUpgradePack
-   *          a runtime-generated config upgrade pack that contains all config
-   *          change definitions from all stacks involved into upgrade
+   * @param context upgrade context
+   * @param request upgrade request
+   * @param entity a single of upgrade
+   * @param task server-side task (if any)
+   * @param configUpgradePack a runtime-generated config upgrade pack that
+   * contains all config change definitions from all stacks involved into
+   * upgrade
    * @throws AmbariException
    */
-  private void makeServerSideStage(UpgradeContext context, RequestStageContainer request,
-      StackId effectiveStackId, UpgradeItemEntity entity, ServerSideActionTask task,
-      boolean skippable, boolean supportsAutoSkipOnFailure, boolean allowRetry,
-      UpgradePack upgradePack, ConfigUpgradePack configUpgradePack)
-          throws AmbariException {
+  private void makeServerSideStage(UpgradeGroupHolder group, UpgradeContext context,
+      RepositoryVersionEntity effectiveRepositoryVersion, RequestStageContainer request,
+      UpgradeItemEntity entity, ServerSideActionTask task, ConfigUpgradePack configUpgradePack)
+      throws AmbariException {
 
     Cluster cluster = context.getCluster();
+    UpgradePack upgradePack = context.getUpgradePack();
 
     Map<String, String> commandParams = getNewParameterMap(request, context);
     commandParams.put(UpgradeContext.COMMAND_PARAM_UPGRADE_PACK, upgradePack.getName());
@@ -1702,23 +1190,22 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         Role.AMBARI_SERVER_ACTION.toString(), Collections.<RequestResourceFilter> emptyList(),
         commandParams);
 
-    actionContext.setStackId(effectiveStackId);
     actionContext.setTimeout(Short.valueOf((short) -1));
-    actionContext.setRetryAllowed(allowRetry);
+    actionContext.setRetryAllowed(group.allowRetry);
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
 
     // hosts in maintenance mode are excluded from the upgrade
     actionContext.setMaintenanceModeHostExcluded(true);
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
-        cluster, effectiveStackId);
+        cluster, context.getRepositoryVersion());
 
     Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari",
         cluster.getClusterName(), cluster.getClusterId(), stageText, jsons.getCommandParamsForStage(),
       jsons.getHostParamsForStage());
 
-    stage.setSkippable(skippable);
-    stage.setAutoSkipFailureSupported(supportsAutoSkipOnFailure);
+    stage.setSkippable(group.skippable);
+    stage.setAutoSkipFailureSupported(group.supportsAutoSkipOnFailure);
 
     long stageId = request.getLastStageId() + 1;
     if (0L == stageId) {
@@ -1732,7 +1219,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         getManagementController().getAuthName(), Role.AMBARI_SERVER_ACTION, RoleCommand.EXECUTE,
         cluster.getClusterName(),
         new ServiceComponentHostServerActionEvent(null, System.currentTimeMillis()), commandParams,
-        itemDetail, null, s_configuration.getDefaultServerTaskTimeout(), allowRetry,
+        itemDetail, null, s_configuration.getDefaultServerTaskTimeout(), group.allowRetry,
         context.isComponentFailureAutoSkipped());
 
     request.addStages(Collections.singletonList(stage));
@@ -1743,11 +1230,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
    * following properties are already set:
    * <ul>
    * <li>{@link UpgradeContext#COMMAND_PARAM_CLUSTER_NAME}
-   * <li>{@link UpgradeContext#COMMAND_PARAM_VERSION}
    * <li>{@link UpgradeContext#COMMAND_PARAM_DIRECTION}
-   * <li>{@link UpgradeContext#COMMAND_PARAM_ORIGINAL_STACK}
-   * <li>{@link UpgradeContext#COMMAND_PARAM_TARGET_STACK}
-   * <li>{@link UpgradeContext#COMMAND_DOWNGRADE_FROM_VERSION}
    * <li>{@link UpgradeContext#COMMAND_PARAM_UPGRADE_TYPE}
    * <li>{@link KeyNames#REFRESH_CONFIG_TAGS_BEFORE_EXECUTION} - necessary in
    * order to have the commands contain the correct configurations. Otherwise,
@@ -1755,7 +1238,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
    * command was created. For upgrades, this is problematic since the commands
    * are all created ahead of time, but the upgrade may change configs as part
    * of the upgrade pack.</li>
-   * <li>{@link #COMMAND_PARAM_REQUEST_ID}</li> the ID of the request.
+   * <li>{@link UpgradeContext#COMMAND_PARAM_REQUEST_ID}</li> the ID of the request.
    * <ul>
    *
    * @return the initialized parameter map.
@@ -1858,54 +1341,47 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   }
 
   /**
-   * Builds the list of {@link HostOrderItem}s from the upgrade request. If the
-   * upgrade request does not contain the hosts
+   * Creates the {@link UpgradeHistoryEntity} instances for this upgrade for
+   * every component participating.
    *
-   * @param requestMap
-   *          the map of properties from the request (not {@code null}).
-   * @return the ordered list of actions to orchestrate for the
-   *         {@link UpgradeType#HOST_ORDERED} upgrade.
-   * @throws AmbariException
-   *           if the request properties are not valid.
+   * @param cluster
+   *          the cluster (not {@code null}).
+   * @param upgrade
+   *          the upgrade to add the entities to (not {@code null}).
+   * @param upgradeContext
+   *          the upgrade context for this upgrade (not {@code null}).
    */
-  @SuppressWarnings("unchecked")
-  private List<HostOrderItem> extractHostOrderItemsFromRequest(Map<String, Object> requestMap)
-      throws AmbariException {
-    // ewwww
-    Set<Map<String, List<String>>> hostsOrder = (Set<Map<String, List<String>>>) requestMap.get(
-        UPGRADE_HOST_ORDERED_HOSTS);
-
-    if (CollectionUtils.isEmpty(hostsOrder)) {
-      throw new AmbariException(
-          String.format("The %s property must be specified when using a %s upgrade type.",
-              UPGRADE_HOST_ORDERED_HOSTS, UpgradeType.HOST_ORDERED));
-    }
-
-    List<HostOrderItem> hostOrderItems = new ArrayList<>();
-
-    // extract all of the hosts so that we can ensure they are all accounted for
-    Iterator<Map<String, List<String>>> iterator = hostsOrder.iterator();
-    while (iterator.hasNext()) {
-      Map<String, List<String>> grouping = iterator.next();
-      List<String> hosts = grouping.get("hosts");
-      List<String> serviceChecks = grouping.get("service_checks");
-
-      if (CollectionUtils.isEmpty(hosts) && CollectionUtils.isEmpty(serviceChecks)) {
-        throw new AmbariException(String.format(
-            "The %s property must contain at least one object with either a %s or %s key",
-            UPGRADE_HOST_ORDERED_HOSTS, "hosts", "service_checks"));
-      }
+  private void addComponentHistoryToUpgrade(Cluster cluster, UpgradeEntity upgrade,
+      UpgradeContext upgradeContext) throws AmbariException {
+    Set<String> services = upgradeContext.getSupportedServices();
+    for (String serviceName : services) {
+      Service service = cluster.getService(serviceName);
+      Map<String, ServiceComponent> componentMap = service.getServiceComponents();
+      for (ServiceComponent component : componentMap.values()) {
+        UpgradeHistoryEntity history = new UpgradeHistoryEntity();
+        history.setUpgrade(upgrade);
+        history.setServiceName(serviceName);
+        history.setComponentName(component.getName());
+
+        // depending on whether this is an upgrade or a downgrade, the history
+        // will be different
+        if (upgradeContext.getDirection() == Direction.UPGRADE || upgradeContext.isPatchRevert()) {
+          history.setFromRepositoryVersion(component.getDesiredRepositoryVersion());
+          history.setTargetRepositoryVersion(upgradeContext.getRepositoryVersion());
+        } else {
+          // the target version on a downgrade is the original version that the
+          // service was on in the failed upgrade
+          RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion(
+              serviceName);
 
-      if (CollectionUtils.isNotEmpty(hosts)) {
-        hostOrderItems.add(new HostOrderItem(HostOrderActionType.HOST_UPGRADE, hosts));
-      }
+          history.setFromRepositoryVersion(upgradeContext.getRepositoryVersion());
+          history.setTargetRepositoryVersion(targetRepositoryVersion);
+        }
 
-      if (CollectionUtils.isNotEmpty(serviceChecks)) {
-        hostOrderItems.add(new HostOrderItem(HostOrderActionType.SERVICE_CHECK, serviceChecks));
+        // add the history
+        upgrade.addHistory(history);
       }
     }
-
-    return hostOrderItems;
   }
 
   /**
@@ -1967,269 +1443,31 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   }
 
   /**
-   * Builds a chain of {@link UpgradeRequestValidator}s to ensure that the
-   * incoming request to create a new upgrade is valid.
-   *
-   * @param upgradeType
-   *          the type of upgrade to build the validator for.
-   * @return the validator which can check to ensure that the properties are
-   *         valid.
+   * The {@link RepositoryVersions} class is used to represent to/from versions
+   * of a service during an upgrade or downgrade.
    */
-  private UpgradeRequestValidator buildValidator(UpgradeType upgradeType){
-    UpgradeRequestValidator validator = new BasicUpgradePropertiesValidator();
-    UpgradeRequestValidator preReqValidator = new PreReqCheckValidator();
-    validator.setNextValidator(preReqValidator);
-
-    final UpgradeRequestValidator upgradeTypeValidator;
-    switch( upgradeType ){
-      case HOST_ORDERED:
-        upgradeTypeValidator = new HostOrderedUpgradeValidator();
-        break;
-      case NON_ROLLING:
-      case ROLLING:
-      default:
-        upgradeTypeValidator = null;
-        break;
-    }
+  final static class RepositoryVersions {
+    @JsonProperty("from_repository_id")
+    final long fromRepositoryId;
 
-    preReqValidator.setNextValidator(upgradeTypeValidator);
-    return validator;
-  }
+    @JsonProperty("from_repository_version")
+    final String fromRepositoryVersion;
 
-  /**
-   * The {@link UpgradeRequestValidator} contains the logic to check for correct
-   * upgrade request properties and then pass the responsibility onto the next
-   * validator in the chain.
-   */
-  private abstract class UpgradeRequestValidator {
-    /**
-     * The next validator.
-     */
-    UpgradeRequestValidator m_nextValidator;
+    @JsonProperty("to_repository_id")
+    final long toRepositoryId;
 
-    /**
-     * Sets the next validator in the chain.
-     *
-     * @param nextValidator
-     *          the next validator to run, or {@code null} for none.
-     */
-    void setNextValidator(UpgradeRequestValidator nextValidator) {
-      m_nextValidator = nextValidator;
-    }
-
-    /**
-     * Validates the upgrade request from this point in the chain.
-     *
-     * @param upgradeContext
-     * @param upgradePack
-     * @throws AmbariException
-     */
-    final void validate(UpgradeContext upgradeContext, UpgradePack upgradePack)
-        throws AmbariException {
-
-      // run this instance's check
-      check(upgradeContext, upgradePack);
-
-      // pass along to the next
-      if( null != m_nextValidator ) {
-        m_nextValidator.validate(upgradeContext, upgradePack);
-      }
-    }
-
-    /**
-     * Checks to ensure that upgrade request is valid given the specific
-     * arguments.
-     *
-     * @param upgradeContext
-     * @param upgradePack
-     *
-     * @throws AmbariException
-     */
-    abstract void check(UpgradeContext upgradeContext, UpgradePack upgradePack)
-        throws AmbariException;
-  }
-
-  /**
-   * The {@link BasicUpgradePropertiesValidator} ensures that the basic required
-   * properties are present on the upgrade request.
-   */
-  private final class BasicUpgradePropertiesValidator extends UpgradeRequestValidator {
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void check(UpgradeContext upgradeContext, UpgradePack upgradePack)
-        throws AmbariException {
-      Map<String, Object> requestMap = upgradeContext.getUpgradeRequest();
-
-      String clusterName = (String) requestMap.get(UPGRADE_CLUSTER_NAME);
-      String versionId = (String) requestMap.get(UPGRADE_REPO_ID);
-      String version = (String) requestMap.get(UPGRADE_REPO_VERSION);
-      String direction = (String) requestMap.get(UPGRADE_DIRECTION);
-
-      if (StringUtils.isBlank(clusterName)) {
-        throw new AmbariException(String.format("%s is required", UPGRADE_CLUSTER_NAME));
-      }
-
-      if (StringUtils.isBlank(versionId) && StringUtils.isBlank(version)) {
-        throw new AmbariException(
-            String.format("Either %s or %s is required", UPGRADE_REPO_ID, UPGRADE_REPO_VERSION));
-      }
-
-      if (StringUtils.isBlank(direction)) {
-        throw new AmbariException(String.format("%s is required", UPGRADE_DIRECTION));
-      }
-    }
-  }
-
-  /**
-   * The {@link PreReqCheckValidator} ensures that the upgrade pre-requisite
-   * checks have passed.
-   */
-  private final class PreReqCheckValidator extends UpgradeRequestValidator {
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    void check(UpgradeContext upgradeContext, UpgradePack upgradePack) throws AmbariException {
-      Cluster cluster = upgradeContext.getCluster();
-      Direction direction = upgradeContext.getDirection();
-      Map<String, Object> requestMap = upgradeContext.getUpgradeRequest();
-      UpgradeType upgradeType = upgradeContext.getType();
-
-      String version = (String) requestMap.get(UPGRADE_REPO_VERSION);
-      boolean skipPrereqChecks = Boolean.parseBoolean((String) requestMap.get(UPGRADE_SKIP_PREREQUISITE_CHECKS));
-      boolean failOnCheckWarnings = Boolean.parseBoolean((String) requestMap.get(UPGRADE_FAIL_ON_CHECK_WARNINGS));
-      String preferredUpgradePack = requestMap.containsKey(UPGRADE_PACK) ? (String) requestMap.get(UPGRADE_PACK) : null;
-
-      // verify that there is not an upgrade or downgrade that is in progress or suspended
-      UpgradeEntity existingUpgrade = cluster.getUpgradeInProgress();
-      if( null != existingUpgrade ){
-        throw new AmbariException(
-            String.format("Unable to perform %s as another %s (request ID %s) is in progress.",
-                direction.getText(false), existingUpgrade.getDirection().getText(false),
-                existingUpgrade.getRequestId()));
-      }
-
-      // skip this check if it's a downgrade or we are instructed to skip it
-      if( direction.isDowngrade() || skipPrereqChecks ){
-        return;
-      }
-
-      // Validate pre-req checks pass
-      PreUpgradeCheckResourceProvider preUpgradeCheckResourceProvider = (PreUpgradeCheckResourceProvider)
-          getResourceProvider(Resource.Type.PreUpgradeCheck);
-
-      Predicate preUpgradeCheckPredicate = new PredicateBuilder().property(
-          PreUpgradeCheckResourceProvider.UPGRADE_CHECK_CLUSTER_NAME_PROPERTY_ID).equals(cluster.getClusterName()).and().property(
-          PreUpgradeCheckResourceProvider.UPGRADE_CHECK_REPOSITORY_VERSION_PROPERTY_ID).equals(version).and().property(
-          PreUpgradeCheckResourceProvider.UPGRADE_CHECK_UPGRADE_TYPE_PROPERTY_ID).equals(upgradeType).and().property(
-          PreUpgradeCheckResourceProvider.UPGRADE_CHECK_UPGRADE_PACK_PROPERTY_ID).equals(preferredUpgradePack).toPredicate();
-
-      Request preUpgradeCheckRequest = PropertyHelper.getReadRequest();
-
-      Set<Resource> preUpgradeCheckResources;
-      try {
-        preUpgradeCheckResources = preUpgradeCheckResourceProvider.getResources(
-            preUpgradeCheckRequest, preUpgradeCheckPredicate);
-      } catch (NoSuchResourceException|SystemException|UnsupportedPropertyException|NoSuchParentResourceException e) {
-        throw new AmbariException(
-            String.format("Unable to perform %s. Prerequisite checks could not be run",
-                direction.getText(false), e));
-      }
-
-      List<Resource> failedResources = new LinkedList<>();
-      if (preUpgradeCheckResources != null) {
-        for (Resource res : preUpgradeCheckResources) {
-          PrereqCheckStatus prereqCheckStatus = (PrereqCheckStatus) res.getPropertyValue(
-              PreUpgradeCheckResourceProvider.UPGRADE_CHECK_STATUS_PROPERTY_ID);
-
-          if (prereqCheckStatus == PrereqCheckStatus.FAIL
-              || (failOnCheckWarnings && prereqCheckStatus == PrereqCheckStatus.WARNING)) {
-            failedResources.add(res);
-          }
-        }
-      }
-
-      if (!failedResources.isEmpty()) {
-        throw new AmbariException(
-            String.format("Unable to perform %s. Prerequisite checks failed %s",
-                direction.getText(false), s_gson.toJson(failedResources)));
-      }
-    }
-  }
-
-  /**
-   * Ensures that for {@link UpgradeType#HOST_ORDERED}, the properties supplied
-   * are valid.
-   */
-  @SuppressWarnings("unchecked")
-  private final class HostOrderedUpgradeValidator extends UpgradeRequestValidator {
+    @JsonProperty("to_repository_version")
+    final String toRepositoryVersion;
 
     /**
-     * {@inheritDoc}
+     * Constructor.
      */
-    @Override
-    void check(UpgradeContext upgradeContext, UpgradePack upgradePack) throws AmbariException {
-      Cluster cluster = upgradeContext.getCluster();
-      Direction direction = upgradeContext.getDirection();
-      Map<String, Object> requestMap = upgradeContext.getUpgradeRequest();
-
-      String skipFailuresRequestProperty = (String) requestMap.get(UPGRADE_SKIP_FAILURES);
-      if (Boolean.parseBoolean(skipFailuresRequestProperty)) {
-        throw new AmbariException(
-            String.format("The %s property is not valid when creating a %s upgrade.",
-                UPGRADE_SKIP_FAILURES, UpgradeType.HOST_ORDERED));
-      }
-
-      String skipManualVerification = (String) requestMap.get(UPGRADE_SKIP_MANUAL_VERIFICATION);
-      if (Boolean.parseBoolean(skipManualVerification)) {
-        throw new AmbariException(
-            String.format("The %s property is not valid when creating a %s upgrade.",
-                UPGRADE_SKIP_MANUAL_VERIFICATION, UpgradeType.HOST_ORDERED));
-      }
-
-      if (!requestMap.containsKey(UPGRADE_HOST_ORDERED_HOSTS)) {
-        throw new AmbariException(
-            String.format("The %s property is required when creating a %s upgrade.",
-                UPGRADE_HOST_ORDERED_HOSTS, UpgradeType.HOST_ORDERED));
-      }
-
-      List<HostOrderItem> hostOrderItems = extractHostOrderItemsFromRequest(requestMap);
-      List<String> hostsFromRequest = new ArrayList<>(hostOrderItems.size());
-      for (HostOrderItem hostOrderItem : hostOrderItems) {
-        if (hostOrderItem.getType() == HostOrderActionType.HOST_UPGRADE) {
-          hostsFromRequest.addAll(hostOrderItem.getActionItems());
-        }
-      }
-
-      // ensure that all hosts for this cluster are accounted for
-      Collection<Host> hosts = cluster.getHosts();
-      Set<String> clusterHostNames = new HashSet<>(hosts.size());
-      for (Host host : hosts) {
-        clusterHostNames.add(host.getHostName());
-      }
+    public RepositoryVersions(RepositoryVersionEntity from, RepositoryVersionEntity to) {
+      fromRepositoryId = from.getId();
+      fromRepositoryVersion = from.getVersion();
 
-      Collection<String> disjunction = CollectionUtils.disjunction(hostsFromRequest,
-          clusterHostNames);
-
-      if (CollectionUtils.isNotEmpty(disjunction)) {
-        throw new AmbariException(String.format(
-            "The supplied list of hosts must match the cluster hosts in an upgrade of type %s. The following hosts are either missing or invalid: %s",
-            UpgradeType.HOST_ORDERED, StringUtils.join(disjunction, ", ")));
-      }
-
-      // verify that the upgradepack has the required grouping and set the
-      // action items on it
-      HostOrderGrouping hostOrderGrouping = null;
-      List<Grouping> groupings = upgradePack.getGroups(direction);
-      for (Grouping grouping : groupings) {
-        if (grouping instanceof HostOrderGrouping) {
-          hostOrderGrouping = (HostOrderGrouping) grouping;
-          hostOrderGrouping.setHostOrderItems(hostOrderItems);
-        }
-      }
+      toRepositoryId = to.getId();
+      toRepositoryVersion = to.getVersion();
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/48f7fb22/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java
index 4ded10e..455d569 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/utilities/PropertyHelper.java
@@ -20,7 +20,6 @@ package org.apache.ambari.server.controller.utilities;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -31,13 +30,11 @@ import java.util.regex.Pattern;
 
 import org.apache.ambari.server.controller.internal.PropertyInfo;
 import org.apache.ambari.server.controller.internal.RequestImpl;
-import org.apache.ambari.server.controller.jmx.JMXPropertyProvider;
 import org.apache.ambari.server.controller.spi.PageRequest;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.SortRequest;
 import org.apache.ambari.server.controller.spi.TemporalInfo;
-import org.apache.ambari.server.state.stack.Metric;
 import org.apache.commons.lang.StringUtils;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.type.TypeReference;
@@ -52,7 +49,7 @@ public class PropertyHelper {
   private static final String SQLSERVER_PROPERTIES_FILE = "sqlserver_properties.json";
   private static final String JMX_PROPERTIES_FILE = "jmx_properties.json";
   private static final String KEY_PROPERTIES_FILE = "key_properties.json";
-  private static final char EXTERNAL_PATH_SEP = '/';
+  public static final char EXTERNAL_PATH_SEP = '/';
 
   /**
    * Aggregate functions implicitly supported by the Metrics Service
@@ -126,7 +123,7 @@ public class PropertyHelper {
    * @return the set of property ids
    */
   public static Set<String> getPropertyIds(Map<String, Map<String, PropertyInfo>> componentPropertyInfoMap ) {
-    Set<String> propertyIds = new HashSet<String>();
+    Set<String> propertyIds = new HashSet<>();
 
     for (Map.Entry<String, Map<String, PropertyInfo>> entry : componentPropertyInfoMap.entrySet()) {
       propertyIds.addAll(entry.getValue().keySet());
@@ -250,7 +247,7 @@ public class PropertyHelper {
    * @return the set of categories
    */
   public static Set<String> getCategories(Set<String> propertyIds) {
-    Set<String> categories = new HashSet<String>();
+    Set<String> categories = new HashSet<>();
     for (String property : propertyIds) {
       String category = PropertyHelper.getPropertyCategory(property);
       while (category != null) {
@@ -314,9 +311,9 @@ public class PropertyHelper {
     Set<String> ids = request.getPropertyIds();
 
     if (ids != null) {
-      ids = new HashSet<String>(ids);
+      ids = new HashSet<>(ids);
     } else {
-      ids = new HashSet<String>();
+      ids = new HashSet<>();
     }
 
     Set<Map<String, Object>> properties = request.getProperties();
@@ -336,7 +333,7 @@ public class PropertyHelper {
    * @return the map of properties for the given resource
    */
   public static Map<String, Object> getProperties(Resource resource) {
-    Map<String, Object> properties = new HashMap<String, Object>();
+    Map<String, Object> properties = new HashMap<>();
 
     Map<String, Map<String, Object>> categories = resource.getPropertiesMap();
 
@@ -416,7 +413,7 @@ public class PropertyHelper {
    * @param propertyIds  the property ids associated with the request; may be null
    */
   public static Request getReadRequest(String ... propertyIds) {
-    return PropertyHelper.getReadRequest(new HashSet<String>(
+    return PropertyHelper.getReadRequest(new HashSet<>(
         Arrays.asList(propertyIds)));
   }
 
@@ -441,13 +438,13 @@ public class PropertyHelper {
               new TypeReference<Map<Resource.InternalType, Map<String, Map<String, Metric>>>>() {});
 
       Map<Resource.InternalType, Map<String, Map<String, PropertyInfo>>> resourceMetrics =
-          new HashMap<Resource.InternalType, Map<String, Map<String, PropertyInfo>>>();
+          new HashMap<>();
 
       for (Map.Entry<Resource.InternalType, Map<String, Map<String, Metric>>> resourceEntry : resourceMetricMap.entrySet()) {
-        Map<String, Map<String, PropertyInfo>> componentMetrics = new HashMap<String, Map<String, PropertyInfo>>();
+        Map<String, Map<String, PropertyInfo>> componentMetrics = new HashMap<>();
 
         for (Map.Entry<String, Map<String, Metric>> componentEntry : resourceEntry.getValue().entrySet()) {
-          Map<String, PropertyInfo> metrics = new HashMap<String, PropertyInfo>();
+          Map<String, PropertyInfo> metrics = new HashMap<>();
 
           for (Map.Entry<String, Metric> metricEntry : componentEntry.getValue().entrySet()) {
             String property = metricEntry.getKey();
@@ -492,11 +489,11 @@ public class PropertyHelper {
               new TypeReference<Map<Resource.InternalType, Map<Resource.InternalType, String>>>() {});
 
       Map<Resource.InternalType, Map<Resource.Type, String>> returnMap =
-          new HashMap<Resource.InternalType, Map<Resource.Type, String>>();
+          new HashMap<>();
 
       // convert inner maps from InternalType to Type
       for (Map.Entry<Resource.InternalType, Map<Resource.InternalType, String>> entry : map.entrySet()) {
-        Map<Resource.Type, String> innerMap = new HashMap<Resource.Type, String>();
+        Map<Resource.Type, String> innerMap = new HashMap<>();
 
         for (Map.Entry<Resource.InternalType, String> entry1 : entry.getValue().entrySet()) {
           innerMap.put(Resource.Type.valueOf(entry1.getKey().name()), entry1.getValue());
@@ -596,7 +593,7 @@ public class PropertyHelper {
     for (Map.Entry<String, Map<String, PropertyInfo>> metricInfoEntry : metrics.entrySet()) {
       Map<String, PropertyInfo> metricInfo = metricInfoEntry.getValue();
 
-      Map<String, PropertyInfo> aggregateMetrics = new HashMap<String, PropertyInfo>();
+      Map<String, PropertyInfo> aggregateMetrics = new HashMap<>();
       // For every metric
       for (Map.Entry<String, PropertyInfo> metricEntry : metricInfo.entrySet()) {
         // For each aggregate function id


Mime
View raw message