This is an automated email from the ASF dual-hosted git repository.

ncole pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new ce9cdfa  [AMBARI-24728] Orchestration Should Save Upgrade Pack for 
source or target (#2417)
ce9cdfa is described below

commit ce9cdfa2845208cdc3c210318907b636cc99b15a
Author: ncole <[email protected]>
AuthorDate: Wed Oct 3 16:14:08 2018 -0400

    [AMBARI-24728] Orchestration Should Save Upgrade Pack for source or target 
(#2417)
---
 .../internal/UpgradeResourceProvider.java          |   1 +
 .../ambari/server/orm/entities/UpgradeEntity.java  |  19 ++
 .../ambari/server/stack/upgrade/UpgradePack.java   |  22 +++
 .../stack/upgrade/orchestrate/UpgradeContext.java  |  76 ++++---
 .../stack/upgrade/orchestrate/UpgradeHelper.java   | 114 ++++++++---
 .../org/apache/ambari/server/state/StackInfo.java  |   6 +
 .../ambari/server/upgrade/UpgradeCatalog280.java   |  16 +-
 .../src/main/resources/Ambari-DDL-Derby-CREATE.sql |   1 +
 .../src/main/resources/Ambari-DDL-MySQL-CREATE.sql |   1 +
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql    |   1 +
 .../main/resources/Ambari-DDL-Postgres-CREATE.sql  |   1 +
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql    |   1 +
 .../main/resources/Ambari-DDL-SQLServer-CREATE.sql |   1 +
 .../internal/UpgradeResourceProviderTest.java      |   1 +
 .../UpgradeSummaryResourceProviderTest.java        |   1 +
 .../ambari/server/orm/dao/UpgradeDAOTest.java      |  12 ++
 .../AbstractAuthenticationProviderTest.java        |   2 +-
 .../upgrades/ComponentVersionCheckActionTest.java  |   2 +
 .../serveraction/upgrades/ConfigureActionTest.java |   1 +
 .../upgrades/CreateAndConfigureActionTest.java     |   1 +
 .../serveraction/upgrades/UpgradeActionTest.java   |   2 +
 .../upgrade/orchestrate/UpgradeContextTest.java    |  69 ++++---
 .../upgrade/orchestrate/UpgradeHelperTest.java     |  19 ++
 .../services/RetryUpgradeActionServiceTest.java    |   1 +
 .../state/stack/ConfigUpgradeValidityTest.java     |   2 -
 .../server/upgrade/UpgradeCatalog280Test.java      |  11 +-
 .../stacks/HDP/2.2.0/upgrades/upgrade_from_211.xml | 220 +++++++++++++++++++++
 27 files changed, 511 insertions(+), 93 deletions(-)

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 9d1398f..3c5ee2c 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
@@ -760,6 +760,7 @@ public class UpgradeResourceProvider extends 
AbstractControllerResourceProvider
     upgrade.setClusterId(cluster.getClusterId());
     upgrade.setDirection(direction);
     upgrade.setUpgradePackage(pack.getName());
+    upgrade.setUpgradePackStackId(pack.getOwnerStackId());
     upgrade.setUpgradeType(pack.getType());
     
upgrade.setAutoSkipComponentFailures(upgradeContext.isComponentFailureAutoSkipped());
     
upgrade.setAutoSkipServiceCheckFailures(upgradeContext.isServiceCheckFailureAutoSkipped());
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 9342b46..21d7f84 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
@@ -43,6 +43,7 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.stack.upgrade.Direction;
 import org.apache.ambari.server.stack.upgrade.UpgradeType;
 import org.apache.ambari.server.state.RepositoryType;
+import org.apache.ambari.server.state.StackId;
 import org.apache.commons.lang.builder.EqualsBuilder;
 
 import com.google.common.base.Objects;
@@ -126,6 +127,9 @@ public class UpgradeEntity {
   @Column(name="upgrade_package", nullable = false)
   private String upgradePackage;
 
+  @Column(name="upgrade_package_stack", nullable = false)
+  private String upgradePackStack;
+
   @Column(name="upgrade_type", nullable = false)
   @Enumerated(value = EnumType.STRING)
   private UpgradeType upgradeType;
@@ -326,6 +330,21 @@ public class UpgradeEntity {
   }
 
   /**
+   * @return the stack that owns the upgrade pack
+   */
+  public StackId getUpgradePackStackId() {
+    return null == upgradePackStack ? null : new StackId(upgradePackStack);
+  }
+
+  /**
+   * @param stackId
+   *          the stack that owns the upgrade pack
+   */
+  public void setUpgradePackStackId(StackId stackId) {
+    upgradePackStack = stackId.toString();
+  }
+
+  /**
    * Gets whether skippable components that failed are automatically skipped.
    * They will be placed into the {@link HostRoleStatus#SKIPPED_FAILED} state.
    *
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/UpgradePack.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/UpgradePack.java
index 7f26bf0..44027cf 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/UpgradePack.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/UpgradePack.java
@@ -38,6 +38,7 @@ import javax.xml.bind.annotation.XmlValue;
 
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.stack.upgrade.Task.Type;
+import org.apache.ambari.server.state.StackId;
 import org.apache.commons.collections.CollectionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -130,6 +131,9 @@ public class UpgradePack {
   @XmlElement(name="intermediate-stack")
   private List<IntermediateStack> intermediateStacks;
 
+  @XmlTransient
+  private StackId ownerStackId;
+
   public String getName() {
     return name;
   }
@@ -803,4 +807,22 @@ public class UpgradePack {
       .map(executeStage -> executeStage.task)
       .anyMatch(taskPredicate);
   }
+
+  /**
+   * Sets the stack id that owns this upgrade pack.  This may be set only once.
+   *
+   * @param stackId
+   *          the owner stack id
+   */
+  public void setOwnerStackId(StackId stackId) {
+    ownerStackId = (null == ownerStackId) ? stackId : ownerStackId;
+  }
+
+  /**
+   * @return
+   *      the stack id that owns this upgrade pack.
+   */
+  public StackId getOwnerStackId() {
+    return ownerStackId;
+  }
 }
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeContext.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeContext.java
index f149244..5245921 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeContext.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeContext.java
@@ -136,7 +136,7 @@ public class UpgradeContext {
   /**
    * The upgrade pack for this upgrade.
    */
-  private UpgradePack m_upgradePack;
+  private final UpgradePack m_upgradePack;
 
   /**
    * Upgrades will always have a single version being upgraded to and 
downgrades
@@ -320,7 +320,8 @@ public class UpgradeContext {
   @AssistedInject
   public UpgradeContext(@Assisted Cluster cluster,
       @Assisted Map<String, Object> upgradeRequestMap, Gson gson, 
UpgradeHelper upgradeHelper,
-      UpgradeDAO upgradeDAO, RepositoryVersionDAO repoVersionDAO, ConfigHelper 
configHelper)
+      UpgradeDAO upgradeDAO, RepositoryVersionDAO repoVersionDAO, ConfigHelper 
configHelper,
+      AmbariMetaInfo metaInfo)
       throws AmbariException {
     // injected constructor dependencies
     m_gson = gson;
@@ -329,6 +330,7 @@ public class UpgradeContext {
     m_repoVersionDAO = repoVersionDAO;
     m_cluster = cluster;
     m_isRevert = upgradeRequestMap.containsKey(UPGRADE_REVERT_UPGRADE_ID);
+    m_metaInfo = metaInfo;
 
     if (m_isRevert) {
       m_revertUpgradeId = 
Long.parseLong(upgradeRequestMap.get(UPGRADE_REVERT_UPGRADE_ID).toString());
@@ -395,6 +397,7 @@ public class UpgradeContext {
       // !!! direction can ONLY be an downgrade on revert
       m_direction = Direction.DOWNGRADE;
       m_orchestration = revertUpgrade.getOrchestration();
+      m_upgradePack = getUpgradePack(revertUpgrade);
     } else {
 
       // determine direction
@@ -421,8 +424,26 @@ public class UpgradeContext {
           m_repositoryVersion = 
m_repoVersionDAO.findByPK(Long.valueOf(repositoryVersionId));
           m_orchestration = m_repositoryVersion.getType();
 
+
+          Set<String> serviceNames = getServicesForUpgrade(cluster, 
m_repositoryVersion);
           // add all of the services participating in the upgrade
-          m_services.addAll(getServicesForUpgrade(cluster, 
m_repositoryVersion));
+          m_services.addAll(serviceNames);
+
+          /*
+           * 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) 
upgradeRequestMap.get(UPGRADE_PACK);
+
+          @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES,
+              comment="This is wrong; it assumes that any upgrade source AND 
target are consistent stacks")
+          RepositoryVersionEntity upgradeFromRepositoryVersion = 
cluster.getService(
+              serviceNames.iterator().next()).getDesiredRepositoryVersion();
+
+          m_upgradePack = 
m_upgradeHelper.suggestUpgradePack(m_cluster.getClusterName(),
+              upgradeFromRepositoryVersion.getStackId(), 
m_repositoryVersion.getStackId(), m_direction,
+              m_type, preferredUpgradePackName);
+
           break;
         }
         case DOWNGRADE:{
@@ -440,6 +461,8 @@ public class UpgradeContext {
             m_targetRepositoryMap.put(history.getServiceName(), 
history.getFromReposistoryVersion());
           }
 
+          m_upgradePack = getUpgradePack(upgrade);
+
           break;
         }
         default:
@@ -448,21 +471,6 @@ public class UpgradeContext {
       }
     }
 
-
-    /**
-     * 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) 
upgradeRequestMap.get(UPGRADE_PACK);
-
-    @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES, comment="This 
is wrong")
-    RepositoryVersionEntity upgradeFromRepositoryVersion = cluster.getService(
-        m_services.iterator().next()).getDesiredRepositoryVersion();
-
-    m_upgradePack = 
m_upgradeHelper.suggestUpgradePack(m_cluster.getClusterName(),
-        upgradeFromRepositoryVersion.getStackId(), 
m_repositoryVersion.getStackId(), m_direction,
-        m_type, preferredUpgradePackName);
-
     // the validator will throw an exception if the upgrade request is not 
valid
     UpgradeRequestValidator upgradeRequestValidator = buildValidator(m_type);
     upgradeRequestValidator.validate(cluster, m_direction, m_type, 
m_upgradePack,
@@ -544,10 +552,7 @@ public class UpgradeContext {
       }
     }
 
-    String upgradePackage = upgradeEntity.getUpgradePackage();
-    stackId = (null != stackId) ? stackId : m_repositoryVersion.getStackId(); 
// fallback to old value
-    Map<String, UpgradePack> packs = 
m_metaInfo.getUpgradePacks(stackId.getStackName(), stackId.getStackVersion());
-    m_upgradePack = packs.get(upgradePackage);
+    m_upgradePack = getUpgradePack(upgradeEntity);
 
     m_resolver = new MasterHostResolver(m_cluster, configHelper, this);
     m_orchestration = upgradeEntity.getOrchestration();
@@ -580,16 +585,6 @@ public class UpgradeContext {
   }
 
   /**
-   * Sets the upgrade pack for this upgrade
-   *
-   * @param upgradePack
-   *          the upgrade pack to set
-   */
-  public void setUpgradePack(UpgradePack upgradePack) {
-    m_upgradePack = upgradePack;
-  }
-
-  /**
    * Gets the cluster that the upgrade is for.
    *
    * @return the cluster (never {@code null}).
@@ -1445,4 +1440,21 @@ public class UpgradeContext {
       return hostOrderItems;
     }
   }
+
+  /**
+   * Loads the upgrade pack used for an upgrade after it has been persisted.
+   *
+   * @param upgrade
+   *          the upgrade entity
+   * @return
+   *          the upgrade pack.  May be {@code null} if it doesn't exist
+   */
+  UpgradePack getUpgradePack(UpgradeEntity upgrade) {
+    StackId stackId = upgrade.getUpgradePackStackId();
+
+    Map<String, UpgradePack> packs = m_metaInfo.getUpgradePacks(
+        stackId.getStackName(), stackId.getStackVersion());
+
+    return packs.get(upgrade.getUpgradePackage());
+  }
 }
\ No newline at end of file
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelper.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelper.java
index 1f05b87..2dfa830 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelper.java
@@ -176,54 +176,104 @@ public class UpgradeHelper {
 
     // Find upgrade packs based on current stack. This is where to upgrade from
     Cluster cluster = m_clusters.get().getCluster(clusterName);
+
     StackId currentStack = cluster.getCurrentStackVersion();
 
-    StackId stackForUpgradePack = targetStackId;
+    /*
+     * To find upgrades packs when moving STACK-1.0 to STACK-2.0:
+     * - Search STACK-2.0 upgrade packs that define source as STACK-1.0
+     * - Search STACK-1.0 upgrade packs that define target as STACK-2.0 
(legacy)
+     */
 
-    if (direction.isDowngrade()) {
-      stackForUpgradePack = sourceStackId;
+    UpgradePack pack = findPreferred(preferredUpgradePackName, currentStack, 
targetStackId);
+    if (null != pack) {
+      return pack;
     }
 
-    Map<String, UpgradePack> packs = 
m_ambariMetaInfoProvider.get().getUpgradePacks(
-        currentStack.getStackName(), currentStack.getStackVersion());
-
-    UpgradePack pack = null;
-
-    if (StringUtils.isNotEmpty(preferredUpgradePackName) && 
packs.containsKey(preferredUpgradePackName)) {
-      pack = packs.get(preferredUpgradePackName);
-
-      LOG.warn("Upgrade pack '{}' not found for stack {}", 
preferredUpgradePackName, currentStack);
+    // !!! try to find a stack that defines the source
+    pack = findUpgradePack(targetStackId, currentStack, upgradeType, true);
+    if (null != pack) {
+      return pack;
     }
 
-    // Best-attempt at picking an upgrade pack assuming within the same stack 
whose target stack version matches.
-    // If multiple candidates are found, raise an exception.
-    if (null == pack) {
-      for (UpgradePack upgradePack : packs.values()) {
-        if (null != upgradePack.getTargetStack()
-            && StringUtils.equals(upgradePack.getTargetStack(), 
stackForUpgradePack.getStackId())
-            && upgradeType == upgradePack.getType()) {
-          if (null == pack) {
-            // Pick the pack.
-            pack = upgradePack;
-          } else {
-            throw new AmbariException(
-                String.format(
-                    "Unable to perform %s. Found multiple upgrade packs for 
type %s and stack %s",
-                    direction.getText(false), upgradeType.toString(), 
stackForUpgradePack));
-          }
-        }
-      }
-    }
+    // !!! try to find a stack that defines the target (legacy)
+    pack = findUpgradePack(currentStack, targetStackId, upgradeType, false);
 
     if (null == pack) {
       throw new AmbariException(
           String.format("Unable to perform %s. Could not locate %s upgrade 
pack for stack %s",
-              direction.getText(false), upgradeType.toString(), 
stackForUpgradePack));
+              direction.getText(false), upgradeType.toString(), 
targetStackId));
     }
 
    return pack;
   }
 
+  /**
+   * Finds an upgrade pack with a preferred name.
+   *
+   * @param preferred
+   *          the name of the preferred upgrade pack
+   * @param stackIds
+   *          the stack ids to find
+   */
+  private UpgradePack findPreferred(String preferred, StackId... stackIds) {
+    if (StringUtils.isEmpty(preferred)) {
+      return null;
+    }
+
+    for (StackId stackId : stackIds) {
+      Map<String, UpgradePack> packs = 
m_ambariMetaInfoProvider.get().getUpgradePacks(
+          stackId.getStackName(), stackId.getStackVersion());
+
+      if (!packs.containsKey(preferred)) {
+        LOG.warn("Upgrade pack '{}' not found for stack {}", preferred, 
stackId);
+      } else {
+        return packs.get(preferred);
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Finds a suitable upgrade pack given the source and target stacks.
+   *
+   * @param sourceStack
+   *          the source stack
+   * @param stackToFind
+   *          the stack to search in upgrade packs
+   * @param compareToSource
+   *          when comparing, use the {@code source} or {@code target} in the 
upgrade pack
+   * @return
+   *          the upgrade pack, if found
+   * @throws AmbariException
+   */
+  private UpgradePack findUpgradePack(StackId sourceStack, StackId stackToFind,
+      UpgradeType upgradeType, boolean compareToSource) throws AmbariException 
{
+
+    Map<String, UpgradePack> packs = 
m_ambariMetaInfoProvider.get().getUpgradePacks(
+        sourceStack.getStackName(), sourceStack.getStackVersion());
+
+    UpgradePack result = null;
+
+    for (UpgradePack upgradePack : packs.values()) {
+      StackId upgradeStack = compareToSource ?
+          new StackId(upgradePack.getSourceStack()) : new 
StackId(upgradePack.getTargetStack());
+
+      if (upgradeStack.equals(stackToFind)) {
+        if (null == result) {
+          result = upgradePack;
+        } else {
+          throw new AmbariException(
+              String.format(
+                  "Unable to resolve upgrade pack. Found multiple upgrade 
packs for type %s and stack %s",
+                  upgradeType.toString(), stackToFind));
+        }
+      }
+    }
+
+    return result;
+  }
 
   /**
    * Generates a list of UpgradeGroupHolder items that are used to execute 
either
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
index 428fab8..cc47a1a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/StackInfo.java
@@ -35,6 +35,7 @@ import org.apache.ambari.server.stack.Validable;
 import org.apache.ambari.server.stack.upgrade.ConfigUpgradePack;
 import org.apache.ambari.server.stack.upgrade.UpgradePack;
 import org.apache.ambari.server.state.repository.VersionDefinitionXml;
+import org.apache.ambari.server.state.stack.LatestRepoCallable;
 import org.apache.ambari.server.state.stack.RepositoryXml;
 import org.apache.ambari.server.state.stack.StackRoleCommandOrder;
 import org.apache.ambari.server.utils.VersionUtils;
@@ -442,6 +443,11 @@ public class StackInfo implements Comparable<StackInfo>, 
Validable {
    * @param upgradePacks map of upgrade packs
    */
   public void setUpgradePacks(Map<String, UpgradePack> upgradePacks) {
+    if (null != upgradePacks) {
+      upgradePacks.values().forEach(pack -> {
+        pack.setOwnerStackId(new StackId(this));
+      });
+    }
     this.upgradePacks = upgradePacks;
   }
 
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog280.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog280.java
index 9b3babf..0222da8 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog280.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog280.java
@@ -39,6 +39,10 @@ public class UpgradeCatalog280 extends 
AbstractUpgradeCatalog {
   protected static final String HOST_COMPONENT_STATE_TABLE = 
"hostcomponentstate";
   private static final String 
REQUEST_SCHEDULE_BATCH_TOLERATION_LIMIT_PER_BATCH_COLUMN_NAME = 
"batch_toleration_limit_per_batch";
   protected static final String LAST_LIVE_STATE_COLUMN = "last_live_state";
+
+  private static final String UPGRADE_TABLE = "upgrade";
+  private static final String UPGRADE_PACK_STACK_ID = "upgrade_pack_stack_id";
+
   @Inject
   public UpgradeCatalog280(Injector injector) {
     super(injector);
@@ -56,8 +60,9 @@ public class UpgradeCatalog280 extends AbstractUpgradeCatalog 
{
 
   @Override
   protected void executeDDLUpdates() throws AmbariException, SQLException {
-    addComulnsToRequestscheduleTable();
     removeLastValidState();
+    addColumnsToRequestScheduleTable();
+    addColumnsToUpgradeTable();
   }
 
   @Override
@@ -68,10 +73,17 @@ public class UpgradeCatalog280 extends 
AbstractUpgradeCatalog {
   protected void executeDMLUpdates() throws AmbariException, SQLException {
   }
 
-  protected void addComulnsToRequestscheduleTable() throws SQLException {
+  protected void addColumnsToRequestScheduleTable() throws SQLException {
+    dbAccessor.addColumn(UPGRADE_TABLE,
+        new DBAccessor.DBColumnInfo(UPGRADE_PACK_STACK_ID, String.class, 255,
+            "", false));
+  }
+
+  protected void addColumnsToUpgradeTable() throws SQLException {
     dbAccessor.addColumn(REQUEST_SCHEDULE_TABLE_NAME,
         new 
DBAccessor.DBColumnInfo(REQUEST_SCHEDULE_BATCH_TOLERATION_LIMIT_PER_BATCH_COLUMN_NAME,
 Short.class, null,
             null, true));
+
   }
 
   protected void removeLastValidState() throws SQLException {
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
index 064807b..b5d3ca4 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -869,6 +869,7 @@ CREATE TABLE upgrade (
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   orchestration VARCHAR(255) DEFAULT 'STANDARD' NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
+  upgrade_package_stack VARCHAR(255) NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
   repo_version_id BIGINT NOT NULL,
   skip_failures SMALLINT DEFAULT 0 NOT NULL,
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index ccc0851..ba9ce93 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -887,6 +887,7 @@ CREATE TABLE upgrade (
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   orchestration VARCHAR(255) DEFAULT 'STANDARD' NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
+  upgrade_package_stack VARCHAR(255) NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
   repo_version_id BIGINT NOT NULL,
   skip_failures TINYINT(1) NOT NULL DEFAULT 0,
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 5f315f1..ba33ceb 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -866,6 +866,7 @@ CREATE TABLE upgrade (
   direction VARCHAR2(255) DEFAULT 'UPGRADE' NOT NULL,
   orchestration VARCHAR2(255) DEFAULT 'STANDARD' NOT NULL,
   upgrade_package VARCHAR2(255) NOT NULL,
+  upgrade_package_stack VARCHAR2(255) NOT NULL,
   upgrade_type VARCHAR2(32) NOT NULL,
   repo_version_id NUMBER(19) NOT NULL,
   skip_failures NUMBER(1) DEFAULT 0 NOT NULL,
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index f40f940..ea79911 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -870,6 +870,7 @@ CREATE TABLE upgrade (
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   orchestration VARCHAR(255) DEFAULT 'STANDARD' NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
+  upgrade_package_stack VARCHAR(255) NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
   repo_version_id BIGINT NOT NULL,
   skip_failures SMALLINT DEFAULT 0 NOT NULL,
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
index f957031..5dea72b 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -867,6 +867,7 @@ CREATE TABLE upgrade (
   upgrade_type VARCHAR(32) NOT NULL,
   repo_version_id NUMERIC(19) NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
+  upgrade_package_stack VARCHAR(255) NOT NULL,
   skip_failures BIT NOT NULL DEFAULT 0,
   skip_sc_failures BIT NOT NULL DEFAULT 0,
   downgrade_allowed BIT NOT NULL DEFAULT 1,
diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql 
b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
index ba59961..ed04fb1 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -887,6 +887,7 @@ CREATE TABLE upgrade (
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   orchestration VARCHAR(255) DEFAULT 'STANDARD' NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
+  upgrade_package_stack VARCHAR(255) NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
   repo_version_id BIGINT NOT NULL,
   skip_failures BIT NOT NULL DEFAULT 0,
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
index b0af6d9..91d6dfd 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
@@ -671,6 +671,7 @@ public class UpgradeResourceProviderTest extends 
EasyMockSupport {
     upgradeEntity.setDirection(Direction.UPGRADE);
     upgradeEntity.setRepositoryVersion(repoVersionEntity2200);
     upgradeEntity.setUpgradePackage("upgrade_test");
+    upgradeEntity.setUpgradePackStackId(repoVersionEntity2200.getStackId());
     upgradeEntity.setUpgradeType(UpgradeType.ROLLING);
     upgradeEntity.setRequestEntity(requestEntity);
 
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeSummaryResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeSummaryResourceProviderTest.java
index 1b5824d..36010bc 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeSummaryResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeSummaryResourceProviderTest.java
@@ -278,6 +278,7 @@ public class UpgradeSummaryResourceProviderTest {
     upgrade.setClusterId(cluster.getClusterId());
     upgrade.setId(1L);
     upgrade.setUpgradePackage("some-name");
+    upgrade.setUpgradePackStackId(new StackId((String) null));
     upgrade.setUpgradeType(UpgradeType.ROLLING);
     upgrade.setDirection(Direction.UPGRADE);
 
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
index 3b469b1..c284b69 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
@@ -102,6 +102,7 @@ public class UpgradeDAOTest {
     entity.setRepositoryVersion(repositoryVersion2200);
     entity.setUpgradeType(UpgradeType.ROLLING);
     entity.setUpgradePackage("test-upgrade");
+    entity.setUpgradePackStackId(new StackId((String) null));
     entity.setDowngradeAllowed(true);
 
     UpgradeGroupEntity group = new UpgradeGroupEntity();
@@ -179,8 +180,10 @@ public class UpgradeDAOTest {
     entity1.setRepositoryVersion(repositoryVersion2500);
     entity1.setUpgradeType(UpgradeType.ROLLING);
     entity1.setUpgradePackage("test-upgrade");
+    entity1.setUpgradePackStackId(new StackId((String) null));
     entity1.setDowngradeAllowed(true);
     dao.create(entity1);
+
     UpgradeEntity entity2 = new UpgradeEntity();
     entity2.setId(22L);
     entity2.setClusterId(clusterId.longValue());
@@ -189,8 +192,10 @@ public class UpgradeDAOTest {
     entity2.setRepositoryVersion(repositoryVersion2200);
     entity2.setUpgradeType(UpgradeType.ROLLING);
     entity2.setUpgradePackage("test-upgrade");
+    entity2.setUpgradePackStackId(new StackId((String) null));
     entity2.setDowngradeAllowed(true);
     dao.create(entity2);
+
     UpgradeEntity entity3 = new UpgradeEntity();
     entity3.setId(33L);
     entity3.setClusterId(clusterId.longValue());
@@ -199,8 +204,10 @@ public class UpgradeDAOTest {
     entity3.setRepositoryVersion(repositoryVersion2511);
     entity3.setUpgradeType(UpgradeType.ROLLING);
     entity3.setUpgradePackage("test-upgrade");
+    entity3.setUpgradePackStackId(new StackId((String) null));
     entity3.setDowngradeAllowed(true);
     dao.create(entity3);
+
     UpgradeEntity lastUpgradeForCluster = 
dao.findLastUpgradeForCluster(clusterId.longValue(), Direction.UPGRADE);
     assertNotNull(lastUpgradeForCluster);
     assertEquals(33L, (long)lastUpgradeForCluster.getId());
@@ -228,6 +235,7 @@ public class UpgradeDAOTest {
     upgradeEntity.setRepositoryVersion(repositoryVersion2500);
     upgradeEntity.setUpgradeType(UpgradeType.ROLLING);
     upgradeEntity.setUpgradePackage("test-upgrade");
+    upgradeEntity.setUpgradePackStackId(new StackId((String) null));
     dao.create(upgradeEntity);
 
     UpgradeEntity lastUpgradeForCluster = dao.findLastUpgradeForCluster(1, 
Direction.UPGRADE);
@@ -271,6 +279,7 @@ public class UpgradeDAOTest {
     entity1.setRepositoryVersion(repositoryVersion2500);
     entity1.setUpgradeType(UpgradeType.ROLLING);
     entity1.setUpgradePackage("test-upgrade");
+    entity1.setUpgradePackStackId(new StackId((String) null));
     entity1.setDowngradeAllowed(true);
     entity1.setOrchestration(RepositoryType.PATCH);
     entity1.setRevertAllowed(true);
@@ -289,6 +298,7 @@ public class UpgradeDAOTest {
     entity2.setRepositoryVersion(repositoryVersion2511);
     entity2.setUpgradeType(UpgradeType.ROLLING);
     entity2.setUpgradePackage("test-upgrade");
+    entity2.setUpgradePackStackId(new StackId((String) null));
     entity2.setDowngradeAllowed(true);
     entity2.setOrchestration(RepositoryType.MAINT);
     entity2.setRevertAllowed(true);
@@ -312,6 +322,7 @@ public class UpgradeDAOTest {
     entity3.setRepositoryVersion(repositoryVersion2511);
     entity3.setUpgradeType(UpgradeType.ROLLING);
     entity3.setUpgradePackage("test-upgrade");
+    entity3.setUpgradePackStackId(new StackId((String) null));
     entity3.setOrchestration(RepositoryType.MAINT);
     entity3.setDowngradeAllowed(false);
     dao.create(entity3);
@@ -334,6 +345,7 @@ public class UpgradeDAOTest {
     entity4.setRepositoryVersion(repositoryVersion2500);
     entity4.setUpgradeType(UpgradeType.ROLLING);
     entity4.setUpgradePackage("test-upgrade");
+    entity4.setUpgradePackStackId(new StackId((String) null));
     entity4.setOrchestration(RepositoryType.MAINT);
     entity4.setDowngradeAllowed(false);
     dao.create(entity4);
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AbstractAuthenticationProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AbstractAuthenticationProviderTest.java
index b24935d..ca47faa 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AbstractAuthenticationProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/security/authentication/AbstractAuthenticationProviderTest.java
@@ -46,7 +46,7 @@ import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.Module;
 
-abstract class AbstractAuthenticationProviderTest extends EasyMockSupport {
+public abstract class AbstractAuthenticationProviderTest extends 
EasyMockSupport {
 
   static final String TEST_USER_NAME = "userName";
 
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
index 2cfdf5b..4ba7235 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
@@ -209,6 +209,7 @@ public class ComponentVersionCheckActionTest {
     upgradeEntity.setClusterId(c.getClusterId());
     upgradeEntity.setRequestEntity(requestEntity);
     upgradeEntity.setUpgradePackage("");
+    upgradeEntity.setUpgradePackStackId(new StackId((String) null));
     upgradeEntity.setRepositoryVersion(toRepositoryVersion);
     upgradeEntity.setUpgradeType(UpgradeType.NON_ROLLING);
     upgradeDAO.create(upgradeEntity);
@@ -282,6 +283,7 @@ public class ComponentVersionCheckActionTest {
     upgradeEntity.setClusterId(c.getClusterId());
     upgradeEntity.setRequestEntity(requestEntity);
     upgradeEntity.setUpgradePackage("");
+    upgradeEntity.setUpgradePackStackId(new StackId((String) null));
     upgradeEntity.setRepositoryVersion(toRepositoryVersion);
     upgradeEntity.setUpgradeType(UpgradeType.NON_ROLLING);
     upgradeDAO.create(upgradeEntity);
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java
index 624e1a4..7ce6102 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ConfigureActionTest.java
@@ -1993,6 +1993,7 @@ public class ConfigureActionTest {
     upgradeEntity.setClusterId(cluster.getClusterId());
     upgradeEntity.setRequestEntity(requestEntity);
     upgradeEntity.setUpgradePackage("");
+    upgradeEntity.setUpgradePackStackId(new StackId((String) null));
     upgradeEntity.setRepositoryVersion(repositoryVersion);
     upgradeEntity.setUpgradeType(UpgradeType.NON_ROLLING);
 
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/CreateAndConfigureActionTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/CreateAndConfigureActionTest.java
index 718f54f..a089035 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/CreateAndConfigureActionTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/CreateAndConfigureActionTest.java
@@ -317,6 +317,7 @@ public class CreateAndConfigureActionTest {
     upgradeEntity.setClusterId(cluster.getClusterId());
     upgradeEntity.setRequestEntity(requestEntity);
     upgradeEntity.setUpgradePackage("");
+    upgradeEntity.setUpgradePackStackId(new StackId((String) null));
     upgradeEntity.setRepositoryVersion(repositoryVersion);
     upgradeEntity.setUpgradeType(UpgradeType.NON_ROLLING);
 
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
index bfb9201..30df4a5 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
@@ -783,6 +783,7 @@ public class UpgradeActionTest {
     upgradeEntity.setClusterId(cluster.getClusterId());
     upgradeEntity.setRequestEntity(requestEntity);
     upgradeEntity.setUpgradePackage("");
+    upgradeEntity.setUpgradePackStackId(new StackId((String) null));
     upgradeEntity.setRepositoryVersion(repositoryVersion);
     upgradeEntity.setUpgradeType(UpgradeType.NON_ROLLING);
 
@@ -827,6 +828,7 @@ public class UpgradeActionTest {
     revert.setClusterId(cluster.getClusterId());
     revert.setRequestEntity(requestEntity);
     revert.setUpgradePackage("");
+    revert.setUpgradePackStackId(new StackId((String) null));
     revert.setRepositoryVersion(upgradeToRevert.getRepositoryVersion());
     revert.setUpgradeType(upgradeToRevert.getUpgradeType());
     revert.setOrchestration(upgradeToRevert.getOrchestration());
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeContextTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeContextTest.java
index 81a68b2..55f490f 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeContextTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeContextTest.java
@@ -24,11 +24,13 @@ import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
@@ -51,6 +53,7 @@ import org.easymock.Mock;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
@@ -116,6 +119,9 @@ public class UpgradeContextTest extends EasyMockSupport {
   @Mock
   private VersionDefinitionXml m_vdfXml;
 
+  @Mock
+  private AmbariMetaInfo m_ambariMetaInfo;
+
   /**
    * The upgrade history to return for the completed upgrade.
    */
@@ -130,6 +136,9 @@ public class UpgradeContextTest extends EasyMockSupport {
   public void setup() throws Exception {
     injectMocks(this);
 
+    expect(m_ambariMetaInfo.getUpgradePacks(
+        EasyMock.anyString(), 
EasyMock.anyString())).andReturn(Collections.emptyMap()).anyTimes();
+
     expect(m_sourceRepositoryVersion.getId()).andReturn(1L).anyTimes();
     expect(m_sourceRepositoryVersion.getStackId()).andReturn(new 
StackId("HDP", "2.6")).anyTimes();
     
expect(m_sourceRepositoryVersion.getVersion()).andReturn("2.6.0.0").anyTimes();
@@ -158,7 +167,8 @@ public class UpgradeContextTest extends EasyMockSupport {
     
expect(m_completedRevertableUpgrade.getRepositoryVersion()).andReturn(m_targetRepositoryVersion).anyTimes();
     
expect(m_completedRevertableUpgrade.getOrchestration()).andReturn(RepositoryType.PATCH).anyTimes();
     
expect(m_completedRevertableUpgrade.getHistory()).andReturn(m_upgradeHistory).anyTimes();
-    
expect(m_completedRevertableUpgrade.getUpgradePackage()).andReturn(null).anyTimes();
+    
expect(m_completedRevertableUpgrade.getUpgradePackage()).andReturn("myUpgradePack").anyTimes();
+    expect(m_completedRevertableUpgrade.getUpgradePackStackId()).andReturn(new 
StackId((String) null)).anyTimes();
 
     RepositoryVersionEntity hdfsRepositoryVersion = 
createNiceMock(RepositoryVersionEntity.class);
     expect(hdfsRepositoryVersion.getId()).andReturn(1L).anyTimes();
@@ -188,6 +198,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     UpgradeHelper upgradeHelper = createNiceMock(UpgradeHelper.class);
     ConfigHelper configHelper = createNiceMock(ConfigHelper.class);
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
+    AmbariMetaInfo ami = createNiceMock(AmbariMetaInfo.class);
 
     
expect(m_targetRepositoryVersion.getType()).andReturn(RepositoryType.STANDARD).atLeastOnce();
 
@@ -205,7 +216,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     requestMap.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, 
"true");
 
     UpgradeContext context = new UpgradeContext(m_cluster, requestMap, null, 
upgradeHelper,
-        m_upgradeDAO, m_repositoryVersionDAO, configHelper);
+        m_upgradeDAO, m_repositoryVersionDAO, configHelper, ami);
 
     assertEquals(Direction.UPGRADE, context.getDirection());
     assertEquals(RepositoryType.STANDARD, context.getOrchestrationType());
@@ -226,6 +237,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     UpgradeHelper upgradeHelper = createNiceMock(UpgradeHelper.class);
     ConfigHelper configHelper = createNiceMock(ConfigHelper.class);
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
+    AmbariMetaInfo ami = createNiceMock(AmbariMetaInfo.class);
 
     expect(m_clusterVersionSummary.getAvailableServiceNames()).andReturn(
         Sets.newHashSet(HDFS_SERVICE_NAME)).once();
@@ -252,7 +264,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     requestMap.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, 
"true");
 
     UpgradeContext context = new UpgradeContext(m_cluster, requestMap, null, 
upgradeHelper,
-        m_upgradeDAO, m_repositoryVersionDAO, configHelper);
+        m_upgradeDAO, m_repositoryVersionDAO, configHelper, ami);
 
     assertEquals(Direction.UPGRADE, context.getDirection());
     assertEquals(RepositoryType.PATCH, context.getOrchestrationType());
@@ -275,6 +287,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     UpgradeHelper upgradeHelper = createNiceMock(UpgradeHelper.class);
     ConfigHelper configHelper = createNiceMock(ConfigHelper.class);
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
+    AmbariMetaInfo ami = createNiceMock(AmbariMetaInfo.class);
 
     expect(m_clusterVersionSummary.getAvailableServiceNames()).andReturn(
         Sets.newHashSet(HDFS_SERVICE_NAME)).once();
@@ -301,7 +314,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     requestMap.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, 
"true");
 
     UpgradeContext context = new UpgradeContext(m_cluster, requestMap, null, 
upgradeHelper,
-        m_upgradeDAO, m_repositoryVersionDAO, configHelper);
+        m_upgradeDAO, m_repositoryVersionDAO, configHelper, ami);
 
     assertEquals(Direction.UPGRADE, context.getDirection());
     assertEquals(RepositoryType.MAINT, context.getOrchestrationType());
@@ -321,12 +334,14 @@ public class UpgradeContextTest extends EasyMockSupport {
   public void testRevert() throws Exception {
     UpgradeHelper upgradeHelper = createNiceMock(UpgradeHelper.class);
     ConfigHelper configHelper = createNiceMock(ConfigHelper.class);
-
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
+    AmbariMetaInfo ami = createNiceMock(AmbariMetaInfo.class);
 
-    expect(upgradeHelper.suggestUpgradePack(EasyMock.anyString(), 
EasyMock.anyObject(StackId.class),
-        EasyMock.anyObject(StackId.class), EasyMock.anyObject(Direction.class),
-        EasyMock.anyObject(UpgradeType.class), 
EasyMock.anyString())).andReturn(upgradePack).once();
+    Map<String, UpgradePack> map = ImmutableMap.<String, UpgradePack>builder()
+        .put("myUpgradePack", upgradePack)
+        .build();
+
+    expect(ami.getUpgradePacks(EasyMock.anyString(), 
EasyMock.anyString())).andReturn(map).anyTimes();
 
     
expect(m_upgradeDAO.findRevertable(1L)).andReturn(m_completedRevertableUpgrade).once();
 
@@ -337,7 +352,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     replayAll();
 
     UpgradeContext context = new UpgradeContext(m_cluster, requestMap, null, 
upgradeHelper,
-        m_upgradeDAO, m_repositoryVersionDAO, configHelper);
+        m_upgradeDAO, m_repositoryVersionDAO, configHelper, ami);
 
     assertEquals(Direction.DOWNGRADE, context.getDirection());
     assertEquals(RepositoryType.PATCH, context.getOrchestrationType());
@@ -360,10 +375,13 @@ public class UpgradeContextTest extends EasyMockSupport {
     ConfigHelper configHelper = createNiceMock(ConfigHelper.class);
     UpgradeHelper upgradeHelper = createNiceMock(UpgradeHelper.class);
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
+    AmbariMetaInfo ami = createNiceMock(AmbariMetaInfo.class);
 
-    expect(upgradeHelper.suggestUpgradePack(EasyMock.anyString(), 
EasyMock.anyObject(StackId.class),
-      EasyMock.anyObject(StackId.class), EasyMock.anyObject(Direction.class),
-      EasyMock.anyObject(UpgradeType.class), 
EasyMock.anyString())).andReturn(upgradePack).once();
+    Map<String, UpgradePack> map = ImmutableMap.<String, UpgradePack>builder()
+        .put("myUpgradePack", upgradePack)
+        .build();
+
+    expect(ami.getUpgradePacks(EasyMock.anyString(), 
EasyMock.anyString())).andReturn(map).anyTimes();
 
     
expect(m_upgradeDAO.findRevertable(1L)).andReturn(m_completedRevertableUpgrade).once();
     
expect(m_completedRevertableUpgrade.getUpgradeType()).andReturn(UpgradeType.NON_ROLLING);
@@ -374,7 +392,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     replayAll();
 
     UpgradeContext context = new UpgradeContext(m_cluster, requestMap, null, 
upgradeHelper,
-      m_upgradeDAO, m_repositoryVersionDAO, configHelper);
+      m_upgradeDAO, m_repositoryVersionDAO, configHelper, ami);
 
     assertEquals(Direction.DOWNGRADE, context.getDirection());
     assertEquals(RepositoryType.PATCH, context.getOrchestrationType());
@@ -397,6 +415,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     UpgradeHelper upgradeHelper = createNiceMock(UpgradeHelper.class);
     ConfigHelper configHelper = createNiceMock(ConfigHelper.class);
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
+    AmbariMetaInfo ami = createNiceMock(AmbariMetaInfo.class);
 
     // give the completed upgrade 2 services which can be reverted
     UpgradeHistoryEntity upgradeHistoryEntity = 
createNiceMock(UpgradeHistoryEntity.class);
@@ -405,9 +424,11 @@ public class UpgradeContextTest extends EasyMockSupport {
     
expect(upgradeHistoryEntity.getTargetRepositoryVersion()).andReturn(m_targetRepositoryVersion).anyTimes();
     m_upgradeHistory.add(upgradeHistoryEntity);
 
-    expect(upgradeHelper.suggestUpgradePack(EasyMock.anyString(), 
EasyMock.anyObject(StackId.class),
-        EasyMock.anyObject(StackId.class), EasyMock.anyObject(Direction.class),
-        EasyMock.anyObject(UpgradeType.class), 
EasyMock.anyString())).andReturn(upgradePack).once();
+    Map<String, UpgradePack> map = ImmutableMap.<String, UpgradePack>builder()
+        .put("myUpgradePack", upgradePack)
+        .build();
+
+    expect(ami.getUpgradePacks(EasyMock.anyString(), 
EasyMock.anyString())).andReturn(map).anyTimes();
 
     
expect(m_upgradeDAO.findRevertable(1L)).andReturn(m_completedRevertableUpgrade).once();
 
@@ -424,7 +445,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     replayAll();
 
     UpgradeContext context = new UpgradeContext(m_cluster, requestMap, null, 
upgradeHelper,
-        m_upgradeDAO, m_repositoryVersionDAO, configHelper);
+        m_upgradeDAO, m_repositoryVersionDAO, configHelper, ami);
 
     assertEquals(Direction.DOWNGRADE, context.getDirection());
     assertEquals(RepositoryType.PATCH, context.getOrchestrationType());
@@ -447,8 +468,8 @@ public class UpgradeContextTest extends EasyMockSupport {
 
     UpgradeHelper upgradeHelper = createNiceMock(UpgradeHelper.class);
     ConfigHelper configHelper = createNiceMock(ConfigHelper.class);
-
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
+    AmbariMetaInfo ami = createNiceMock(AmbariMetaInfo.class);
 
     expect(upgradeHelper.suggestUpgradePack(EasyMock.anyString(), 
EasyMock.anyObject(StackId.class),
         EasyMock.anyObject(StackId.class), EasyMock.anyObject(Direction.class),
@@ -470,7 +491,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     replayAll();
 
     UpgradeContext context = new UpgradeContext(m_cluster, requestMap, null, 
upgradeHelper,
-        m_upgradeDAO, m_repositoryVersionDAO, configHelper);
+        m_upgradeDAO, m_repositoryVersionDAO, configHelper, ami);
 
     assertEquals(Direction.DOWNGRADE, context.getDirection());
     assertEquals(RepositoryType.PATCH, context.getOrchestrationType());
@@ -491,11 +512,13 @@ public class UpgradeContextTest extends EasyMockSupport {
     UpgradeHelper upgradeHelper = createNiceMock(UpgradeHelper.class);
     ConfigHelper configHelper = createNiceMock(ConfigHelper.class);
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
+    AmbariMetaInfo ami = createNiceMock(AmbariMetaInfo.class);
 
-    expect(upgradeHelper.suggestUpgradePack(EasyMock.anyString(), 
EasyMock.anyObject(StackId.class),
-        EasyMock.anyObject(StackId.class), EasyMock.anyObject(Direction.class),
-        EasyMock.anyObject(UpgradeType.class), 
EasyMock.anyString())).andReturn(upgradePack).once();
+    Map<String, UpgradePack> map = ImmutableMap.<String, UpgradePack>builder()
+        .put("myUpgradePack", upgradePack)
+        .build();
 
+    expect(ami.getUpgradePacks(EasyMock.anyString(), 
EasyMock.anyString())).andReturn(map).anyTimes();
 
     Map<String, Object> requestMap = new HashMap<>();
     requestMap.put(UpgradeResourceProvider.UPGRADE_TYPE, 
UpgradeType.NON_ROLLING.name());
@@ -504,7 +527,7 @@ public class UpgradeContextTest extends EasyMockSupport {
     replayAll();
 
     UpgradeContext context = new UpgradeContext(m_cluster, requestMap, null, 
upgradeHelper,
-        m_upgradeDAO, m_repositoryVersionDAO, configHelper);
+        m_upgradeDAO, m_repositoryVersionDAO, configHelper, ami);
 
     assertEquals(Direction.DOWNGRADE, context.getDirection());
     assertEquals(RepositoryType.PATCH, context.getOrchestrationType());
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelperTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelperTest.java
index 18fffb5..1e0ea0d 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelperTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/stack/upgrade/orchestrate/UpgradeHelperTest.java
@@ -31,6 +31,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.lang.reflect.Field;
 import java.sql.SQLException;
@@ -243,6 +244,24 @@ public class UpgradeHelperTest extends EasyMockSupport {
   }
 
   @Test
+  public void testSuggestUpgradePackFromSourceStack() throws Exception {
+    final String clusterName = "c1";
+    final StackId sourceStackId = new StackId("HDP", "2.1.1");
+    final StackId targetStackId = new StackId("HDP", "2.2.0");
+    final Direction upgradeDirection = Direction.UPGRADE;
+    final UpgradeType upgradeType = UpgradeType.ROLLING;
+
+    makeCluster();
+    try {
+      UpgradePack up = m_upgradeHelper.suggestUpgradePack(clusterName, 
sourceStackId, targetStackId, upgradeDirection, upgradeType, null);
+      assertEquals(upgradeType, up.getType());
+    } catch (AmbariException e) {
+      e.printStackTrace();
+      fail("unexpected exception suggesting upgrade pack");
+    }
+  }
+
+  @Test
   public void testUpgradeOrchestration() throws Exception {
     Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("foo", 
"bar");
     assertTrue(upgrades.isEmpty());
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/state/services/RetryUpgradeActionServiceTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/state/services/RetryUpgradeActionServiceTest.java
index bea5113..911ab23 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/state/services/RetryUpgradeActionServiceTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/state/services/RetryUpgradeActionServiceTest.java
@@ -280,6 +280,7 @@ public class RetryUpgradeActionServiceTest {
     upgrade.setRequestEntity(requestEntity);
     upgrade.setClusterId(cluster.getClusterId());
     upgrade.setUpgradePackage("some-name");
+    upgrade.setUpgradePackStackId(new StackId((String) null));
     upgrade.setUpgradeType(UpgradeType.ROLLING);
     upgrade.setDirection(Direction.UPGRADE);
     upgrade.setRepositoryVersion(repoVersionEntity);
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/ConfigUpgradeValidityTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/ConfigUpgradeValidityTest.java
index e241b2c..58da312 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/ConfigUpgradeValidityTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/ConfigUpgradeValidityTest.java
@@ -161,8 +161,6 @@ public class ConfigUpgradeValidityTest {
 
         UpgradeContext cx = upgradeContextFactory.create(cluster, 
upgradeEntity);
 
-        cx.setUpgradePack(upgradePack);
-
         ConfigUpgradePack configUpgradePack = 
ConfigurationPackBuilder.build(cx);
 
         // do configure tasks in the group section
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog280Test.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog280Test.java
index b68584b..d3e6ada 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog280Test.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog280Test.java
@@ -35,7 +35,6 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
-
 import com.google.inject.Injector;
 
 public class UpgradeCatalog280Test {
@@ -61,6 +60,10 @@ public class UpgradeCatalog280Test {
     expectLastCall().once();
 
 
+    Capture<DBAccessor.DBColumnInfo> upgradePackStackColumn = 
newCapture(CaptureType.ALL);
+    dbAccessor.addColumn(eq("upgrade"), capture(upgradePackStackColumn));
+    expectLastCall().once();
+
     replay(dbAccessor, injector);
 
     UpgradeCatalog280 upgradeCatalog280 = new UpgradeCatalog280(injector);
@@ -74,6 +77,12 @@ public class UpgradeCatalog280Test {
     Assert.assertEquals(null, 
capturedBlueprintProvisioningStateColumn.getDefaultValue());
     Assert.assertEquals(Short.class, 
capturedBlueprintProvisioningStateColumn.getType());
 
+    DBAccessor.DBColumnInfo capturedUpgradeColumn = 
upgradePackStackColumn.getValue();
+    Assert.assertEquals("upgrade_pack_stack_id", 
capturedUpgradeColumn.getName());
+    Assert.assertEquals(String.class, capturedUpgradeColumn.getType());
+    Assert.assertEquals((Integer) 255, capturedUpgradeColumn.getLength());
+
+
     verify(dbAccessor);
   }
 }
diff --git 
a/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_from_211.xml
 
b/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_from_211.xml
new file mode 100644
index 0000000..87a116a
--- /dev/null
+++ 
b/ambari-server/src/test/resources/stacks/HDP/2.2.0/upgrades/upgrade_from_211.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0"?>
+<!--
+   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.
+-->
+<upgrade    xsi:noNamespaceSchemaLocation="upgrade-pack.xsd" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
+  <source>2.1.1.*</source>
+  <source-stack>HDP-2.1.1</source-stack>
+  <type>ROLLING</type>
+  <prerequisite-checks>
+    <check>org.apache.ambari.server.checks.HiveMultipleMetastoreCheck</check>
+    
<check>org.apache.ambari.server.checks.MapReduce2JobHistoryStatePreservingCheck</check>
+    
<check>org.apache.ambari.server.checks.SecondaryNamenodeDeletedCheck</check>
+    
<check>org.apache.ambari.server.checks.ServicesMapReduceDistributedCacheCheck</check>
+    
<check>org.apache.ambari.server.checks.ServicesNamenodeHighAvailabilityCheck</check>
+    
<check>org.apache.ambari.server.checks.ServicesNamenodeTruncateCheck</check>
+    
<check>org.apache.ambari.server.checks.ServicesTezDistributedCacheCheck</check>
+    
<check>org.apache.ambari.server.checks.ServicesYarnWorkPreservingCheck</check>
+    <check>org.apache.ambari.server.checks.YarnRMHighAvailabilityCheck</check>
+    
<check>org.apache.ambari.server.checks.YarnTimelineServerStatePreservingCheck</check>
+  </prerequisite-checks>
+  <order>
+    <group xsi:type="cluster" name="PRE_CLUSTER" title="Pre 
{{direction.text.proper}}">
+      <execute-stage title="Confirm 1">
+        <task xsi:type="manual">
+          <message>Foo</message>
+        </task>
+      </execute-stage>
+      <execute-stage service="HDFS" component="NAMENODE" title="Pre Upgrade 
HIVE">
+        <task xsi:type="manual">
+          <message>Back stuff up.</message>
+        </task>
+      </execute-stage>
+      <execute-stage service="HDFS" component="NAMENODE" title="Finalize HDFS">
+        <task xsi:type="execute">
+          <script>foo</script>
+          <function>list</function>
+        </task>
+      </execute-stage>
+      <execute-stage title="Confirm 2">
+        <task xsi:type="manual">
+          <message>Goo</message>
+        </task>
+      </execute-stage>
+    </group>
+  
+    <group name="ZOOKEEPER" title="Zookeeper">
+      <skippable>true</skippable>
+      <allow-retry>false</allow-retry>
+      <service name="ZOOKEEPER">
+        <component>ZOOKEEPER_SERVER</component>
+        <component>ZOOKEEPER_CLIENT</component>
+      </service>
+    </group>
+    
+    <group name="CORE_MASTER" title="Core Masters">
+      <service name="HDFS">
+        <component>JOURNALNODE</component>
+        <component>NAMENODE</component>
+      </service>
+      <service name="YARN">
+        <component>RESOURCEMANAGER</component>
+      </service>
+    </group>
+    
+    <group name="CORE_SLAVES" title="Core Slaves" xsi:type="colocated">
+      <skippable>true</skippable>      <!-- set skippable for test -->
+      <allow-retry>false</allow-retry> <!-- set no retry for test -->
+      <service name="HDFS">
+        <component>DATANODE</component>
+      </service>
+      <service name="HBASE">
+        <component>REGIONSERVER</component>
+      </service>
+      <service name="YARN">
+        <component>NODEMANAGER</component>
+      </service>
+      
+      <batch>
+        <percent>20</percent>
+        <message>Please run additional tests on {{components}}</message>
+      </batch>
+    </group>
+    
+    <group name="HIVE" title="Hive">
+      <skippable>true</skippable>
+      <service name="HIVE">
+        <component>HIVE_METASTORE</component>
+        <component>HIVE_SERVER</component>
+        <component>WEBHCAT_SERVER</component>
+      </service>
+    </group>    
+    
+    <group xsi:type="cluster" name="POST_CLUSTER" title="Finalize 
{{direction.text.proper}}">
+      <execute-stage title="Confirm Finalize">
+        <task xsi:type="manual">
+          <message>Please confirm you are ready to finalize</message>
+        </task>
+      </execute-stage>
+      <execute-stage title="Update remaining HDP stack to {{version}}">
+        <task xsi:type="execute">
+          <script>scripts/stack_select_set_all.py</script>
+          <function>actionexecute</function>
+        </task>
+      </execute-stage>
+      <execute-stage title="Save Cluster State">
+        <task xsi:type="server_action" 
class="org.apache.ambari.server.serveraction.upgrades.FinalizeUpgradeAction">
+        </task>
+      </execute-stage>
+    </group>
+        
+  </order>
+  
+
+  <processing>
+    <service name="ZOOKEEPER">
+      <component name="ZOOKEEPER_SERVER">
+        <pre-upgrade>
+          <task xsi:type="manual">
+            <summary>SUMMARY OF PREPARE</summary>
+            <message>This is a manual task with a placeholder of 
{{foo/bar}}</message>
+          </task>
+        </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
+        <upgrade>
+          <task xsi:type="restart-task" />
+        </upgrade>
+        <post-upgrade>
+          <task xsi:type="configure" id="foo" />
+        </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
+      </component>
+    </service>
+    
+    <service name="HDFS">
+      <component name="NAMENODE">
+        <pre-upgrade>
+          <task xsi:type="execute" hosts="master">
+            <script>foo</script>
+            <function>list</function>
+          </task>
+          <task xsi:type="configure" id="foo" />
+          <task xsi:type="manual">
+            <message>{{direction.verb.proper}} your database</message>
+          </task>
+        </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
+        <upgrade>
+          <task xsi:type="restart-task" />
+        </upgrade>
+        <post-upgrade>
+          <task xsi:type="execute">
+            <script>foo</script>
+            <function>list</function>
+          </task>
+        </post-upgrade>
+        <post-downgrade copy-upgrade="true" />
+      </component>
+      <component name="DATANODE">
+        <pre-downgrade />
+        <upgrade>
+          <task xsi:type="restart-task" />
+        </upgrade>
+        <post-downgrade>
+          <task xsi:type="manual">
+            <message>Manual Downgrade</message>
+          </task>
+        </post-downgrade>
+      </component>
+    </service>
+    
+    <service name="YARN">
+      <component name="RESOURCEMANAGER">
+        <pre-upgrade>
+          <task xsi:type="execute">
+            <script>foo</script>
+            <function>list</function>
+          </task>
+        </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
+        <upgrade />
+      </component>
+      <component name="NODEMANAGER">
+        <pre-upgrade>
+          <task xsi:type="execute">
+            <script>foo</script>
+            <function>list</function>
+          </task>
+        </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
+        <upgrade />
+      </component>
+    </service>
+    
+    <service name="HIVE">
+      <component name="HIVE_SERVER">
+        <pre-upgrade>
+          <task xsi:type="manual">
+            <summary>HiveServer Port Availability</summary>
+            <message>The HiveServer port will now change to 10010 if hive is 
using a binary transfer mode or 10011 if hive is using an http transport mode. 
You can use "netstat -anp | grep 1001[01]" to determine if the port is 
available on each of following HiveServer host(s): {{hosts.all}}. If the port 
is not available, the process using it must be terminated.</message>
+          </task>
+        </pre-upgrade>
+        <pre-downgrade copy-upgrade="true" />
+        <upgrade />
+       </component>
+     </service>    
+  </processing>
+</upgrade>

Reply via email to