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

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

Repository: ambari
Updated Branches:
  refs/heads/branch-feature-AMBARI-12556 87e8bdf1a -> 522039ebd


http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
index e3ffe8f..98f5228 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/UpgradeHelperTest.java
@@ -76,7 +76,9 @@ import org.apache.ambari.server.state.stack.upgrade.TaskWrapper;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeScope;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.apache.ambari.server.utils.EventBusSynchronizer;
+import org.easymock.Capture;
 import org.easymock.EasyMock;
+import org.easymock.IAnswer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -98,8 +100,7 @@ import com.google.inject.util.Modules;
  */
 public class UpgradeHelperTest {
 
-//  private static final StackId HDP_21 = new StackId("HDP-2.1.1");
-//  private static final StackId HDP_22 = new StackId("HDP-2.2.0");
+  private static final StackId STACK_ID_HDP_220 = new StackId("HDP-2.2.0");
   private static final String UPGRADE_VERSION = "2.2.1.0-1234";
   private static final String DOWNGRADE_VERSION = "2.2.0.0-1234";
 
@@ -114,6 +115,9 @@ public class UpgradeHelperTest {
   private Gson m_gson = new Gson();
   private UpgradeContextFactory m_upgradeContextFactory;
 
+  private RepositoryVersionEntity repositoryVersion2200;
+  private RepositoryVersionEntity repositoryVersion2210;
+
   /**
    * Because test cases need to share config mocks, put common ones in this function.
    * @throws Exception
@@ -158,6 +162,9 @@ public class UpgradeHelperTest {
     m_managementController = injector.getInstance(AmbariManagementController.class);
     m_upgradeContextFactory = injector.getInstance(UpgradeContextFactory.class);
 
+    repositoryVersion2200 = helper.getOrCreateRepositoryVersion(STACK_ID_HDP_220, DOWNGRADE_VERSION);
+    repositoryVersion2210 = helper.getOrCreateRepositoryVersion(STACK_ID_HDP_220, UPGRADE_VERSION);
+
     // Set the authenticated user
     // TODO: remove this or replace the authenticated user to test authorization rules
     SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator("admin"));
@@ -207,10 +214,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -289,11 +293,15 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
-    context.setSupportedServices(Collections.singleton("ZOOKEEPER"));
-    context.setScope(UpgradeScope.PARTIAL);
+    Set<String> services = Collections.singleton("ZOOKEEPER");
+    UpgradeContext context = EasyMock.createNiceMock(UpgradeContext.class);
+    EasyMock.expect(context.getCluster()).andReturn(cluster).anyTimes();
+    EasyMock.expect(context.getType()).andReturn(UpgradeType.ROLLING).anyTimes();
+    EasyMock.expect(context.getDirection()).andReturn(Direction.UPGRADE).anyTimes();
+    EasyMock.expect(context.getRepositoryVersion()).andReturn(repositoryVersion2210).anyTimes();
+    EasyMock.expect(context.getSupportedServices()).andReturn(services).anyTimes();
+    EasyMock.expect(context.getRepositoryType()).andReturn(RepositoryType.PATCH).anyTimes();
+    EasyMock.replay(context);
 
     List<Grouping> groupings = upgrade.getGroups(Direction.UPGRADE);
     assertEquals(8, groupings.size());
@@ -347,12 +355,8 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-
-    context.setResolver(m_masterHostResolver);
-    context.setSupportedServices(Collections.singleton("ZOOKEEPER"));
-    context.setScope(UpgradeScope.COMPLETE);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING,
+        repositoryVersion2210, RepositoryType.STANDARD, Collections.singleton("ZOOKEEPER"));
 
     List<Grouping> groupings = upgrade.getGroups(Direction.UPGRADE);
     assertEquals(8, groupings.size());
@@ -404,9 +408,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -454,12 +456,14 @@ public class UpgradeHelperTest {
     Host hostInMaintenanceMode = cluster.getHosts().iterator().next();
     hostInMaintenanceMode.setMaintenanceState(cluster.getClusterId(), MaintenanceState.ON);
 
+    UpgradeContext context = getMockUpgradeContextNoReplay(cluster, Direction.UPGRADE,
+        UpgradeType.ROLLING, repositoryVersion2210);
+
     // use a "real" master host resolver here so that we can actually test MM
-    MasterHostResolver masterHostResolver = new MasterHostResolver(null, cluster, "");
+    MasterHostResolver masterHostResolver = new MasterHostResolver(null, context);
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(masterHostResolver);
+    EasyMock.expect(context.getResolver()).andReturn(masterHostResolver).anyTimes();
+    replay(context);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
     assertEquals(7, groups.size());
@@ -489,9 +493,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -539,9 +541,7 @@ public class UpgradeHelperTest {
     assertEquals(1, schs.size());
     assertEquals(HostState.HEARTBEAT_LOST, schs.get(0).getHostState());
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -577,9 +577,8 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.DOWNGRADE, DOWNGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.DOWNGRADE,
+        UpgradeType.ROLLING, repositoryVersion2200);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -618,9 +617,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -648,11 +645,7 @@ public class UpgradeHelperTest {
     assertNotNull(upgrade);
 
     Cluster cluster = makeCluster();
-
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
-
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
     assertEquals(7, groups.size());
@@ -678,9 +671,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -750,9 +741,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade,
         context);
@@ -862,9 +851,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade,
         context);
@@ -925,9 +912,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade,
         context);
@@ -992,9 +977,7 @@ public class UpgradeHelperTest {
     assertNotNull(upgrade);
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -1066,9 +1049,7 @@ public class UpgradeHelperTest {
       numServiceChecksExpected++;
     }
 
-    UpgradeContext context = m_upgradeContextFactory.create(c, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(c, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -1119,9 +1100,8 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.DOWNGRADE, DOWNGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.DOWNGRADE,
+        UpgradeType.ROLLING, repositoryVersion2200);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -1155,9 +1135,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -1248,7 +1226,6 @@ public class UpgradeHelperTest {
 
     String repositoryVersionString = "2.1.1-1234";
     StackId stackId = new StackId("HDP-2.1.1");
-    StackId stackId2 = new StackId("HDP-2.2.0");
 
     clusters.addCluster(clusterName, stackId);
     Cluster c = clusters.getCluster(clusterName);
@@ -1256,9 +1233,9 @@ public class UpgradeHelperTest {
     RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(stackId,
         repositoryVersionString);
 
-    helper.getOrCreateRepositoryVersion(stackId2,"2.2.0");
+    helper.getOrCreateRepositoryVersion(STACK_ID_HDP_220, "2.2.0");
 
-    helper.getOrCreateRepositoryVersion(stackId2, UPGRADE_VERSION);
+    helper.getOrCreateRepositoryVersion(STACK_ID_HDP_220, UPGRADE_VERSION);
 
     for (int i = 0; i < 4; i++) {
       String hostName = "h" + (i+1);
@@ -1420,9 +1397,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -1516,9 +1491,8 @@ public class UpgradeHelperTest {
     expect(m_masterHostResolver.getCluster()).andReturn(c).anyTimes();
     replay(m_masterHostResolver);
 
-    UpgradeContext context = m_upgradeContextFactory.create(c, UpgradeType.ROLLING,
-        Direction.DOWNGRADE, DOWNGRADE_VERSION, new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(c, Direction.DOWNGRADE, UpgradeType.ROLLING,
+        repositoryVersion2200);
 
     Map<String, UpgradePack> upgrades = ambariMetaInfo.getUpgradePacks("HDP", "2.1.1");
     assertTrue(upgrades.containsKey("upgrade_direction"));
@@ -1556,7 +1530,7 @@ public class UpgradeHelperTest {
     clusters.addCluster(clusterName, stackId);
     Cluster c = clusters.getCluster(clusterName);
 
-    RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(stackId,
+    RepositoryVersionEntity repositoryVersion211 = helper.getOrCreateRepositoryVersion(stackId,
         version);
 
     for (int i = 0; i < 2; i++) {
@@ -1574,28 +1548,34 @@ public class UpgradeHelperTest {
     }
 
     // !!! add services
-    c.addService(serviceFactory.createNew(c, "ZOOKEEPER", repositoryVersion));
+    c.addService(serviceFactory.createNew(c, "ZOOKEEPER", repositoryVersion211));
 
     Service s = c.getService("ZOOKEEPER");
     ServiceComponent sc = s.addServiceComponent("ZOOKEEPER_SERVER");
 
     ServiceComponentHost sch1 = sc.addServiceComponentHost("h1");
-    sch1.setVersion("2.1.1.0-1234");
+    sch1.setVersion(repositoryVersion211.getVersion());
 
     ServiceComponentHost sch2 = sc.addServiceComponentHost("h2");
-    sch2.setVersion("2.1.1.0-1234");
+    sch2.setVersion(repositoryVersion211.getVersion());
 
     List<ServiceComponentHost> schs = c.getServiceComponentHosts("ZOOKEEPER", "ZOOKEEPER_SERVER");
     assertEquals(2, schs.size());
-    MasterHostResolver mhr = new MasterHostResolver(null, c, "2.1.1.0-1234");
 
-    HostsType ht = mhr.getMasterAndHosts("ZOOKEEPER", "ZOOKEEPER_SERVER");
+    UpgradeContext context = getMockUpgradeContextNoReplay(c, Direction.UPGRADE,
+        UpgradeType.HOST_ORDERED, repositoryVersion211);
+
+    MasterHostResolver resolver = new MasterHostResolver(m_configHelper, context);
+    EasyMock.expect(context.getResolver()).andReturn(resolver).anyTimes();
+    replay(context);
+
+    HostsType ht = resolver.getMasterAndHosts("ZOOKEEPER", "ZOOKEEPER_SERVER");
     assertEquals(0, ht.hosts.size());
 
     // !!! if one of them is failed, it should be scheduled
     sch2.setUpgradeState(UpgradeState.FAILED);
 
-    ht = mhr.getMasterAndHosts("ZOOKEEPER", "ZOOKEEPER_SERVER");
+    ht = resolver.getMasterAndHosts("ZOOKEEPER", "ZOOKEEPER_SERVER");
 
     assertEquals(1, ht.hosts.size());
     assertEquals("h2", ht.hosts.iterator().next());
@@ -1617,7 +1597,7 @@ public class UpgradeHelperTest {
     clusters.addCluster(clusterName, stackId);
     Cluster c = clusters.getCluster(clusterName);
 
-    RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(stackId,
+    RepositoryVersionEntity repositoryVersion211 = helper.getOrCreateRepositoryVersion(stackId,
         version);
 
     for (int i = 0; i < 2; i++) {
@@ -1635,7 +1615,7 @@ public class UpgradeHelperTest {
     }
 
     // Add services
-    c.addService(serviceFactory.createNew(c, "HDFS", repositoryVersion));
+    c.addService(serviceFactory.createNew(c, "HDFS", repositoryVersion211));
 
     Service s = c.getService("HDFS");
     ServiceComponent sc = s.addServiceComponent("NAMENODE");
@@ -1655,7 +1635,15 @@ public class UpgradeHelperTest {
     expect(m_configHelper.getValueFromDesiredConfigurations(c, "hdfs-site", "dfs.namenode.http-address.ha.nn2")).andReturn("H2:50070").anyTimes();
     replay(m_configHelper);
 
-    MasterHostResolver mhr = new MockMasterHostResolver(m_configHelper, c, version);
+    UpgradeContext context = getMockUpgradeContextNoReplay(c, Direction.UPGRADE,
+        UpgradeType.NON_ROLLING, repositoryVersion211);
+
+    // use a "real" master host resolver here so that we can actually test MM
+    MasterHostResolver mhr = new MockMasterHostResolver(m_configHelper, context);
+
+    EasyMock.expect(context.getResolver()).andReturn(mhr).anyTimes();
+    replay(context);
+
 
     HostsType ht = mhr.getMasterAndHosts("HDFS", "NAMENODE");
     assertNotNull(ht.master);
@@ -1679,8 +1667,7 @@ public class UpgradeHelperTest {
     clusters.addCluster(clusterName, stackId);
     Cluster c = clusters.getCluster(clusterName);
 
-    RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(stackId,
-        version);
+    RepositoryVersionEntity repositoryVersion211 = helper.getOrCreateRepositoryVersion(stackId, version);
 
     for (int i = 0; i < 2; i++) {
       String hostName = "h" + (i+1);
@@ -1697,7 +1684,7 @@ public class UpgradeHelperTest {
     }
 
     // Add services
-    c.addService(serviceFactory.createNew(c, "HDFS", repositoryVersion));
+    c.addService(serviceFactory.createNew(c, "HDFS", repositoryVersion211));
 
     Service s = c.getService("HDFS");
     ServiceComponent sc = s.addServiceComponent("NAMENODE");
@@ -1717,7 +1704,14 @@ public class UpgradeHelperTest {
     expect(m_configHelper.getValueFromDesiredConfigurations(c, "hdfs-site", "dfs.namenode.http-address.ha.nn2")).andReturn("H2:50070").anyTimes();
     replay(m_configHelper);
 
-    MasterHostResolver mhr = new BadMasterHostResolver(m_configHelper, c, version);
+    UpgradeContext context = getMockUpgradeContextNoReplay(c, Direction.UPGRADE,
+        UpgradeType.NON_ROLLING, repositoryVersion211);
+
+    // use a "real" master host resolver here so that we can actually test MM
+    MasterHostResolver mhr = new BadMasterHostResolver(m_configHelper, context);
+
+    EasyMock.expect(context.getResolver()).andReturn(mhr).anyTimes();
+    replay(context);
 
     HostsType ht = mhr.getMasterAndHosts("HDFS", "NAMENODE");
     assertNotNull(ht.master);
@@ -1754,13 +1748,8 @@ public class UpgradeHelperTest {
     assertEquals(upgradeType, upgradePack.getType());
 
     // get an upgrade
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-
-    context.setResolver(m_masterHostResolver);
-
-    context.setSupportedServices(Collections.singleton("ZOOKEEPER"));
-    context.setScope(UpgradeScope.COMPLETE);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING,
+        repositoryVersion2210, RepositoryType.STANDARD, Collections.singleton("ZOOKEEPER"));
 
     List<Grouping> groupings = upgradePack.getGroups(Direction.UPGRADE);
     assertEquals(2, groupings.size());
@@ -1795,10 +1784,10 @@ public class UpgradeHelperTest {
     clusters.addCluster(clusterName, stackId);
     Cluster c = clusters.getCluster(clusterName);
 
-    RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(stackId,
+    RepositoryVersionEntity repoVersion211 = helper.getOrCreateRepositoryVersion(stackId,
         version);
 
-    helper.getOrCreateRepositoryVersion(stackId2,"2.2.0");
+    RepositoryVersionEntity repoVersion220 = helper.getOrCreateRepositoryVersion(stackId2, "2.2.0");
 
     for (int i = 0; i < 2; i++) {
       String hostName = "h" + (i+1);
@@ -1815,7 +1804,7 @@ public class UpgradeHelperTest {
     }
 
     // !!! add storm
-    c.addService(serviceFactory.createNew(c, "STORM", repositoryVersion));
+    c.addService(serviceFactory.createNew(c, "STORM", repoVersion211));
 
     Service s = c.getService("STORM");
     ServiceComponent sc = s.addServiceComponent("NIMBUS");
@@ -1853,23 +1842,30 @@ public class UpgradeHelperTest {
 
     };
 
-    MasterHostResolver resolver = new MasterHostResolver(m_configHelper, c);
+    UpgradeContext context = getMockUpgradeContextNoReplay(c, Direction.UPGRADE,
+        UpgradeType.NON_ROLLING, repoVersion220);
 
-    UpgradeContext context = m_upgradeContextFactory.create(c, UpgradeType.NON_ROLLING,
-        Direction.UPGRADE, "2.2.0", new HashMap<String, Object>());
-    context.setResolver(resolver);
+    // use a "real" master host resolver here so that we can actually test MM
+    MasterHostResolver masterHostResolver = new MasterHostResolver(m_configHelper, context);
+
+    EasyMock.expect(context.getResolver()).andReturn(masterHostResolver).anyTimes();
+    replay(context);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgradePack, context);
 
     assertEquals(1, groups.size());
 
-    sch1.setVersion("2.1.1");
-    sch2.setVersion("2.1.1");
-    resolver = new MasterHostResolver(m_configHelper, c, "2.1.1");
+    sch1.setVersion(repoVersion211.getVersion());
+    sch2.setVersion(repoVersion211.getVersion());
+
+    context = getMockUpgradeContextNoReplay(c, Direction.DOWNGRADE, UpgradeType.NON_ROLLING,
+        repoVersion211);
 
-    context = m_upgradeContextFactory.create(c, UpgradeType.NON_ROLLING, Direction.DOWNGRADE,
-        "2.1.1", new HashMap<String, Object>());
-    context.setResolver(resolver);
+    // use a "real" master host resolver here so that we can actually test MM
+    masterHostResolver = new MasterHostResolver(m_configHelper, context);
+
+    EasyMock.expect(context.getResolver()).andReturn(masterHostResolver).anyTimes();
+    replay(context);
 
     groups = m_upgradeHelper.createSequence(upgradePack, context);
 
@@ -1895,7 +1891,7 @@ public class UpgradeHelperTest {
     RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(stackId,
         version);
 
-    helper.getOrCreateRepositoryVersion(stackId2,"2.2.0");
+    RepositoryVersionEntity repoVersion220 = helper.getOrCreateRepositoryVersion(stackId2, "2.2.0");
 
     helper.getOrCreateRepositoryVersion(stackId2, UPGRADE_VERSION);
 
@@ -1949,9 +1945,8 @@ public class UpgradeHelperTest {
     UpgradePack upgrade = upgrades.get("upgrade_multi_server_tasks");
     assertNotNull(upgrade);
 
-    UpgradeContext context = m_upgradeContextFactory.create(c, UpgradeType.NON_ROLLING,
-        Direction.UPGRADE, "2.2.0", new HashMap<String, Object>());
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(c, Direction.UPGRADE, UpgradeType.NON_ROLLING,
+        repoVersion220);
 
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
 
@@ -2078,9 +2073,9 @@ public class UpgradeHelperTest {
     clusters.addCluster(clusterName, stackId);
     Cluster c = clusters.getCluster(clusterName);
 
-    RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(stackId, version);
+    RepositoryVersionEntity repoVersion211 = helper.getOrCreateRepositoryVersion(stackId, version);
 
-    helper.getOrCreateRepositoryVersion(stackId2, "2.2.0");
+    RepositoryVersionEntity repoVersion220 = helper.getOrCreateRepositoryVersion(stackId2, "2.2.0");
 
     // create 2 hosts
     for (int i = 0; i < 2; i++) {
@@ -2099,8 +2094,8 @@ public class UpgradeHelperTest {
 
     // add ZK Server to both hosts, and then Nimbus to only 1 - this will test
     // how the HOU breaks out dependencies into stages
-    c.addService(serviceFactory.createNew(c, "ZOOKEEPER", repositoryVersion));
-    c.addService(serviceFactory.createNew(c, "HBASE", repositoryVersion));
+    c.addService(serviceFactory.createNew(c, "ZOOKEEPER", repoVersion211));
+    c.addService(serviceFactory.createNew(c, "HBASE", repoVersion211));
     Service zookeeper = c.getService("ZOOKEEPER");
     Service hbase = c.getService("HBASE");
     ServiceComponent zookeeperServer = zookeeper.addServiceComponent("ZOOKEEPER_SERVER");
@@ -2131,12 +2126,14 @@ public class UpgradeHelperTest {
     field.setAccessible(true);
     field.set(upgradePack, UpgradeType.HOST_ORDERED);
 
-    MasterHostResolver resolver = new MasterHostResolver(m_configHelper, c);
+    UpgradeContext context = getMockUpgradeContextNoReplay(c, Direction.UPGRADE,
+        UpgradeType.HOST_ORDERED, repoVersion220);
+
+    MasterHostResolver resolver = new MasterHostResolver(m_configHelper, context);
+    EasyMock.expect(context.getResolver()).andReturn(resolver).anyTimes();
+    replay(context);
 
-    UpgradeContext context = m_upgradeContextFactory.create(c, UpgradeType.HOST_ORDERED,
-        Direction.UPGRADE, "2.2.0", new HashMap<String, Object>());
 
-    context.setResolver(resolver);
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgradePack, context);
 
     assertEquals(1, groups.size());
@@ -2169,30 +2166,34 @@ public class UpgradeHelperTest {
     assertEquals(StageWrapper.Type.SERVICE_CHECK, holder.items.get(8).getType());
 
     // !!! test downgrade when all host components have failed
-    zookeeperServer1.setVersion("2.1.1");
-    zookeeperServer2.setVersion("2.1.1");
-    hbaseMaster1.setVersion("2.1.1");
-    resolver = new MasterHostResolver(m_configHelper, c, "2.1.1");
+    zookeeperServer1.setVersion(repoVersion211.getVersion());
+    zookeeperServer2.setVersion(repoVersion211.getVersion());
+    hbaseMaster1.setVersion(repoVersion211.getVersion());
 
-    m_upgradeContextFactory.create(c, UpgradeType.HOST_ORDERED, Direction.DOWNGRADE,
-        "2.1.1", new HashMap<String, Object>());
+    context = getMockUpgradeContextNoReplay(c, Direction.DOWNGRADE, UpgradeType.HOST_ORDERED,
+        repoVersion211);
+
+    resolver = new MasterHostResolver(m_configHelper, context);
+    EasyMock.expect(context.getResolver()).andReturn(resolver).anyTimes();
+    replay(context);
 
-    context.setResolver(resolver);
     groups = m_upgradeHelper.createSequence(upgradePack, context);
 
     assertEquals(1, groups.size());
     assertEquals(2, groups.get(0).items.size());
 
     // !!! test downgrade when one of the hosts had failed
-    zookeeperServer1.setVersion("2.1.1");
-    zookeeperServer2.setVersion("2.2.0");
-    hbaseMaster1.setVersion("2.1.1");
-    resolver = new MasterHostResolver(m_configHelper, c, "2.1.1");
+    zookeeperServer1.setVersion(repoVersion211.getVersion());
+    zookeeperServer2.setVersion(repoVersion220.getVersion());
+    hbaseMaster1.setVersion(repoVersion211.getVersion());
+
+    context = getMockUpgradeContextNoReplay(c, Direction.DOWNGRADE, UpgradeType.HOST_ORDERED,
+        repoVersion211);
 
-    m_upgradeContextFactory.create(c, UpgradeType.HOST_ORDERED, Direction.DOWNGRADE,
-        "2.1.1", new HashMap<String, Object>());
+    resolver = new MasterHostResolver(m_configHelper, context);
+    EasyMock.expect(context.getResolver()).andReturn(resolver).anyTimes();
+    replay(context);
 
-    context.setResolver(resolver);
     groups = m_upgradeHelper.createSequence(upgradePack, context);
 
     assertEquals(1, groups.size());
@@ -2214,10 +2215,7 @@ public class UpgradeHelperTest {
 
     Cluster cluster = makeCluster();
 
-    UpgradeContext context = m_upgradeContextFactory.create(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, UPGRADE_VERSION, new HashMap<String, Object>());
-
-    context.setResolver(m_masterHostResolver);
+    UpgradeContext context = getMockUpgradeContext(cluster, Direction.UPGRADE, UpgradeType.ROLLING);
 
     // initially, no conditions should be met
     List<UpgradeGroupHolder> groups = m_upgradeHelper.createSequence(upgrade, context);
@@ -2251,13 +2249,177 @@ public class UpgradeHelperTest {
   }
 
   /**
+   * @param cluster
+   * @param direction
+   * @param type
+   * @return
+   */
+  private UpgradeContext getMockUpgradeContext(Cluster cluster, Direction direction, UpgradeType type){
+    return getMockUpgradeContext(cluster, direction, type, repositoryVersion2210);
+  }
+
+  /**
+   * @param cluster
+   * @param direction
+   * @param type
+   * @return
+   */
+  private UpgradeContext getMockUpgradeContext(Cluster cluster, Direction direction,
+      UpgradeType type, RepositoryVersionEntity repositoryVersion) {
+    Set<String> allServices = cluster.getServices().keySet();
+    return getMockUpgradeContext(cluster, direction, type, repositoryVersion,
+        RepositoryType.STANDARD, allServices);
+  }
+
+  /**
+   * @param cluster
+   * @param direction
+   * @param type
+   * @return
+   */
+  private UpgradeContext getMockUpgradeContext(Cluster cluster, Direction direction,
+      UpgradeType type, RepositoryVersionEntity repositoryVersion, RepositoryType repositoryType,
+      Set<String> services) {
+    return getMockUpgradeContext(cluster, direction, type, repositoryVersion,
+        repositoryType, services, m_masterHostResolver);
+  }
+
+  /**
+   * @param cluster
+   * @param direction
+   * @param type
+   * @return
+   */
+  private UpgradeContext getMockUpgradeContextNoReplay(Cluster cluster, Direction direction,
+      UpgradeType type, RepositoryVersionEntity repositoryVersion) {
+    Set<String> allServices = cluster.getServices().keySet();
+
+    UpgradeContext context = EasyMock.createNiceMock(UpgradeContext.class);
+    EasyMock.expect(context.getCluster()).andReturn(cluster).anyTimes();
+    EasyMock.expect(context.getType()).andReturn(type).anyTimes();
+    EasyMock.expect(context.getDirection()).andReturn(direction).anyTimes();
+    EasyMock.expect(context.getRepositoryVersion()).andReturn(repositoryVersion).anyTimes();
+    EasyMock.expect(context.getSupportedServices()).andReturn(allServices).anyTimes();
+    EasyMock.expect(context.getRepositoryType()).andReturn(RepositoryType.STANDARD).anyTimes();
+    EasyMock.expect(context.isScoped(EasyMock.anyObject(UpgradeScope.class))).andReturn(true).anyTimes();
+    return context;
+  }
+
+  /**
+   * @param cluster
+   * @param direction
+   * @param type
+   * @param repositoryType
+   * @param services
+   * @return
+   */
+  private UpgradeContext getMockUpgradeContext(Cluster cluster, Direction direction,
+      UpgradeType type, RepositoryVersionEntity repositoryVersion, RepositoryType repositoryType,
+      Set<String> services, MasterHostResolver resolver) {
+    UpgradeContext context = EasyMock.createNiceMock(UpgradeContext.class);
+    EasyMock.expect(context.getCluster()).andReturn(cluster).anyTimes();
+    EasyMock.expect(context.getType()).andReturn(type).anyTimes();
+    EasyMock.expect(context.getDirection()).andReturn(direction).anyTimes();
+    EasyMock.expect(context.getRepositoryVersion()).andReturn(repositoryVersion).anyTimes();
+    EasyMock.expect(context.getSupportedServices()).andReturn(services).anyTimes();
+    EasyMock.expect(context.getRepositoryType()).andReturn(repositoryType).anyTimes();
+    EasyMock.expect(context.getResolver()).andReturn(resolver).anyTimes();
+    EasyMock.expect(context.isScoped(EasyMock.anyObject(UpgradeScope.class))).andReturn(true).anyTimes();
+    EasyMock.expect(context.getAmbariMetaInfo()).andReturn(ambariMetaInfo).anyTimes();
+
+    final Map<String, RepositoryVersionEntity> targetRepositoryVersions = new HashMap<>();
+    for( String serviceName : services ){
+      targetRepositoryVersions.put(serviceName, repositoryVersion);
+    }
+
+    final Capture<String> repoVersionServiceName = EasyMock.newCapture();
+    EasyMock.expect(
+        context.getTargetRepositoryVersion(EasyMock.capture(repoVersionServiceName))).andAnswer(
+            new IAnswer<RepositoryVersionEntity>() {
+              @Override
+              public RepositoryVersionEntity answer() {
+                return targetRepositoryVersions.get(repoVersionServiceName.getValue());
+              }
+            }).anyTimes();
+
+    final Capture<String> serviceNameSupported = EasyMock.newCapture();
+    EasyMock.expect(context.isServiceSupported(EasyMock.capture(serviceNameSupported))).andAnswer(
+        new IAnswer<Boolean>() {
+          @Override
+          public Boolean answer() {
+            return targetRepositoryVersions.containsKey(serviceNameSupported.getValue());
+          }
+        }).anyTimes();
+
+
+    final Map<String, String> serviceNames = new HashMap<>();
+
+
+    final Capture<String> serviceDisplayNameArg1 = EasyMock.newCapture();
+    final Capture<String> serviceDisplayNameArg2 = EasyMock.newCapture();
+
+    context.setServiceDisplay(EasyMock.capture(serviceDisplayNameArg1), EasyMock.capture(serviceDisplayNameArg2));
+    EasyMock.expectLastCall().andAnswer(
+        new IAnswer<Object>() {
+          @Override
+          public Object answer() {
+            serviceNames.put(serviceDisplayNameArg1.getValue(), serviceDisplayNameArg2.getValue());
+            return null;
+          }
+        }).anyTimes();
+
+
+    final Map<String, String> componentNames = new HashMap<>();
+    final Capture<String> componentDisplayNameArg1 = EasyMock.newCapture();
+    final Capture<String> componentDisplayNameArg2 = EasyMock.newCapture();
+    final Capture<String> componentDisplayNameArg3 = EasyMock.newCapture();
+
+    context.setComponentDisplay(EasyMock.capture(componentDisplayNameArg1),
+        EasyMock.capture(componentDisplayNameArg2), EasyMock.capture(componentDisplayNameArg3));
+
+    EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+      @Override
+      public Object answer() {
+        componentNames.put(
+            componentDisplayNameArg1.getValue() + ":" + componentDisplayNameArg2.getValue(),
+            componentDisplayNameArg3.getValue());
+        return null;
+      }
+    }).anyTimes();
+
+    final Capture<String> getServiceDisplayArgument1 = EasyMock.newCapture();
+    EasyMock.expect(
+        context.getServiceDisplay(EasyMock.capture(getServiceDisplayArgument1))).andAnswer(
+            new IAnswer<String>() {
+              @Override
+              public String answer() {
+                return serviceNames.get(getServiceDisplayArgument1.getValue());
+              }
+            }).anyTimes();
+
+    final Capture<String> getComponentDisplayArgument1 = EasyMock.newCapture();
+    final Capture<String> getComponentDisplayArgument2 = EasyMock.newCapture();
+    EasyMock.expect(context.getComponentDisplay(EasyMock.capture(getComponentDisplayArgument1),
+        EasyMock.capture(getComponentDisplayArgument2))).andAnswer(new IAnswer<String>() {
+          @Override
+          public String answer() {
+            return componentNames.get(getComponentDisplayArgument1.getValue() + ":"
+                + getComponentDisplayArgument2.getValue());
+          }
+        }).anyTimes();
+
+    replay(context);
+    return context;
+  }
+
+  /**
    * Extend {@link org.apache.ambari.server.stack.MasterHostResolver} in order
    * to overwrite the JMX methods.
    */
   private class MockMasterHostResolver extends MasterHostResolver {
 
-    public MockMasterHostResolver(ConfigHelper configHelper, Cluster cluster, String version) {
-      super(configHelper, cluster, version);
+    public MockMasterHostResolver(ConfigHelper configHelper, UpgradeContext context) {
+      super(configHelper, context);
     }
 
     /**
@@ -2299,8 +2461,8 @@ public class UpgradeHelperTest {
 
   private static class BadMasterHostResolver extends MasterHostResolver {
 
-    public BadMasterHostResolver(ConfigHelper configHelper, Cluster cluster, String version) {
-      super(configHelper, cluster, version);
+    public BadMasterHostResolver(ConfigHelper configHelper, UpgradeContext context) {
+      super(configHelper, context);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/state/services/RetryUpgradeActionServiceTest.java
----------------------------------------------------------------------
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 83a8945..f996aac 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
@@ -286,8 +286,7 @@ public class RetryUpgradeActionServiceTest {
     upgrade.setUpgradePackage("some-name");
     upgrade.setUpgradeType(UpgradeType.ROLLING);
     upgrade.setDirection(Direction.UPGRADE);
-    upgrade.setFromVersion("2.2.0.0");
-    upgrade.setToVersion("2.2.0.1");
+    upgrade.setRepositoryVersion(repoVersionEntity);
     upgradeDAO.create(upgrade);
 
     cluster.setUpgradeEntity(upgrade);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java
index 0eef638..09fc5cd 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/stack/upgrade/StageWrapperBuilderTest.java
@@ -19,7 +19,6 @@ package org.apache.ambari.server.state.stack.upgrade;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -52,8 +51,6 @@ public class StageWrapperBuilderTest extends EasyMockSupport {
   @Test
   public void testBuildOrder() throws Exception {
     Cluster cluster = createNiceMock(Cluster.class);
-    EasyMock.expect(cluster.getCurrentStackVersion()).andReturn(HDP_21).atLeastOnce();
-    EasyMock.expect(cluster.getDesiredStackVersion()).andReturn(HDP_21).anyTimes();
 
     RepositoryVersionEntity repoVersionEntity = createNiceMock(RepositoryVersionEntity.class);
     EasyMock.expect(repoVersionEntity.getStackId()).andReturn(HDP_21).anyTimes();
@@ -62,10 +59,15 @@ public class StageWrapperBuilderTest extends EasyMockSupport {
     EasyMock.expect(repoVersionDAO.findByStackNameAndVersion(EasyMock.anyString(),
         EasyMock.anyString())).andReturn(repoVersionEntity).anyTimes();
 
-    replayAll();
+    UpgradeContext upgradeContext = EasyMock.createNiceMock(UpgradeContext.class);
+    EasyMock.expect(upgradeContext.getCluster()).andReturn(cluster).anyTimes();
+    EasyMock.expect(upgradeContext.getType()).andReturn(UpgradeType.ROLLING).anyTimes();
+    EasyMock.expect(upgradeContext.getDirection()).andReturn(Direction.UPGRADE).anyTimes();
+    EasyMock.expect(upgradeContext.getRepositoryVersion()).andReturn(repoVersionEntity).anyTimes();
+    EasyMock.expect(upgradeContext.isComponentFailureAutoSkipped()).andReturn(false).anyTimes();
+    EasyMock.expect(upgradeContext.isServiceCheckFailureAutoSkipped()).andReturn(false).anyTimes();
 
-    UpgradeContext upgradeContext = new UpgradeContext(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, HDP_21.toString(), new HashMap<String, Object>(), repoVersionDAO);
+    replayAll();
 
     MockStageWrapperBuilder builder = new MockStageWrapperBuilder(null);
     List<StageWrapper> stageWrappers = builder.build(upgradeContext);
@@ -90,8 +92,6 @@ public class StageWrapperBuilderTest extends EasyMockSupport {
   @Test
   public void testAutoSkipCheckInserted() throws Exception {
     Cluster cluster = createNiceMock(Cluster.class);
-    EasyMock.expect(cluster.getCurrentStackVersion()).andReturn(HDP_21).atLeastOnce();
-    EasyMock.expect(cluster.getDesiredStackVersion()).andReturn(HDP_21).anyTimes();
 
     RepositoryVersionEntity repoVersionEntity = createNiceMock(RepositoryVersionEntity.class);
     EasyMock.expect(repoVersionEntity.getStackId()).andReturn(HDP_21).anyTimes();
@@ -100,13 +100,15 @@ public class StageWrapperBuilderTest extends EasyMockSupport {
     EasyMock.expect(repoVersionDAO.findByStackNameAndVersion(EasyMock.anyString(),
         EasyMock.anyString())).andReturn(repoVersionEntity).anyTimes();
 
-    replayAll();
+    UpgradeContext upgradeContext = EasyMock.createNiceMock(UpgradeContext.class);
+    EasyMock.expect(upgradeContext.getCluster()).andReturn(cluster).anyTimes();
+    EasyMock.expect(upgradeContext.getType()).andReturn(UpgradeType.ROLLING).anyTimes();
+    EasyMock.expect(upgradeContext.getDirection()).andReturn(Direction.UPGRADE).anyTimes();
+    EasyMock.expect(upgradeContext.getRepositoryVersion()).andReturn(repoVersionEntity).anyTimes();
+    EasyMock.expect(upgradeContext.isComponentFailureAutoSkipped()).andReturn(true).anyTimes();
+    EasyMock.expect(upgradeContext.isServiceCheckFailureAutoSkipped()).andReturn(true).anyTimes();
 
-    UpgradeContext upgradeContext = new UpgradeContext(cluster, UpgradeType.ROLLING,
-        Direction.UPGRADE, HDP_21.toString(), new HashMap<String, Object>(), repoVersionDAO);
-
-    upgradeContext.setAutoSkipComponentFailures(true);
-    upgradeContext.setAutoSkipServiceCheckFailures(true);
+    replayAll();
 
     Grouping grouping = new Grouping();
     grouping.skippable = true;


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

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
index e5e2de3..42d2a98 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeEntity.java
@@ -17,6 +17,7 @@
  */
 package org.apache.ambari.server.orm.entities;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.persistence.CascadeType;
@@ -39,6 +40,8 @@ import javax.persistence.TableGenerator;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.hadoop.metrics2.sink.relocated.google.common.base.Objects;
 
 /**
  * Models the data representation of an upgrade
@@ -60,7 +63,7 @@ import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
   @NamedQuery(name = "UpgradeEntity.findUpgrade",
       query = "SELECT u FROM UpgradeEntity u WHERE u.upgradeId = :upgradeId"),
   @NamedQuery(name = "UpgradeEntity.findUpgradeByRequestId",
-      query = "SELECT u FROM UpgradeEntity u WHERE u.requestId = :requestId"),  
+      query = "SELECT u FROM UpgradeEntity u WHERE u.requestId = :requestId"),
   @NamedQuery(name = "UpgradeEntity.findLatestForClusterInDirection",
       query = "SELECT u FROM UpgradeEntity u JOIN RequestEntity r ON u.requestId = r.requestId WHERE u.clusterId = :clusterId AND u.direction = :direction ORDER BY r.startTime DESC, u.upgradeId DESC"),
   @NamedQuery(name = "UpgradeEntity.findLatestForCluster",
@@ -91,12 +94,6 @@ public class UpgradeEntity {
   @JoinColumn(name = "request_id", nullable = false, insertable = true, updatable = false)
   private RequestEntity requestEntity = null;
 
-  @Column(name="from_version", nullable = false)
-  private String fromVersion = null;
-
-  @Column(name="to_version", nullable = false)
-  private String toVersion = null;
-
   @Column(name="direction", nullable = false)
   @Enumerated(value = EnumType.STRING)
   private Direction direction = Direction.UPGRADE;
@@ -108,6 +105,9 @@ public class UpgradeEntity {
   @Enumerated(value = EnumType.STRING)
   private UpgradeType upgradeType;
 
+  @JoinColumn(name = "repo_version_id", referencedColumnName = "repo_version_id", nullable = false)
+  private RepositoryVersionEntity repositoryVersion;
+
   @Column(name = "skip_failures", nullable = false)
   private Integer skipFailures = 0;
 
@@ -127,6 +127,14 @@ public class UpgradeEntity {
   private List<UpgradeGroupEntity> upgradeGroupEntities;
 
   /**
+   * Uni-directional relationship between an upgrade an all of the components in
+   * that upgrade.
+   */
+  @OneToMany(orphanRemoval=true, cascade = { CascadeType.ALL })
+  @JoinColumn(name = "upgrade_id")
+  private List<UpgradeHistoryEntity> upgradeHistory;
+
+  /**
    * @return the id
    */
   public Long getId() {
@@ -184,34 +192,6 @@ public class UpgradeEntity {
   }
 
   /**
-   * @return the "from" version
-   */
-  public String getFromVersion() {
-    return fromVersion;
-  }
-
-  /**
-   * @param version the "from" version
-   */
-  public void setFromVersion(String version) {
-    fromVersion = version;
-  }
-
-  /**
-   * @return the "to" version
-   */
-  public String getToVersion() {
-    return toVersion;
-  }
-
-  /**
-   * @param version the "to" version
-   */
-  public void setToVersion(String version) {
-    toVersion = version;
-  }
-
-  /**
    * @return the direction of the upgrade
    */
   public Direction getDirection() {
@@ -333,60 +313,95 @@ public class UpgradeEntity {
     this.suspended = suspended ? (short) 1 : (short) 0;
   }
 
+  /**
+   * Adds a historical entry for a service component in this upgrade.
+   *
+   * @param historicalEntry
+   *          the entry to add.
+   */
+  public void addHistory(UpgradeHistoryEntity historicalEntry) {
+    if (null == upgradeHistory) {
+      upgradeHistory = new ArrayList<>();
+    }
+
+    upgradeHistory.add(historicalEntry);
+  }
+
+  /**
+   * Gets the history of this component's upgrades and downgrades.
+   *
+   * @return the component history, or {@code null} if none.
+   */
+  public List<UpgradeHistoryEntity> getHistory() {
+    return upgradeHistory;
+  }
+
+  /**
+   * Upgrades will always have a single version being upgraded to and downgrades
+   * will have a single version being downgraded from. This repository
+   * represents that version.
+   * <p/>
+   * When the direction is {@link Direction#UPGRADE}, this represents the target
+   * repository. <br/>
+   * When the direction is {@link Direction#DOWNGRADE}, this represents the
+   * repository being downgraded from.
+   *
+   * @return the repository version being upgraded to or downgraded from (never
+   *         {@code null}).
+   */
+  public RepositoryVersionEntity getRepositoryVersion() {
+    return repositoryVersion;
+  }
+
+  /**
+   * Sets the repository version for this upgrade. This value will change
+   * depending on the direction of the upgrade.
+   * <p/>
+   * When the direction is {@link Direction#UPGRADE}, this represents the target
+   * repository. <br/>
+   * When the direction is {@link Direction#DOWNGRADE}, this represents the
+   * repository being downgraded from.
+   *
+   * @param repositoryVersion
+   *          the repository version being upgraded to or downgraded from (not
+   *          {@code null}).
+   */
+  public void setRepositoryVersion(RepositoryVersionEntity repositoryVersion) {
+    this.repositoryVersion = repositoryVersion;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public boolean equals(Object o) {
     if (this == o) {
       return true;
     }
+
     if (o == null || getClass() != o.getClass()) {
       return false;
     }
 
     UpgradeEntity that = (UpgradeEntity) o;
-
-    if (upgradeId != null ? !upgradeId.equals(that.upgradeId) : that.upgradeId != null) {
-      return false;
-    }
-    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) {
-      return false;
-    }
-    if (requestId != null ? !requestId.equals(that.requestId) : that.requestId != null) {
-      return false;
-    }
-    if (fromVersion != null ? !fromVersion.equals(that.fromVersion) : that.fromVersion != null) {
-      return false;
-    }
-    if (toVersion != null ? !toVersion.equals(that.toVersion) : that.toVersion != null) {
-      return false;
-    }
-    if (direction != null ? !direction.equals(that.direction) : that.direction != null) {
-      return false;
-    }
-    if (suspended != null ? !suspended.equals(that.suspended) : that.suspended != null) {
-      return false;
-    }
-    if (upgradeType != null ? !upgradeType.equals(that.upgradeType) : that.upgradeType != null) {
-      return false;
-    }
-    if (upgradePackage != null ? !upgradePackage.equals(that.upgradePackage) : that.upgradePackage != null) {
-      return false;
-    }
-
-    return true;
+    return new EqualsBuilder()
+        .append(upgradeId, that.upgradeId)
+        .append(clusterId, that.clusterId)
+        .append(requestId, that.requestId)
+        .append(direction, that.direction)
+        .append(suspended, that.suspended)
+        .append(upgradeType, that.upgradeType)
+        .append(upgradePackage, that.upgradePackage)
+        .isEquals();
   }
 
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public int hashCode() {
-    int result = upgradeId != null ? upgradeId.hashCode() : 0;
-    result = 31 * result + (clusterId != null ? clusterId.hashCode() : 0);
-    result = 31 * result + (requestId != null ? requestId.hashCode() : 0);
-    result = 31 * result + (fromVersion != null ? fromVersion.hashCode() : 0);
-    result = 31 * result + (toVersion != null ? toVersion.hashCode() : 0);
-    result = 31 * result + (direction != null ? direction.hashCode() : 0);
-    result = 31 * result + (suspended != null ? suspended.hashCode() : 0);
-    result = 31 * result + (upgradeType != null ? upgradeType.hashCode() : 0);
-    result = 31 * result + (upgradePackage != null ? upgradePackage.hashCode() : 0);
-    return result;
+    return Objects.hashCode(upgradeId, clusterId, requestId, direction, suspended, upgradeType,
+        upgradePackage);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java
new file mode 100644
index 0000000..8bfafd3
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/UpgradeHistoryEntity.java
@@ -0,0 +1,232 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.orm.entities;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.hadoop.metrics2.sink.relocated.google.common.base.Objects;
+
+/**
+ * The {@link UpgradeHistoryEntity} represents the version history of components
+ * participating in an upgrade or a downgrade.
+ */
+@Entity
+@Table(
+    name = "upgrade_history",
+    uniqueConstraints = @UniqueConstraint(
+        columnNames = { "upgrade_id", "component_name", "service_name" }))
+@TableGenerator(
+    name = "upgrade_history_id_generator",
+    table = "ambari_sequences",
+    pkColumnName = "sequence_name",
+    valueColumnName = "sequence_value",
+    pkColumnValue = "upgrade_history_id_seq",
+    initialValue = 0)
+@NamedQueries({
+    @NamedQuery(
+        name = "UpgradeHistoryEntity.findAll",
+        query = "SELECT upgradeHistory FROM UpgradeHistoryEntity upgradeHistory"),
+    @NamedQuery(
+        name = "UpgradeHistoryEntity.findByUpgradeId",
+        query = "SELECT upgradeHistory FROM UpgradeHistoryEntity upgradeHistory WHERE upgradeHistory.upgradeId = :upgradeId")
+})
+public class UpgradeHistoryEntity {
+
+  @Id
+  @Column(name = "id", nullable = false, insertable = true, updatable = false)
+  @GeneratedValue(strategy = GenerationType.TABLE, generator = "upgrade_history_id_generator")
+  private Long id;
+
+  @Column(name = "upgrade_id", nullable = false, insertable = false, updatable = false)
+  private Long upgradeId;
+
+  @JoinColumn(name = "upgrade_id", nullable = false)
+  private UpgradeEntity upgrade;
+
+  @Column(name = "service_name", nullable = false, insertable = true, updatable = true)
+  private String serviceName;
+
+  @Column(name = "component_name", nullable = false, insertable = true, updatable = true)
+  private String componentName;
+
+  @ManyToOne
+  @JoinColumn(name = "from_repo_version_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private RepositoryVersionEntity fromRepositoryVersion = null;
+
+  @ManyToOne
+  @JoinColumn(name = "target_repo_version_id", unique = false, nullable = false, insertable = true, updatable = true)
+  private RepositoryVersionEntity targetRepositoryVersion = null;
+
+  /**
+   * @return the id
+   */
+  public Long getId() {
+    return id;
+  }
+
+  /**
+   * Gets the ID of the upgrade associated with this historical entry.
+   *
+   * @return the upgrade ID (never {@code null}).
+   */
+  public Long getUpgradeId() {
+    return upgradeId;
+  }
+
+  /**
+   * @return
+   */
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  /**
+   * @param serviceName
+   */
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  /**
+   * @return
+   */
+  public String getComponentName() {
+    return componentName;
+  }
+
+  /**
+   * @param componentName
+   */
+  public void setComponentName(String componentName) {
+    this.componentName = componentName;
+  }
+
+  /**
+   * Gets the repository that the upgrade is coming from.
+   *
+   * @return the repository that the upgrade is coming from (not {@code null}).
+   */
+  public RepositoryVersionEntity getFromReposistoryVersion() {
+    return fromRepositoryVersion;
+  }
+
+  /**
+   * Sets the repository that the services in the upgrade are CURRENT on.
+   *
+   * @param repositoryVersionEntity
+   *          the repository entity (not {@code null}).
+   */
+  public void setFromRepositoryVersion(RepositoryVersionEntity repositoryVersionEntity) {
+    fromRepositoryVersion = repositoryVersionEntity;
+  }
+
+  /**
+   * Gets the target repository version for this upgrade.
+   *
+   * @return the target repository for the services in the upgrade (not
+   *         {@code null}).
+   */
+  public RepositoryVersionEntity getTargetRepositoryVersion() {
+    return targetRepositoryVersion;
+  }
+
+  /**
+   * Gets the version of the target repository.
+   *
+   * @return the target version string (never {@code null}).
+   * @see #getTargetRepositoryVersion()
+   */
+  public String getTargetVersion() {
+    return targetRepositoryVersion.getVersion();
+  }
+
+  /**
+   * Sets the target repository of the upgrade.
+   *
+   * @param repositoryVersionEntity
+   *          the target repository (not {@code null}).
+   */
+  public void setTargetRepositoryVersion(RepositoryVersionEntity repositoryVersionEntity) {
+    targetRepositoryVersion = repositoryVersionEntity;
+  }
+
+  /**
+   * Sets the associated upgrade entity.
+   *
+   * @param upgrade
+   */
+  public void setUpgrade(UpgradeEntity upgrade) {
+    this.upgrade = upgrade;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    UpgradeHistoryEntity that = (UpgradeHistoryEntity) o;
+    return new EqualsBuilder()
+        .append(id, that.id)
+        .append(upgradeId, that.upgradeId)
+        .append(serviceName, that.serviceName)
+        .append(componentName, that.componentName)
+        .isEquals();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(id, upgradeId, serviceName, componentName);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString() {
+    return Objects.toStringHelper(this)
+        .add("id", id)
+        .add("upgradeId", upgradeId)
+        .add("serviceName", serviceName)
+        .add("componentName", componentName)
+        .add("from", fromRepositoryVersion)
+        .add("to", targetRepositoryVersion).toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java
index de0f282..4942f27 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/AbstractUpgradeServerAction.java
@@ -17,10 +17,6 @@
  */
 package org.apache.ambari.server.serveraction.upgrades;
 
-import java.util.Collections;
-import java.util.Set;
-
-import org.apache.ambari.server.controller.internal.UpgradeResourceProvider;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.serveraction.AbstractServerAction;
 import org.apache.ambari.server.state.Cluster;
@@ -28,11 +24,7 @@ import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.UpgradeContext;
 import org.apache.ambari.server.state.UpgradeContextFactory;
 import org.apache.ambari.server.state.UpgradeHelper;
-import org.apache.ambari.server.state.stack.upgrade.Direction;
-import org.apache.ambari.server.state.stack.upgrade.UpgradeScope;
-import org.apache.commons.lang.StringUtils;
 
-import com.google.common.collect.Sets;
 import com.google.inject.Inject;
 
 /**
@@ -42,25 +34,8 @@ public abstract class AbstractUpgradeServerAction extends AbstractServerAction {
 
   public static final String CLUSTER_NAME_KEY = UpgradeContext.COMMAND_PARAM_CLUSTER_NAME;
   public static final String UPGRADE_DIRECTION_KEY = UpgradeContext.COMMAND_PARAM_DIRECTION;
-  public static final String VERSION_KEY = UpgradeContext.COMMAND_PARAM_VERSION;
   protected static final String REQUEST_ID = UpgradeContext.COMMAND_PARAM_REQUEST_ID;
 
-  /**
-   * The original "current" stack of the cluster before the upgrade started.
-   * This is the same regardless of whether the current direction is
-   * {@link Direction#UPGRADE} or {@link Direction#DOWNGRADE}.
-   */
-  protected static final String ORIGINAL_STACK_KEY = UpgradeContext.COMMAND_PARAM_ORIGINAL_STACK;
-
-  /**
-   * The target upgrade stack before the upgrade started. This is the same
-   * regardless of whether the current direction is {@link Direction#UPGRADE} or
-   * {@link Direction#DOWNGRADE}.
-   */
-  protected static final String TARGET_STACK_KEY = UpgradeContext.COMMAND_PARAM_TARGET_STACK;
-
-  protected static final String SUPPORTED_SERVICES_KEY = UpgradeResourceProvider.COMMAND_PARAM_SUPPORTED_SERVICES;
-
   @Inject
   protected Clusters m_clusters;
 
@@ -83,22 +58,6 @@ public abstract class AbstractUpgradeServerAction extends AbstractServerAction {
   protected UpgradeContext getUpgradeContext(Cluster cluster) {
     UpgradeEntity upgrade = cluster.getUpgradeInProgress();
     UpgradeContext upgradeContext = m_upgradeContextFactory.create(cluster, upgrade);
-
-    final UpgradeScope scope;
-    final Set<String> supportedServices;
-    String services = getCommandParameterValue(SUPPORTED_SERVICES_KEY);
-    if (StringUtils.isBlank(services)) {
-      scope = UpgradeScope.COMPLETE;
-      supportedServices = Collections.emptySet();
-
-    } else {
-      scope = UpgradeScope.PARTIAL;
-      supportedServices = Sets.newHashSet(StringUtils.split(services, ','));
-    }
-
-    upgradeContext.setSupportedServices(supportedServices);
-    upgradeContext.setScope(scope);
-
     return upgradeContext;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java
index 4a3bd9b..dc7bc10 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckAction.java
@@ -18,7 +18,6 @@
 package org.apache.ambari.server.serveraction.upgrades;
 
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -54,7 +53,7 @@ public class ComponentVersionCheckAction extends FinalizeUpgradeAction {
     Cluster cluster = m_clusters.getCluster(clusterName);
 
     UpgradeContext upgradeContext = getUpgradeContext(cluster);
-    List<InfoTuple> errors = getHostComponentsWhichDidNotUpgrade(upgradeContext);
+    Set<InfoTuple> errors = validateComponentVersions(upgradeContext);
 
     StringBuilder outSB = new StringBuilder();
     StringBuilder errSB = new StringBuilder();
@@ -69,19 +68,21 @@ public class ComponentVersionCheckAction extends FinalizeUpgradeAction {
     }
   }
 
-  private String getErrors(StringBuilder outSB, StringBuilder errSB, List<InfoTuple> errors) {
+  private String getErrors(StringBuilder outSB, StringBuilder errSB, Set<InfoTuple> errors) {
 
-    errSB.append("The following components were found to have version mismatches.  ");
-    errSB.append("Finalize will not complete successfully:\n");
+    errSB.append("Finalization will not be able to completed because of the following version inconsistencies:");
 
     Set<String> hosts = new TreeSet<>();
     Map<String, JsonArray> hostDetails = new HashMap<>();
 
     for (InfoTuple tuple : errors) {
+      errSB.append("  ");
       errSB.append(tuple.hostName).append(": ");
+      errSB.append(System.lineSeparator()).append("    ");
       errSB.append(tuple.serviceName).append('/').append(tuple.componentName);
       errSB.append(" reports ").append(StringUtils.trimToEmpty(tuple.currentVersion));
-      errSB.append('\n');
+      errSB.append(" but expects ").append(tuple.targetVersion);
+      errSB.append(System.lineSeparator());
 
       hosts.add(tuple.hostName);
 
@@ -93,6 +94,7 @@ public class ComponentVersionCheckAction extends FinalizeUpgradeAction {
       obj.addProperty("service", tuple.serviceName);
       obj.addProperty("component", tuple.componentName);
       obj.addProperty("version", tuple.currentVersion);
+      obj.addProperty("targetVersion", tuple.targetVersion);
 
       hostDetails.get(tuple.hostName).add(obj);
     }

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

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

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


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

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java
index bc178ea..4408492 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackUpgradeConfigurationMergeTest.java
@@ -156,6 +156,7 @@ public class StackUpgradeConfigurationMergeTest extends EasyMockSupport {
     RepositoryVersionEntity repositoryVersionEntity = createNiceMock(RepositoryVersionEntity.class);
     UpgradePack upgradePack = createNiceMock(UpgradePack.class);
     StackEntity targetStack = createNiceMock(StackEntity.class);
+    StackId targetStackId = createNiceMock(StackId.class);
 
     String version = "2.5.0.0-1234";
 
@@ -172,9 +173,12 @@ public class StackUpgradeConfigurationMergeTest extends EasyMockSupport {
 
     EasyMock.expect(targetStack.getStackName()).andReturn("HDP").anyTimes();
     EasyMock.expect(targetStack.getStackVersion()).andReturn("2.5").anyTimes();
+    EasyMock.expect(targetStackId.getStackName()).andReturn("HDP").atLeastOnce();
+    EasyMock.expect(targetStackId.getStackVersion()).andReturn("2.5").atLeastOnce();
 
-    EasyMock.expect(repositoryVersionEntity.getStack()).andReturn(targetStack);
-    EasyMock.expect(repositoryVersionEntity.getVersion()).andReturn(version);
+    EasyMock.expect(repositoryVersionEntity.getStackId()).andReturn(targetStackId).atLeastOnce();
+    EasyMock.expect(repositoryVersionEntity.getStack()).andReturn(targetStack).atLeastOnce();
+    EasyMock.expect(repositoryVersionEntity.getVersion()).andReturn(version).atLeastOnce();
     EasyMock.expect(repositoryVersionDAO.findByStackNameAndVersion("HDP", version)).andReturn(
         repositoryVersionEntity);
 
@@ -244,9 +248,8 @@ public class StackUpgradeConfigurationMergeTest extends EasyMockSupport {
     EasyMock.expect(upgradeContext.getCluster()).andReturn(cluster).anyTimes();
     EasyMock.expect(upgradeContext.getDirection()).andReturn(Direction.UPGRADE).anyTimes();
     EasyMock.expect(upgradeContext.getUpgradePack()).andReturn(upgradePack).anyTimes();
-    EasyMock.expect(upgradeContext.getTargetRepositoryVersion()).andReturn(repositoryVersionEntity).anyTimes();
-    EasyMock.expect(upgradeContext.getTargetStackId()).andReturn(new StackId("HDP-2.5")).anyTimes();
-    EasyMock.expect(upgradeContext.getVersion()).andReturn(version).anyTimes();
+    EasyMock.expect(upgradeContext.getRepositoryVersion()).andReturn(repositoryVersionEntity).anyTimes();
+    EasyMock.expect(upgradeContext.getTargetRepositoryVersion(EasyMock.anyString())).andReturn(repositoryVersionEntity).anyTimes();
     replayAll();
 
     UpgradeResourceProvider upgradeResourceProvider = new UpgradeResourceProvider(amc);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeResourceProviderTest.java
----------------------------------------------------------------------
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 e2d9cc6..3780ea5 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
@@ -291,7 +291,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.ROLLING.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_FAILURES, Boolean.TRUE.toString());
@@ -354,7 +354,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.ROLLING.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_MANUAL_VERIFICATION, Boolean.TRUE.toString());
@@ -398,7 +398,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.ROLLING.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_FAILURES, Boolean.TRUE.toString());
@@ -555,7 +555,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.1");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2111.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
@@ -606,7 +606,7 @@ public class UpgradeResourceProviderTest {
     // this should get skipped
     ServiceComponent component = service.getServiceComponent("ZOOKEEPER_SERVER");
     ServiceComponentHost sch = component.addServiceComponentHost("h2");
-    sch.setVersion("2.2.2.2");
+    sch.setVersion(repoVersionEntity2200.getVersion());
 
     // start out with 0 (sanity check)
     List<UpgradeEntity> upgrades = upgradeDao.findUpgrades(cluster.getClusterId());
@@ -623,8 +623,7 @@ public class UpgradeResourceProviderTest {
     UpgradeEntity upgradeEntity = new UpgradeEntity();
     upgradeEntity.setClusterId(cluster.getClusterId());
     upgradeEntity.setDirection(Direction.UPGRADE);
-    upgradeEntity.setFromVersion("2.1.1.1");
-    upgradeEntity.setToVersion("2.2.2.2");
+    upgradeEntity.setRepositoryVersion(repoVersionEntity2200);
     upgradeEntity.setUpgradePackage("upgrade_test");
     upgradeEntity.setUpgradeType(UpgradeType.ROLLING);
     upgradeEntity.setRequestEntity(requestEntity);
@@ -638,7 +637,6 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.1");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
@@ -672,7 +670,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.1");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2111.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
@@ -693,7 +691,7 @@ public class UpgradeResourceProviderTest {
     // create another upgrade which should fail
     requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, "9999");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
@@ -706,10 +704,8 @@ public class UpgradeResourceProviderTest {
 
     // fix the properties and try again
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_FROM_VERSION, "2.1.1.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
 
     Map<String, String> requestInfoProperties = new HashMap<>();
@@ -722,10 +718,15 @@ public class UpgradeResourceProviderTest {
 
     UpgradeEntity entity = upgradeDao.findUpgrade(Long.parseLong(id));
     assertNotNull(entity);
-    assertEquals("2.1.1.0", entity.getFromVersion());
-    assertEquals("2.2.0.0", entity.getToVersion());
     assertEquals(Direction.DOWNGRADE, entity.getDirection());
 
+    // associated version is the FROM on DOWNGRADE
+    assertEquals(repoVersionEntity2111.getVersion(), entity.getRepositoryVersion().getVersion());
+
+    // target is by service
+    assertEquals(repoVersionEntity2110.getVersion(),
+        entity.getHistory().iterator().next().getTargetVersion());
+
     StageDAO dao = injector.getInstance(StageDAO.class);
     List<StageEntity> stages = dao.findByRequestId(entity.getRequestId());
 
@@ -757,7 +758,7 @@ public class UpgradeResourceProviderTest {
     // create upgrade request
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_nonrolling_new_stack");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, "NON_ROLLING");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
@@ -797,14 +798,11 @@ public class UpgradeResourceProviderTest {
     abortUpgrade(upgrade.getRequestId());
 
     // create downgrade with one upgraded service
-    StackId stackId = new StackId("HDP", "2.2.0");
     service.setDesiredRepositoryVersion(repoVersionEntity2200);
 
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_nonrolling_new_stack");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_FROM_VERSION, "2.2.0.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
 
     Map<String, String> requestInfoProperties = new HashMap<>();
@@ -943,7 +941,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.2.3");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_direction");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
@@ -973,10 +971,8 @@ public class UpgradeResourceProviderTest {
     requestProps.clear();
     // Now perform a downgrade
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_direction");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_FROM_VERSION, "2.2.2.3");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
 
     request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), null);
@@ -1072,7 +1068,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
@@ -1201,10 +1197,7 @@ public class UpgradeResourceProviderTest {
     Map<String, UpgradePack> upgradePacks = ambariMetaInfo.getUpgradePacks("HDP", "2.1.1");
     UpgradePack upgrade = upgradePacks.get("upgrade_to_new_stack");
 
-    UpgradeContext upgradeContext = upgradeContextFactory.create(cluster, upgrade.getType(),
-        Direction.UPGRADE, "2.2.0.0", new HashMap<String, Object>());
-    upgradeContext.setUpgradePack(upgrade);
-
+    UpgradeContext upgradeContext = EasyMock.createNiceMock(UpgradeContext.class);
     upgradeResourceProvider.applyStackAndProcessConfigurations(upgradeContext);
 
     Map<String, Map<String, String>> expectedConfigurations = expectedConfigurationsCapture.getValue();
@@ -1248,7 +1241,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.1");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2111.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
@@ -1353,7 +1346,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_FAILURES, Boolean.TRUE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_SC_FAILURES, Boolean.FALSE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_REQUEST_ID, "" + entity.getRequestId());
@@ -1378,7 +1371,7 @@ public class UpgradeResourceProviderTest {
 
     requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_FAILURES, Boolean.FALSE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_SC_FAILURES, Boolean.TRUE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_REQUEST_ID, "" + entity.getRequestId());
@@ -1402,7 +1395,7 @@ public class UpgradeResourceProviderTest {
 
     requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_FAILURES, Boolean.FALSE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_SC_FAILURES, Boolean.FALSE.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_REQUEST_ID, "" + entity.getRequestId());
@@ -1428,7 +1421,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.ROLLING.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_MANUAL_VERIFICATION, Boolean.FALSE.toString());
@@ -1466,7 +1459,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test_host_ordered");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.HOST_ORDERED.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, Boolean.TRUE.toString());
@@ -1526,10 +1519,9 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_FROM_VERSION, "2.1.1.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());
 
     Map<String, String> requestInfoProperties = new HashMap<>();
@@ -1554,10 +1546,8 @@ public class UpgradeResourceProviderTest {
 
     requestProps.clear();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.1.1.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_FROM_VERSION, "2.2.0.0");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.DOWNGRADE.name());
 
     request = PropertyHelper.getCreateRequest(Collections.singleton(requestProps), requestInfoProperties);
@@ -1607,7 +1597,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.0.0");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity2200.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test_host_ordered");
     requestProps.put(UpgradeResourceProvider.UPGRADE_TYPE, UpgradeType.HOST_ORDERED.toString());
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS,Boolean.TRUE.toString());
@@ -1627,6 +1617,11 @@ public class UpgradeResourceProviderTest {
     }
   }
 
+  @Test
+  public void testUpgradeHistory() throws Exception {
+    Assert.fail("Implement me!");
+  }
+
   private String parseSingleMessage(String msgStr){
     JsonParser parser = new JsonParser();
     JsonArray msgArray = (JsonArray) parser.parse(msgStr);
@@ -1662,8 +1657,6 @@ public class UpgradeResourceProviderTest {
 
   @Test
   public void testTimeouts() throws Exception {
-    Cluster cluster = clusters.getCluster("c1");
-
     StackEntity stackEntity = stackDAO.find("HDP", "2.1.1");
     RepositoryVersionEntity repoVersionEntity = new RepositoryVersionEntity();
     repoVersionEntity.setDisplayName("My New Version 3");
@@ -1674,7 +1667,7 @@ public class UpgradeResourceProviderTest {
 
     Map<String, Object> requestProps = new HashMap<>();
     requestProps.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "c1");
-    requestProps.put(UpgradeResourceProvider.UPGRADE_VERSION, "2.2.2.3");
+    requestProps.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, String.valueOf(repoVersionEntity.getId()));
     requestProps.put(UpgradeResourceProvider.UPGRADE_PACK, "upgrade_test");
     requestProps.put(UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS, "true");
     requestProps.put(UpgradeResourceProvider.UPGRADE_DIRECTION, Direction.UPGRADE.name());

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/UpgradeSummaryResourceProviderTest.java
----------------------------------------------------------------------
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 f4ac0b1..73d0e37 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
@@ -38,7 +38,6 @@ import org.apache.ambari.server.H2DatabaseCleaner;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
-import org.apache.ambari.server.actionmanager.ServiceComponentHostEventWrapper;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.AmbariServer;
 import org.apache.ambari.server.controller.predicate.AndPredicate;
@@ -72,12 +71,10 @@ import org.apache.ambari.server.state.HostState;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
-import org.apache.ambari.server.state.ServiceComponentHostEvent;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.UpgradeHelper;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
-import org.apache.ambari.server.state.svccomphost.ServiceComponentHostOpInProgressEvent;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -163,7 +160,7 @@ public class UpgradeSummaryResourceProviderTest {
     clusters.addCluster(clusterName, stackId);
     Cluster cluster = clusters.getCluster("c1");
 
-    helper.getOrCreateRepositoryVersion(stackId, stackId.getStackVersion());
+    helper.getOrCreateRepositoryVersion(stackId, "2.2.0.1-1234");
 
     clusters.addHost("h1");
     Host host = clusters.getHost("h1");
@@ -196,8 +193,6 @@ public class UpgradeSummaryResourceProviderTest {
   @Transactional
   void createCommands(Cluster cluster, Long upgradeRequestId, Long stageId) {
     HostEntity h1 = hostDAO.findByName("h1");
-    ServiceComponentHostEvent event = new ServiceComponentHostOpInProgressEvent("ZOOKEEPER_SERVER", "h1", 1L);
-    ServiceComponentHostEventWrapper eventWrapper = new ServiceComponentHostEventWrapper(event);
 
     RequestEntity requestEntity = requestDAO.findByPK(upgradeRequestId);
 
@@ -277,8 +272,11 @@ public class UpgradeSummaryResourceProviderTest {
     upgrade.setUpgradePackage("some-name");
     upgrade.setUpgradeType(UpgradeType.ROLLING);
     upgrade.setDirection(Direction.UPGRADE);
-    upgrade.setFromVersion("2.2.0.0");
-    upgrade.setToVersion("2.2.0.1");
+
+    RepositoryVersionEntity repositoryVersion2201 = injector.getInstance(
+        RepositoryVersionDAO.class).findByStackNameAndVersion("HDP", "2.2.0.1-1234");
+
+    upgrade.setRepositoryVersion(repositoryVersion2201);
     upgradeDAO.create(upgrade);
 
     // Resource used to make assertions.

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/UpgradeDAOTest.java
----------------------------------------------------------------------
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 9e47e4d..baf6bba 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
@@ -33,11 +33,13 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.orm.OrmTestHelper;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.RequestEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.orm.entities.UpgradeGroupEntity;
 import org.apache.ambari.server.orm.entities.UpgradeItemEntity;
+import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.UpgradeState;
 import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
@@ -62,6 +64,10 @@ public class UpgradeDAOTest {
 
   private OrmTestHelper helper;
 
+  RepositoryVersionEntity repositoryVersion2200;
+  RepositoryVersionEntity repositoryVersion2500;
+  RepositoryVersionEntity repositoryVersion2511;
+
   /**
    *
    */
@@ -83,12 +89,16 @@ public class UpgradeDAOTest {
     requestEntity.setStages(new ArrayList<StageEntity>());
     requestDAO.create(requestEntity);
 
+    repositoryVersion2200 = helper.getOrCreateRepositoryVersion(new StackId("HDP", "2.2.0"), "2.2.0.0-1234");
+    repositoryVersion2500 = helper.getOrCreateRepositoryVersion(new StackId("HDP", "2.5.0"), "2.5.0.0-4567");
+    repositoryVersion2511 = helper.getOrCreateRepositoryVersion(new StackId("HDP", "2.5.0"), "2.5.1.1-4567");
+
+
     // create upgrade entities
     UpgradeEntity entity = new UpgradeEntity();
     entity.setClusterId(clusterId.longValue());
     entity.setRequestEntity(requestEntity);
-    entity.setFromVersion("");
-    entity.setToVersion("");
+    entity.setRepositoryVersion(repositoryVersion2200);
     entity.setUpgradeType(UpgradeType.ROLLING);
     entity.setUpgradePackage("test-upgrade");
     entity.setDowngradeAllowed(true);
@@ -165,8 +175,7 @@ public class UpgradeDAOTest {
     entity1.setClusterId(clusterId.longValue());
     entity1.setDirection(Direction.UPGRADE);
     entity1.setRequestEntity(requestEntity);
-    entity1.setFromVersion("2.2.0.0-1234");
-    entity1.setToVersion("2.3.0.0-4567");
+    entity1.setRepositoryVersion(repositoryVersion2500);
     entity1.setUpgradeType(UpgradeType.ROLLING);
     entity1.setUpgradePackage("test-upgrade");
     entity1.setDowngradeAllowed(true);
@@ -176,8 +185,7 @@ public class UpgradeDAOTest {
     entity2.setClusterId(clusterId.longValue());
     entity2.setDirection(Direction.DOWNGRADE);
     entity2.setRequestEntity(requestEntity);
-    entity2.setFromVersion("2.3.0.0-4567");
-    entity2.setToVersion("2.2.0.0-1234");
+    entity2.setRepositoryVersion(repositoryVersion2200);
     entity2.setUpgradeType(UpgradeType.ROLLING);
     entity2.setUpgradePackage("test-upgrade");
     entity2.setDowngradeAllowed(true);
@@ -187,8 +195,7 @@ public class UpgradeDAOTest {
     entity3.setClusterId(clusterId.longValue());
     entity3.setDirection(Direction.UPGRADE);
     entity3.setRequestEntity(requestEntity);
-    entity3.setFromVersion("2.2.0.0-1234");
-    entity3.setToVersion("2.3.1.1-4567");
+    entity3.setRepositoryVersion(repositoryVersion2511);
     entity3.setUpgradeType(UpgradeType.ROLLING);
     entity3.setUpgradePackage("test-upgrade");
     entity3.setDowngradeAllowed(true);
@@ -217,8 +224,7 @@ public class UpgradeDAOTest {
     upgradeEntity.setClusterId(clusterId.longValue());
     upgradeEntity.setDirection(Direction.UPGRADE);
     upgradeEntity.setRequestEntity(requestEntity);
-    upgradeEntity.setFromVersion("2.2.0.0-1234");
-    upgradeEntity.setToVersion("2.3.0.0-4567");
+    upgradeEntity.setRepositoryVersion(repositoryVersion2500);
     upgradeEntity.setUpgradeType(UpgradeType.ROLLING);
     upgradeEntity.setUpgradePackage("test-upgrade");
     dao.create(upgradeEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/ComponentVersionCheckActionTest.java
----------------------------------------------------------------------
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 7301c66..738ad1f 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
@@ -169,7 +169,9 @@ public class ComponentVersionCheckActionTest {
     String urlInfo = "[{'repositories':["
         + "{'Repositories/base_url':'http://foo1','Repositories/repo_name':'HDP','Repositories/repo_id':'" + targetStack.getStackId() + "'}"
         + "], 'OperatingSystems/os_type':'redhat6'}]";
-    repoVersionDAO.create(stackEntityTarget, targetRepo, String.valueOf(System.currentTimeMillis()), urlInfo);
+
+    RepositoryVersionEntity toRepositoryVersion = repoVersionDAO.create(stackEntityTarget,
+        targetRepo, String.valueOf(System.currentTimeMillis()), urlInfo);
 
     // Start upgrading the newer repo
     c.setCurrentStackVersion(targetStack);
@@ -194,8 +196,7 @@ public class ComponentVersionCheckActionTest {
     upgradeEntity.setClusterId(c.getClusterId());
     upgradeEntity.setRequestEntity(requestEntity);
     upgradeEntity.setUpgradePackage("");
-    upgradeEntity.setFromVersion(sourceRepo);
-    upgradeEntity.setToVersion(targetRepo);
+    upgradeEntity.setRepositoryVersion(toRepositoryVersion);
     upgradeEntity.setUpgradeType(UpgradeType.NON_ROLLING);
     upgradeDAO.create(upgradeEntity);
 
@@ -236,6 +237,10 @@ public class ComponentVersionCheckActionTest {
     // Create the starting repo version
     m_helper.getOrCreateRepositoryVersion(sourceStack, sourceRepo);
 
+    // create the new repo version
+    RepositoryVersionEntity toRepositoryVersion = m_helper.getOrCreateRepositoryVersion(targetStack,
+        targetRepo);
+
     RequestEntity requestEntity = new RequestEntity();
     requestEntity.setClusterId(c.getClusterId());
     requestEntity.setRequestId(1L);
@@ -248,8 +253,7 @@ public class ComponentVersionCheckActionTest {
     upgradeEntity.setClusterId(c.getClusterId());
     upgradeEntity.setRequestEntity(requestEntity);
     upgradeEntity.setUpgradePackage("");
-    upgradeEntity.setFromVersion(sourceRepo);
-    upgradeEntity.setToVersion(targetRepo);
+    upgradeEntity.setRepositoryVersion(toRepositoryVersion);
     upgradeEntity.setUpgradeType(UpgradeType.NON_ROLLING);
     upgradeDAO.create(upgradeEntity);
 
@@ -296,7 +300,6 @@ public class ComponentVersionCheckActionTest {
     // Finalize the upgrade
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo);
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -365,9 +368,6 @@ public class ComponentVersionCheckActionTest {
     // automatically before CURRENT
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo);
-    commandParams.put(FinalizeUpgradeAction.ORIGINAL_STACK_KEY, sourceStack.getStackId());
-    commandParams.put(FinalizeUpgradeAction.TARGET_STACK_KEY, targetStack.getStackId());
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -435,9 +435,6 @@ public class ComponentVersionCheckActionTest {
     // Finalize the upgrade
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo);
-    commandParams.put(FinalizeUpgradeAction.SUPPORTED_SERVICES_KEY, "ZOOKEEPER");
-    commandParams.put(FinalizeUpgradeAction.TARGET_STACK_KEY, "HDP-2.1.1");
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/serveraction/upgrades/UpgradeActionTest.java
----------------------------------------------------------------------
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 0ff0b0a..2bc2c13 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
@@ -51,13 +51,11 @@ import org.apache.ambari.server.orm.dao.HostDAO;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
 import org.apache.ambari.server.orm.dao.RequestDAO;
-import org.apache.ambari.server.orm.dao.ServiceComponentDesiredStateDAO;
 import org.apache.ambari.server.orm.dao.StackDAO;
 import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.HostVersionEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.RequestEntity;
-import org.apache.ambari.server.orm.entities.ServiceComponentHistoryEntity;
 import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.serveraction.ServerAction;
@@ -135,8 +133,6 @@ public class UpgradeActionTest {
   @Inject
   private UpgradeDAO upgradeDAO;
   @Inject
-  private ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO;
-  @Inject
   private StackDAO stackDAO;
   @Inject
   private AmbariMetaInfo ambariMetaInfo;
@@ -145,6 +141,11 @@ public class UpgradeActionTest {
   @Inject
   private ConfigFactory configFactory;
 
+  private RepositoryVersionEntity repositoryVersion2110;
+  private RepositoryVersionEntity repositoryVersion2111;
+  private RepositoryVersionEntity repositoryVersion2201;
+  private RepositoryVersionEntity repositoryVersion2202;
+
   @Before
   public void setup() throws Exception {
     m_injector = Guice.createInjector(new InMemoryDefaultTestModule());
@@ -159,6 +160,11 @@ public class UpgradeActionTest {
     Field field = AmbariServer.class.getDeclaredField("clusterController");
     field.setAccessible(true);
     field.set(null, amc);
+
+    repositoryVersion2110 = m_helper.getOrCreateRepositoryVersion(HDP_21_STACK, HDP_2_1_1_0);
+    repositoryVersion2111 = m_helper.getOrCreateRepositoryVersion(HDP_21_STACK, HDP_2_1_1_1);
+    repositoryVersion2201 = m_helper.getOrCreateRepositoryVersion(HDP_22_STACK, HDP_2_2_0_1);
+    repositoryVersion2202 = m_helper.getOrCreateRepositoryVersion(HDP_22_STACK, HDP_2_2_0_2);
   }
 
   @After
@@ -394,7 +400,7 @@ public class UpgradeActionTest {
 
     Cluster cluster = clusters.getCluster(clusterName);
 
-    createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
+    createUpgrade(cluster, repositoryVersion2201);
 
     // Install ZK and HDFS with some components
     Service zk = installService(cluster, "ZOOKEEPER");
@@ -423,7 +429,6 @@ public class UpgradeActionTest {
     commandParams.put(UpdateDesiredStackAction.COMMAND_PARAM_ORIGINAL_STACK, sourceStack.getStackId());
     commandParams.put(UpdateDesiredStackAction.COMMAND_PARAM_TARGET_STACK, targetStack.getStackId());
     commandParams.put(UpdateDesiredStackAction.COMMAND_PARAM_DIRECTION, Direction.UPGRADE.toString());
-    commandParams.put(UpdateDesiredStackAction.COMMAND_PARAM_VERSION, targetRepo);
     commandParams.put(UpdateDesiredStackAction.COMMAND_PARAM_UPGRADE_PACK, upgradePackName);
 
     ExecutionCommand executionCommand = new ExecutionCommand();
@@ -468,13 +473,10 @@ public class UpgradeActionTest {
 
     Cluster cluster = clusters.getCluster(clusterName);
 
-    createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
+    createUpgrade(cluster, repositoryVersion2111);
 
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "downgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, sourceRepo);
-    commandParams.put(FinalizeUpgradeAction.ORIGINAL_STACK_KEY, sourceStack.getStackId());
-    commandParams.put(FinalizeUpgradeAction.TARGET_STACK_KEY, targetStack.getStackId());
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -522,13 +524,10 @@ public class UpgradeActionTest {
 
     Cluster cluster = clusters.getCluster(clusterName);
 
-    createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
+    createUpgrade(cluster, repositoryVersion2202);
 
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "downgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, midRepo);
-    commandParams.put(FinalizeUpgradeAction.ORIGINAL_STACK_KEY, sourceStack.getStackId());
-    commandParams.put(FinalizeUpgradeAction.TARGET_STACK_KEY, targetStack.getStackId());
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -559,7 +558,7 @@ public class UpgradeActionTest {
 
     Cluster cluster = clusters.getCluster(clusterName);
 
-    createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
+    createUpgrade(cluster, repositoryVersion2111);
 
     RepositoryInfo repo = ambariMetaInfo.getRepository(sourceStack.getStackName(), sourceStack.getStackVersion(), "redhat6", sourceStack.getStackId());
     assertEquals(HDP_211_CENTOS6_REPO_URL, repo.getBaseUrl());
@@ -567,7 +566,6 @@ public class UpgradeActionTest {
     // Finalize the upgrade
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo);
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -618,7 +616,7 @@ public class UpgradeActionTest {
     // Verify the repo before calling Finalize
     Cluster cluster = clusters.getCluster(clusterName);
 
-    createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
+    createUpgrade(cluster, repositoryVersion2111);
 
     RepositoryInfo repo = ambariMetaInfo.getRepository(sourceStack.getStackName(),
             sourceStack.getStackVersion(), "redhat6", sourceStack.getStackId());
@@ -627,7 +625,6 @@ public class UpgradeActionTest {
     // Finalize the upgrade
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo);
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -661,13 +658,10 @@ public class UpgradeActionTest {
     cluster.setCurrentStackVersion(sourceStack);
     cluster.setDesiredStackVersion(targetStack);
 
-    createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
+    createUpgrade(cluster, repositoryVersion2201);
 
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo);
-    commandParams.put(FinalizeUpgradeAction.ORIGINAL_STACK_KEY, sourceStack.getStackId());
-    commandParams.put(FinalizeUpgradeAction.TARGET_STACK_KEY, targetStack.getStackId());
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -719,7 +713,7 @@ public class UpgradeActionTest {
 
     makeCrossStackUpgradeTargetRepo(targetStack, targetRepo, hostName);
 
-    createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
+    createUpgrade(cluster, repositoryVersion2201);
 
     // create some configs
     createConfigs(cluster);
@@ -739,9 +733,6 @@ public class UpgradeActionTest {
 
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "downgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, sourceRepo);
-    commandParams.put(FinalizeUpgradeAction.ORIGINAL_STACK_KEY, sourceStack.getStackId());
-    commandParams.put(FinalizeUpgradeAction.TARGET_STACK_KEY, targetStack.getStackId());
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -819,7 +810,7 @@ public class UpgradeActionTest {
     cluster.setCurrentStackVersion(sourceStack);
     cluster.setDesiredStackVersion(targetStack);
 
-    createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
+    createUpgrade(cluster, repositoryVersion2201);
 
     // set the SCH versions to the new stack so that the finalize action is
     // happy
@@ -842,9 +833,6 @@ public class UpgradeActionTest {
     // automatically before CURRENT
     Map<String, String> commandParams = new HashMap<>();
     commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo);
-    commandParams.put(FinalizeUpgradeAction.ORIGINAL_STACK_KEY, sourceStack.getStackId());
-    commandParams.put(FinalizeUpgradeAction.TARGET_STACK_KEY, targetStack.getStackId());
 
     ExecutionCommand executionCommand = new ExecutionCommand();
     executionCommand.setCommandParams(commandParams);
@@ -870,74 +858,6 @@ public class UpgradeActionTest {
     assertEquals(targetStack, desiredStackId);
   }
 
-  @Test
-  public void testUpgradeHistory() throws Exception {
-    StackId sourceStack = HDP_21_STACK;
-    StackId targetStack = HDP_21_STACK;
-    String sourceRepo = HDP_2_1_1_0;
-    String targetRepo = HDP_2_1_1_1;
-    String hostName = "h1";
-
-    createUpgradeClusterAndSourceRepo(sourceStack, sourceRepo, hostName);
-
-    Cluster cluster = clusters.getCluster(clusterName);
-
-    // install HDFS with some components
-    Service service = installService(cluster, "HDFS");
-    addServiceComponent(cluster, service, "NAMENODE");
-    addServiceComponent(cluster, service, "DATANODE");
-    ServiceComponentHost nnSCH = createNewServiceComponentHost(cluster, "HDFS", "NAMENODE", "h1");
-    ServiceComponentHost dnSCH = createNewServiceComponentHost(cluster, "HDFS", "DATANODE", "h1");
-
-    RepositoryVersionEntity targetRepositoryVersion = createUpgradeClusterTargetRepo(targetStack,
-        targetRepo, hostName);
-
-    // fake their upgrade
-    service.setDesiredRepositoryVersion(targetRepositoryVersion);
-    nnSCH.setVersion(targetRepo);
-    dnSCH.setVersion(targetRepo);
-
-    UpgradeEntity upgrade = createUpgrade(cluster, sourceStack, sourceRepo, targetRepo);
-
-    // verify that no history exist exists yet
-    List<ServiceComponentHistoryEntity> historyEntites = serviceComponentDesiredStateDAO.findHistory(
-            cluster.getClusterId(), nnSCH.getServiceName(),
-            nnSCH.getServiceComponentName());
-
-    assertEquals(0, historyEntites.size());
-
-    RepositoryInfo repo = ambariMetaInfo.getRepository(sourceStack.getStackName(), sourceStack.getStackVersion(), "redhat6", sourceStack.getStackId());
-    assertEquals(HDP_211_CENTOS6_REPO_URL, repo.getBaseUrl());
-//    verifyBaseRepoURL(helper, cluster, null, host, HDP_211_CENTOS6_REPO_URL);
-
-    // Finalize the upgrade, passing in the request ID so that history is
-    // created
-    Map<String, String> commandParams = new HashMap<>();
-    commandParams.put(FinalizeUpgradeAction.REQUEST_ID, String.valueOf(upgrade.getRequestId()));
-    commandParams.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-    commandParams.put(FinalizeUpgradeAction.VERSION_KEY, targetRepo);
-
-    ExecutionCommand executionCommand = new ExecutionCommand();
-    executionCommand.setCommandParams(commandParams);
-    executionCommand.setClusterName(clusterName);
-
-    HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(null, null, null, null);
-    hostRoleCommand.setExecutionCommandWrapper(new ExecutionCommandWrapper(executionCommand));
-
-    finalizeUpgradeAction.setExecutionCommand(executionCommand);
-    finalizeUpgradeAction.setHostRoleCommand(hostRoleCommand);
-
-    CommandReport report = finalizeUpgradeAction.execute(null);
-    assertNotNull(report);
-    assertEquals(HostRoleStatus.COMPLETED.name(), report.getStatus());
-
-    // ensure that history now exists
-    historyEntites = serviceComponentDesiredStateDAO.findHistory(cluster.getClusterId(),
-            nnSCH.getServiceName(), nnSCH.getServiceComponentName());
-
-    assertEquals(1, historyEntites.size());
-  }
-
 
   private ServiceComponentHost createNewServiceComponentHost(Cluster cluster, String svc,
                                                              String svcComponent, String hostName) throws AmbariException {
@@ -1013,8 +933,8 @@ public class UpgradeActionTest {
    * @param targetRepo
    * @throws Exception
    */
-  private UpgradeEntity createUpgrade(Cluster cluster, StackId sourceStack, String sourceRepo,
-      String targetRepo) throws Exception {
+  private UpgradeEntity createUpgrade(Cluster cluster, RepositoryVersionEntity repositoryVersion)
+      throws Exception {
 
     // create some entities for the finalize action to work with for patch
     // history
@@ -1030,8 +950,7 @@ public class UpgradeActionTest {
     upgradeEntity.setClusterId(cluster.getClusterId());
     upgradeEntity.setRequestEntity(requestEntity);
     upgradeEntity.setUpgradePackage("");
-    upgradeEntity.setFromVersion(sourceRepo);
-    upgradeEntity.setToVersion(targetRepo);
+    upgradeEntity.setRepositoryVersion(repositoryVersion);
     upgradeEntity.setUpgradeType(UpgradeType.NON_ROLLING);
 
     upgradeDAO.create(upgradeEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java
index 325fc90..4c9ffcc 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceComponentTest.java
@@ -23,14 +23,12 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.fail;
 
 import java.sql.SQLException;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.H2DatabaseCleaner;
-import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.controller.ServiceComponentResponse;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
@@ -39,23 +37,15 @@ import org.apache.ambari.server.orm.dao.HostComponentDesiredStateDAO;
 import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
 import org.apache.ambari.server.orm.dao.HostDAO;
 import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
-import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.dao.ServiceComponentDesiredStateDAO;
 import org.apache.ambari.server.orm.dao.StackDAO;
-import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.HostEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
-import org.apache.ambari.server.orm.entities.RequestEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
-import org.apache.ambari.server.orm.entities.ServiceComponentHistoryEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentVersionEntity;
 import org.apache.ambari.server.orm.entities.StackEntity;
-import org.apache.ambari.server.orm.entities.StageEntity;
-import org.apache.ambari.server.orm.entities.UpgradeEntity;
-import org.apache.ambari.server.state.stack.upgrade.Direction;
-import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -343,60 +333,6 @@ public class ServiceComponentTest {
     }
   }
 
-  @Test
-  public void testHistoryCreation() throws AmbariException {
-    ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO = injector.getInstance(
-        ServiceComponentDesiredStateDAO.class);
-
-    String componentName = "NAMENODE";
-    ServiceComponent component = serviceComponentFactory.createNew(service, componentName);
-    service.addServiceComponent(component);
-
-    ServiceComponent sc = service.getServiceComponent(componentName);
-    Assert.assertNotNull(sc);
-
-    sc.setDesiredState(State.INSTALLED);
-    Assert.assertEquals(State.INSTALLED, sc.getDesiredState());
-
-    StackId newStackId = new StackId("HDP-2.2.0");
-    RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(newStackId,
-        newStackId.getStackVersion());
-
-    sc.setDesiredRepositoryVersion(repositoryVersion);
-
-    StackId stackId = sc.getDesiredStackId();
-    Assert.assertEquals(new StackId("HDP", "2.2.0"), stackId);
-
-    Assert.assertEquals("HDP-2.2.0", sc.getDesiredStackId().getStackId());
-
-    ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.findByName(
-        cluster.getClusterId(), serviceName, componentName);
-
-    Assert.assertNotNull(serviceComponentDesiredStateEntity);
-
-    UpgradeEntity upgradeEntity = createUpgradeEntity("2.2.0.0", "2.2.0.1");
-    ServiceComponentHistoryEntity history = new ServiceComponentHistoryEntity();
-    history.setFromStack(serviceComponentDesiredStateEntity.getDesiredStack());
-    history.setToStack(serviceComponentDesiredStateEntity.getDesiredStack());
-    history.setUpgrade(upgradeEntity);
-
-    serviceComponentDesiredStateEntity.addHistory(history);
-
-    serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.merge(
-        serviceComponentDesiredStateEntity);
-
-    serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.findByName(
-        cluster.getClusterId(), serviceName, componentName);
-
-    assertEquals(1, serviceComponentDesiredStateEntity.getHistory().size());
-    ServiceComponentHistoryEntity persistedHistory = serviceComponentDesiredStateEntity.getHistory().iterator().next();
-
-    assertEquals(history.getFromStack(), persistedHistory.getFromStack());
-    assertEquals(history.getToStack(), persistedHistory.getFromStack());
-    assertEquals(history.getUpgrade(), persistedHistory.getUpgrade());
-    assertEquals(history.getServiceComponentDesiredState(), persistedHistory.getServiceComponentDesiredState());
-  }
-
 
   @Test
   public void testServiceComponentRemove() throws AmbariException {
@@ -459,83 +395,6 @@ public class ServiceComponentTest {
     Assert.assertNull(serviceComponentDesiredStateEntity);
  }
 
-  /**
-   * Tests the CASCADE nature of removing a service component also removes the
-   * history.
-   *
-   * @throws AmbariException
-   */
-  @Test
-  public void testHistoryRemoval() throws AmbariException {
-    ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO = injector.getInstance(
-        ServiceComponentDesiredStateDAO.class);
-
-    String componentName = "NAMENODE";
-    ServiceComponent component = serviceComponentFactory.createNew(service, componentName);
-    service.addServiceComponent(component);
-
-    ServiceComponent sc = service.getServiceComponent(componentName);
-    Assert.assertNotNull(sc);
-
-    sc.setDesiredState(State.INSTALLED);
-    Assert.assertEquals(State.INSTALLED, sc.getDesiredState());
-
-    StackId newStackId = new StackId("HDP-2.2.0");
-    RepositoryVersionEntity repositoryVersion = helper.getOrCreateRepositoryVersion(newStackId,
-        newStackId.getStackVersion());
-
-    sc.setDesiredRepositoryVersion(repositoryVersion);
-
-    StackId stackId = sc.getDesiredStackId();
-    Assert.assertEquals(new StackId("HDP", "2.2.0"), stackId);
-
-    Assert.assertEquals("HDP-2.2.0", sc.getDesiredStackId().getStackId());
-
-    ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.findByName(
-        cluster.getClusterId(), serviceName, componentName);
-
-
-    Assert.assertNotNull(serviceComponentDesiredStateEntity);
-
-    UpgradeEntity upgradeEntity = createUpgradeEntity("2.2.0.0", "2.2.0.1");
-    ServiceComponentHistoryEntity history = new ServiceComponentHistoryEntity();
-    history.setFromStack(serviceComponentDesiredStateEntity.getDesiredStack());
-    history.setToStack(serviceComponentDesiredStateEntity.getDesiredStack());
-    history.setUpgrade(upgradeEntity);
-    history.setServiceComponentDesiredState(serviceComponentDesiredStateEntity);
-
-    serviceComponentDesiredStateEntity.addHistory(history);
-
-    serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.merge(
-        serviceComponentDesiredStateEntity);
-
-    serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.findByName(
-        cluster.getClusterId(), serviceName, componentName);
-
-    assertEquals(1, serviceComponentDesiredStateEntity.getHistory().size());
-
-    // verify that we can retrieve the history directly
-    List<ServiceComponentHistoryEntity> componentHistoryList = serviceComponentDesiredStateDAO.findHistory(
-        sc.getClusterId(), sc.getServiceName(), sc.getName());
-
-    assertEquals(1, componentHistoryList.size());
-
-    // delete the SC
-    sc.delete();
-
-    // verify history is gone, too
-    serviceComponentDesiredStateEntity = serviceComponentDesiredStateDAO.findByName(
-        cluster.getClusterId(), serviceName, componentName);
-
-    Assert.assertNull(serviceComponentDesiredStateEntity);
-
-    // verify that we cannot retrieve the history directly
-    componentHistoryList = serviceComponentDesiredStateDAO.findHistory(sc.getClusterId(),
-        sc.getServiceName(), sc.getName());
-
-    assertEquals(0, componentHistoryList.size());
-  }
-
   @Test
   public void testVersionCreation() throws Exception {
     ServiceComponentDesiredStateDAO serviceComponentDesiredStateDAO = injector.getInstance(
@@ -734,38 +593,4 @@ public class ServiceComponentTest {
     entity = serviceComponentDesiredStateDAO.findByName(cluster.getClusterId(), serviceName, componentName);
     assertEquals(RepositoryVersionState.CURRENT, entity.getRepositoryState());
   }
-
-
-  /**
-   * Creates an upgrade entity, asserting it was created correctly.
-   *
-   * @param fromVersion
-   * @param toVersion
-   * @return
-   */
-  private UpgradeEntity createUpgradeEntity(String fromVersion, String toVersion) {
-    RequestDAO requestDAO = injector.getInstance(RequestDAO.class);
-    RequestEntity requestEntity = new RequestEntity();
-    requestEntity.setRequestId(99L);
-    requestEntity.setClusterId(cluster.getClusterId());
-    requestEntity.setStatus(HostRoleStatus.PENDING);
-    requestEntity.setStages(new ArrayList<StageEntity>());
-    requestDAO.create(requestEntity);
-
-    UpgradeDAO upgradeDao = injector.getInstance(UpgradeDAO.class);
-    UpgradeEntity upgradeEntity = new UpgradeEntity();
-    upgradeEntity.setClusterId(cluster.getClusterId());
-    upgradeEntity.setDirection(Direction.UPGRADE);
-    upgradeEntity.setFromVersion(fromVersion);
-    upgradeEntity.setToVersion(toVersion);
-    upgradeEntity.setUpgradePackage("upgrade_test");
-    upgradeEntity.setUpgradeType(UpgradeType.ROLLING);
-    upgradeEntity.setRequestEntity(requestEntity);
-
-    upgradeDao.create(upgradeEntity);
-    List<UpgradeEntity> upgrades = upgradeDao.findUpgrades(cluster.getClusterId());
-    assertEquals(1, upgrades.size());
-    return upgradeEntity;
-  }
-
 }


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

Posted by jo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java
index a68a2e1..db58d27 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContext.java
@@ -17,31 +17,65 @@
  */
 package org.apache.ambari.server.state;
 
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.VERSION;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_CLUSTER_NAME;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_DIRECTION;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_FAIL_ON_CHECK_WARNINGS;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_HOST_ORDERED_HOSTS;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_PACK;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_SKIP_FAILURES;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_SKIP_MANUAL_VERIFICATION;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_SKIP_PREREQUISITE_CHECKS;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_SKIP_SC_FAILURES;
+import static org.apache.ambari.server.controller.internal.UpgradeResourceProvider.UPGRADE_TYPE;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 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;
 
 import org.apache.ambari.annotations.Experimental;
 import org.apache.ambari.annotations.ExperimentalFeature;
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
 import org.apache.ambari.server.agent.ExecutionCommand.KeyNames;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.controller.internal.AbstractControllerResourceProvider;
+import org.apache.ambari.server.controller.internal.PreUpgradeCheckResourceProvider;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+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.RepositoryVersionDAO;
+import org.apache.ambari.server.orm.dao.UpgradeDAO;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
+import org.apache.ambari.server.orm.entities.UpgradeHistoryEntity;
 import org.apache.ambari.server.stack.MasterHostResolver;
 import org.apache.ambari.server.stageplanner.RoleGraphFactory;
+import org.apache.ambari.server.state.repository.VersionDefinitionXml;
+import org.apache.ambari.server.state.stack.PrereqCheckStatus;
 import org.apache.ambari.server.state.stack.UpgradePack;
 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.UpgradeScope;
 import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
 
 import com.google.common.base.Objects;
 import com.google.gson.Gson;
@@ -51,11 +85,12 @@ import com.google.inject.assistedinject.Assisted;
 import com.google.inject.assistedinject.AssistedInject;
 
 /**
- * Used to hold various helper objects required to process an upgrade pack.
+ * The {@link UpgradeContext} is used to hold all information pertaining to an
+ * upgrade. It is initialized directly from an existing {@link UpgradeEntity} or
+ * from a request to create an upgrade/downgrade.
  */
 public class UpgradeContext {
 
-  public static final String COMMAND_PARAM_VERSION = VERSION;
   public static final String COMMAND_PARAM_CLUSTER_NAME = "clusterName";
   public static final String COMMAND_PARAM_DIRECTION = "upgrade_direction";
   public static final String COMMAND_PARAM_UPGRADE_PACK = "upgrade_pack";
@@ -64,21 +99,6 @@ public class UpgradeContext {
   public static final String COMMAND_PARAM_UPGRADE_TYPE = "upgrade_type";
   public static final String COMMAND_PARAM_TASKS = "tasks";
   public static final String COMMAND_PARAM_STRUCT_OUT = "structured_out";
-  public static final String COMMAND_DOWNGRADE_FROM_VERSION = "downgrade_from_version";
-
-  /**
-   * The original "current" stack of the cluster before the upgrade started.
-   * This is the same regardless of whether the current direction is
-   * {@link Direction#UPGRADE} or {@link Direction#DOWNGRADE}.
-   */
-  public static final String COMMAND_PARAM_ORIGINAL_STACK = "original_stack";
-
-  /**
-   * The target upgrade stack before the upgrade started. This is the same
-   * regardless of whether the current direction is {@link Direction#UPGRADE} or
-   * {@link Direction#DOWNGRADE}.
-   */
-  public static final String COMMAND_PARAM_TARGET_STACK = "target_stack";
 
   /**
    * The cluster that the upgrade is for.
@@ -106,50 +126,37 @@ public class UpgradeContext {
   private UpgradePack m_upgradePack;
 
   /**
-   * The version being upgrade to or downgraded to.
-   */
-  private final String m_version;
-
-  /**
-   * The original "current" stack of the cluster before the upgrade started.
-   * This is the same regardless of whether the current direction is
-   * {@link Direction#UPGRADE} or {@link Direction#DOWNGRADE}.
+   * Upgrades will always have a single version being upgraded to and downgrades
+   * will have a single version being downgraded from. This repository
+   * represents that version.
+   * <p/>
+   * When the direction is {@link Direction#UPGRADE}, this represents the target
+   * repository. <br/>
+   * When the direction is {@link Direction#DOWNGRADE}, this represents the
+   * repository being downgraded from.
    */
-  private StackId m_originalStackId;
+  private final RepositoryVersionEntity m_repositoryVersion;
 
   /**
-   * The stack currently used to start/restart services during an upgrade.This is the same
-   * During a {@link UpgradeType#ROLLING} upgrade, this is always the {@link this.m_targetStackId},
-   * During a {@link UpgradeType#NON_ROLLING} upgrade, this is initially the {@link this.m_sourceStackId} while
-   * stopping services, and then changes to the {@link this.m_targetStackId} when starting services.
+   * Resolves master components on hosts.
    */
-  private StackId m_effectiveStackId;
+  private final MasterHostResolver m_resolver;
 
   /**
-   * The target upgrade stack before the upgrade started. This is the same
-   * regardless of whether the current direction is {@link Direction#UPGRADE} or
-   * {@link Direction#DOWNGRADE}.
+   * A collection of hosts in the cluster which are unhealthy and will not
+   * participate in the upgrade.
    */
-  private StackId m_targetStackId;
+  private final List<ServiceComponentHost> m_unhealthy = new ArrayList<>();
 
   /**
-   * The target repository before the upgrade started. This is the same
-   * regardless of whether the current direction is {@link Direction#UPGRADE} or
-   * {@link Direction#DOWNGRADE}.
+   * Mapping of service name to display name.
    */
-  private RepositoryVersionEntity m_targetRepositoryVersion;
+  private final Map<String, String> m_serviceNames = new HashMap<>();
 
   /**
-   * Optionally set if {@link #setDowngradeFromVersion(String)} is called.
+   * Mapping of component name to display name.
    */
-  private RepositoryVersionEntity m_downgradeFromRepositoryVersion;
-
-  private MasterHostResolver m_resolver;
-  private AmbariMetaInfo m_metaInfo;
-  private List<ServiceComponentHost> m_unhealthy = new ArrayList<>();
-  private Map<String, String> m_serviceNames = new HashMap<>();
-  private Map<String, String> m_componentNames = new HashMap<>();
-  private String m_downgradeFromVersion = null;
+  private final Map<String, String> m_componentNames = new HashMap<>();
 
   /**
    * {@code true} if slave/client component failures should be automatically
@@ -170,9 +177,19 @@ public class UpgradeContext {
    */
   private boolean m_autoSkipManualVerification = false;
 
-  private Set<String> m_supported = new HashSet<>();
+  /**
+   * A set of services which are included in this upgrade. If this is empty,
+   * then all cluster services are included.
+   */
+  private Set<String> m_services = new HashSet<>();
 
-  private UpgradeScope m_scope = UpgradeScope.ANY;
+  /**
+   * A mapping of service to target repository. On an upgrade, this will be the
+   * same for all services. On a downgrade, this may be different for each
+   * service depending on which repository the service was on before the failed
+   * upgrade.
+   */
+  private final Map<String, RepositoryVersionEntity> m_targetRepositoryMap = new HashMap<>();
 
   /**
    * Used by some {@link Grouping}s to generate commands. It is exposed here
@@ -189,45 +206,183 @@ public class UpgradeContext {
   private RoleGraphFactory m_roleGraphFactory;
 
   /**
-   * Used to lookup the reposotory version given a stack name and version.
+   * Used for serializing the upgrade type.
    */
-  final private RepositoryVersionDAO m_repoVersionDAO;
+  @Inject
+  private Gson m_gson;
 
   /**
-   * Used for serializing the upgrade type.
+   * Used for looking up information about components and services.
    */
   @Inject
-  private Gson m_gson;
+  private AmbariMetaInfo m_metaInfo;
 
   /**
-   * Constructor.
-   *
-   * @param cluster
-   *          the cluster that the upgrade is for
-   * @param type
-   *          the type of upgrade, either rolling or non_rolling
-   * @param direction
-   *          the direction for the upgrade
-   * @param upgradeRequestMap
-   *          the original map of paramters used to create the upgrade
-   *
-   * @param repoVersionDAO
-   *          the repository version DAO.
+   * Used to suggest upgrade packs during creation of an upgrade context.
+   */
+  @Inject
+  private UpgradeHelper m_upgradeHelper;
+
+  /**
+   * Used to lookup the repository version from an ID.
+   */
+  @Inject
+  private RepositoryVersionDAO m_repoVersionDAO;
+
+  /**
+   * Used to lookup a prior upgrade by ID.
    */
+  @Inject
+  private UpgradeDAO m_upgradeDAO;
+
   @AssistedInject
-  public UpgradeContext(@Assisted Cluster cluster, @Assisted UpgradeType type,
-      @Assisted Direction direction, @Assisted String version,
-      @Assisted Map<String, Object> upgradeRequestMap,
-      RepositoryVersionDAO repoVersionDAO) {
+  public UpgradeContext(@Assisted Cluster cluster,
+      @Assisted Map<String, Object> upgradeRequestMap, Gson gson, UpgradeHelper upgradeHelper,
+      UpgradeDAO upgradeDAO, RepositoryVersionDAO repoVersionDAO, ConfigHelper configHelper)
+      throws AmbariException {
+    // injected constructor dependencies
+    m_gson = gson;
+    m_upgradeHelper = upgradeHelper;
+    m_upgradeDAO = upgradeDAO;
     m_repoVersionDAO = repoVersionDAO;
+
     m_cluster = cluster;
-    m_type = type;
-    m_direction = direction;
-    m_version = version;
     m_upgradeRequestMap = upgradeRequestMap;
 
-    // sets the original/target stacks - requires direction and cluster
-    setSourceAndTargetVersions();
+    // determine direction
+    String directionProperty = (String) m_upgradeRequestMap.get(UPGRADE_DIRECTION);
+    if (StringUtils.isEmpty(directionProperty)) {
+      throw new AmbariException(String.format("%s is required", UPGRADE_DIRECTION));
+    }
+
+    m_direction = Direction.valueOf(directionProperty);
+
+    // determine upgrade type (default is ROLLING)
+    String upgradeTypeProperty = (String) m_upgradeRequestMap.get(UPGRADE_TYPE);
+    if (StringUtils.isNotBlank(upgradeTypeProperty)) {
+      try {
+        m_type = UpgradeType.valueOf(m_upgradeRequestMap.get(UPGRADE_TYPE).toString());
+      } catch (Exception e) {
+        throw new AmbariException(String.format("Property %s has an incorrect value of %s.",
+            UPGRADE_TYPE, upgradeTypeProperty));
+      }
+    } else {
+      // default type
+      m_type= UpgradeType.ROLLING;
+    }
+
+    // depending on the direction, we must either have a target repository or an upgrade we are downgrading from
+    switch(m_direction){
+      case UPGRADE:{
+        String repositoryVersionId = (String) m_upgradeRequestMap.get(UPGRADE_REPO_VERSION_ID);
+        if (null == repositoryVersionId) {
+          throw new AmbariException(
+              String.format("The property %s is required when the upgrade direction is %s",
+                  UPGRADE_REPO_VERSION_ID, m_direction));
+        }
+
+        // depending on the repository, add services
+        m_repositoryVersion = m_repoVersionDAO.findByPK(Long.valueOf(repositoryVersionId));
+        if (m_repositoryVersion.getType() == RepositoryType.STANDARD) {
+          m_services.addAll(cluster.getServices().keySet());
+        } else {
+          try {
+            VersionDefinitionXml vdf = m_repositoryVersion.getRepositoryXml();
+            m_services.addAll(vdf.getAvailableServiceNames());
+
+            // if this is every true, then just stop the upgrade attempt and
+            // throw an exception
+            if (m_services.isEmpty()) {
+              String message = String.format(
+                  "When using a VDF of type %s, the available services must be defined in the VDF",
+                  m_repositoryVersion.getType());
+
+              throw new AmbariException(message);
+            }
+
+          } catch (Exception e) {
+            String msg = String.format(
+                "Could not parse version definition for %s.  Upgrade will not proceed.",
+                m_repositoryVersion.getVersion());
+
+            throw new AmbariException(msg);
+          }
+        }
+
+        // populate the target repository map for all services in the upgrade
+        for (String service : m_services) {
+          m_targetRepositoryMap.put(service, m_repositoryVersion);
+        }
+
+        break;
+      }
+      case DOWNGRADE:{
+        UpgradeEntity upgrade = m_upgradeDAO.findLastUpgradeForCluster(
+            cluster.getClusterId(), Direction.UPGRADE);
+
+        m_repositoryVersion = upgrade.getRepositoryVersion();
+
+        // populate the target repository map for all services in the upgrade
+        for (UpgradeHistoryEntity history : upgrade.getHistory()) {
+          m_services.add(history.getServiceName());
+          m_targetRepositoryMap.put(history.getServiceName(), history.getFromReposistoryVersion());
+        }
+
+        break;
+      }
+      default:
+        m_repositoryVersion = null;
+        break;
+    }
+
+
+    /**
+     * 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) m_upgradeRequestMap.get(UPGRADE_PACK);
+
+    @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES, comment="This is wrong")
+    String upgradePackFromVersion = cluster.getService(
+        m_services.iterator().next()).getDesiredRepositoryVersion().getVersion();
+
+    m_upgradePack = m_upgradeHelper.suggestUpgradePack(m_cluster.getClusterName(),
+        upgradePackFromVersion, m_repositoryVersion.getVersion(), 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(this);
+
+    // 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 = m_upgradePack.isComponentFailureAutoSkipped();
+    boolean skipServiceCheckFailures = m_upgradePack.isServiceCheckFailureAutoSkipped();
+
+    // only override the upgrade pack if set on the request
+    if (m_upgradeRequestMap.containsKey(UPGRADE_SKIP_FAILURES)) {
+      skipComponentFailures = Boolean.parseBoolean(
+          (String) m_upgradeRequestMap.get(UPGRADE_SKIP_FAILURES));
+    }
+
+    // only override the upgrade pack if set on the request
+    if (m_upgradeRequestMap.containsKey(UPGRADE_SKIP_SC_FAILURES)) {
+      skipServiceCheckFailures = Boolean.parseBoolean(
+          (String) m_upgradeRequestMap.get(UPGRADE_SKIP_SC_FAILURES));
+    }
+
+    boolean skipManualVerification = false;
+    if (m_upgradeRequestMap.containsKey(UPGRADE_SKIP_MANUAL_VERIFICATION)) {
+      skipManualVerification = Boolean.parseBoolean(
+          (String) m_upgradeRequestMap.get(UPGRADE_SKIP_MANUAL_VERIFICATION));
+    }
+
+    m_autoSkipComponentFailures = skipComponentFailures;
+    m_autoSkipServiceCheckFailures = skipServiceCheckFailures;
+    m_autoSkipManualVerification = skipManualVerification;
+
+    m_resolver = new MasterHostResolver(configHelper, this);
   }
 
   /**
@@ -242,82 +397,39 @@ public class UpgradeContext {
    */
   @AssistedInject
   public UpgradeContext(@Assisted Cluster cluster, @Assisted UpgradeEntity upgradeEntity,
-      RepositoryVersionDAO repoVersionDAO) {
-    m_repoVersionDAO = repoVersionDAO;
+      AmbariMetaInfo ambariMetaInfo, ConfigHelper configHelper) {
+    m_metaInfo = ambariMetaInfo;
 
     m_cluster = cluster;
     m_type = upgradeEntity.getUpgradeType();
     m_direction = upgradeEntity.getDirection();
-
-    m_version = upgradeEntity.getToVersion();
-
-    // sets the original/target stacks - requires direction and cluster
-    setSourceAndTargetVersions();
-
-    if (m_direction == Direction.DOWNGRADE) {
-      setDowngradeFromVersion(upgradeEntity.getFromVersion());
-    }
-
-    // since this constructor is initialized from an entity, then this map is
-    // not present
-    m_upgradeRequestMap = Collections.emptyMap();
+    m_repositoryVersion = upgradeEntity.getRepositoryVersion();
 
     m_autoSkipComponentFailures = upgradeEntity.isComponentFailureAutoSkipped();
     m_autoSkipServiceCheckFailures = upgradeEntity.isServiceCheckFailureAutoSkipped();
-  }
 
-  /**
-   * Sets the source and target versions. This will also set the effective stack
-   * ID based on the already-set {@link UpgradeType} and {@link Direction}.
-   *
-   * @see #getEffectiveStackId()
-   */
-  private void setSourceAndTargetVersions() {
-    StackId sourceStackId = null;
-
-    // taret stack will not always be what it is today - tagging as experimental
-    @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
-    StackId targetStackId = null;
-
-    switch (m_direction) {
-      case UPGRADE:
-        sourceStackId = m_cluster.getCurrentStackVersion();
-
-        m_targetRepositoryVersion = m_repoVersionDAO.findByStackNameAndVersion(
-            sourceStackId.getStackName(), m_version);
-
-        // !!! TODO check the repo_version for patch-ness and restrict the
-        // context to those services that require it. Consult the version
-        // definition and add the service names to supportedServices
-        targetStackId = m_targetRepositoryVersion.getStackId();
-        break;
-      case DOWNGRADE:
-        sourceStackId = m_cluster.getCurrentStackVersion();
-        targetStackId = m_cluster.getDesiredStackVersion();
-
-        m_targetRepositoryVersion = m_repoVersionDAO.findByStackNameAndVersion(
-            targetStackId.getStackName(), m_version);
-        break;
+    List<UpgradeHistoryEntity> allHistory = upgradeEntity.getHistory();
+    for (UpgradeHistoryEntity history : allHistory) {
+      String serviceName = history.getServiceName();
+      RepositoryVersionEntity targetRepositoryVersion = history.getTargetRepositoryVersion();
+      m_targetRepositoryMap.put(serviceName, targetRepositoryVersion);
+      m_services.add(serviceName);
     }
 
-    m_originalStackId = sourceStackId;
+    @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES, comment = "This is wrong")
+    String upgradePackage = upgradeEntity.getUpgradePackage();
+    StackId stackId = m_repositoryVersion.getStackId();
+    Map<String, UpgradePack> packs = m_metaInfo.getUpgradePacks(stackId.getStackName(), stackId.getStackVersion());
+    m_upgradePack = packs.get(upgradePackage);
 
-    switch (m_type) {
-      case ROLLING:
-      case HOST_ORDERED:
-        m_effectiveStackId = targetStackId;
-        break;
-      case NON_ROLLING:
-        m_effectiveStackId = (m_direction.isUpgrade()) ? sourceStackId : targetStackId;
-        break;
-      default:
-        m_effectiveStackId = targetStackId;
-        break;
-    }
+    m_resolver = new MasterHostResolver(configHelper, this);
 
-    m_targetStackId = m_targetRepositoryVersion.getStackId();
+    // since this constructor is initialized from an entity, then this map is
+    // not present
+    m_upgradeRequestMap = Collections.emptyMap();
   }
 
+
   /**
    * Gets the original mapping of key/value pairs from the request which created
    * the upgrade.
@@ -358,10 +470,49 @@ public class UpgradeContext {
   }
 
   /**
+   * Gets the version being upgraded to or downgraded to for all services
+   * participating. This is the version that the service will be on if the
+   * upgrade or downgrade succeeds.
+   * <p/>
+   * With a {@link Direction#UPGRADE}, all services should be targetting the
+   * same repository version. However, {@link Direction#DOWNGRADE} will target
+   * the original repository that the service was on.
+   *
+   * @return the target version for the upgrade
+   */
+  public Map<String, RepositoryVersionEntity> getTargetVersions() {
+    return new HashMap<>(m_targetRepositoryMap);
+  }
+
+  /**
+   * Gets the repository being upgraded to or downgraded to for the given
+   * service. This is the version that the service will be on if the upgrade or
+   * downgrade succeeds.
+   * <p/>
+   * With a {@link Direction#UPGRADE}, all services should be targetting the
+   * same repository version. However, {@link Direction#DOWNGRADE} will target
+   * the original repository that the service was on.
+   *
+   * @return the target repository for the upgrade
+   */
+  public RepositoryVersionEntity getTargetRepositoryVersion(String serviceName) {
+    return m_targetRepositoryMap.get(serviceName);
+  }
+
+  /**
+   * Gets the version being upgraded to or downgraded to for the given service.
+   * This is the version that the service will be on if the upgrade or downgrade
+   * succeeds.
+   * <p/>
+   * With a {@link Direction#UPGRADE}, all services should be targetting the
+   * same repository version. However, {@link Direction#DOWNGRADE} will target
+   * the original repository that the service was on.
+   *
    * @return the target version for the upgrade
    */
-  public String getVersion() {
-    return m_version;
+  public String getTargetVersion(String serviceName) {
+    RepositoryVersionEntity serviceTargetVersion = m_targetRepositoryMap.get(serviceName);
+    return serviceTargetVersion.getVersion();
   }
 
   /**
@@ -379,16 +530,6 @@ public class UpgradeContext {
   }
 
   /**
-   * Sets the host resolver.
-   *
-   * @param resolver
-   *          the resolver that also references the required cluster
-   */
-  public void setResolver(MasterHostResolver resolver) {
-    m_resolver = resolver;
-  }
-
-  /**
    * @return the resolver
    */
   public MasterHostResolver getResolver() {
@@ -403,13 +544,6 @@ public class UpgradeContext {
   }
 
   /**
-   * @param metaInfo the metainfo for access to service definitions
-   */
-  public void setAmbariMetaInfo(AmbariMetaInfo metaInfo) {
-    m_metaInfo = metaInfo;
-  }
-
-  /**
    * @param unhealthy a list of unhealthy host components
    */
   public void addUnhealthy(List<ServiceComponentHost> unhealthy) {
@@ -417,50 +551,20 @@ public class UpgradeContext {
   }
 
   /**
-   * @return the originalStackId
-   */
-  public StackId getOriginalStackId() {
-    return m_originalStackId;
-  }
-
-  /**
-   * @param originalStackId
-   *          the originalStackId to set
-   */
-  public void setOriginalStackId(StackId originalStackId) {
-    m_originalStackId = originalStackId;
-  }
-
-  /**
-   * @return the effectiveStackId that is currently in use.
-   */
-  public StackId getEffectiveStackId() {
-    return m_effectiveStackId;
-  }
-
-  /**
-   * @param effectiveStackId the effectiveStackId to set
-   */
-  public void setEffectiveStackId(StackId effectiveStackId) {
-    m_effectiveStackId = effectiveStackId;
-  }
-
-
-  /**
-   * @return the targetStackId
-   */
-  public StackId getTargetStackId() {
-    return m_targetStackId;
-  }
-
-  /**
-   * Gets the target repository version for this upgrade.
+   * Gets the single repository version for the upgrade depending on the
+   * direction.
+   * <p/>
+   * If the direction is {@link Direction#UPGRADE} then this will return the
+   * target repository which every service will be on if the upgrade is
+   * finalized. <br/>
+   * If the direction is {@link Direction#DOWNGRADE} then this will return the
+   * repository from which the downgrade is coming from.
    *
    * @return the target repository version for this upgrade (never
    *         {@code null}).
    */
-  public RepositoryVersionEntity getTargetRepositoryVersion() {
-    return m_targetRepositoryVersion;
+  public RepositoryVersionEntity getRepositoryVersion() {
+    return m_repositoryVersion;
   }
 
   /**
@@ -505,38 +609,6 @@ public class UpgradeContext {
   }
 
   /**
-   * Optionally set if doing a downgrade. Represents the non-finalized version
-   * being downgraded from.
-   *
-   * @return version cluster is downgrading from
-   */
-  public String getDowngradeFromVersion() {
-    return m_downgradeFromVersion;
-  }
-
-  /**
-   * Optionally set if doing a downgrade. Represents the non-finalized version
-   * being downgraded from.
-   *
-   * @return
-   */
-  public RepositoryVersionEntity getDowngradeFromRepositoryVersion() {
-    return m_downgradeFromRepositoryVersion;
-  }
-
-  /**
-   * Set the HDP stack version we are downgrading from.
-   *
-   * @param downgradeFromVersion
-   */
-  public void setDowngradeFromVersion(String downgradeFromVersion) {
-    m_downgradeFromVersion = downgradeFromVersion;
-
-    m_downgradeFromRepositoryVersion = m_repoVersionDAO.findByStackAndVersion(m_targetStackId,
-        downgradeFromVersion);
-  }
-
-  /**
    * Gets whether skippable components that failed are automatically skipped.
    *
    * @return the skipComponentFailures
@@ -546,17 +618,6 @@ public class UpgradeContext {
   }
 
   /**
-   * Sets whether skippable components that failed are automatically skipped.
-   *
-   * @param autoSkipComponentFailures
-   *          {@code true} to automatically skip component failures which are
-   *          marked as skippable.
-   */
-  public void setAutoSkipComponentFailures(boolean autoSkipComponentFailures) {
-    m_autoSkipComponentFailures = autoSkipComponentFailures;
-  }
-
-  /**
    * Gets whether skippable service checks that failed are automatically
    * skipped.
    *
@@ -567,18 +628,6 @@ public class UpgradeContext {
   }
 
   /**
-   * Sets whether skippable service checks that failed are automatically
-   * skipped.
-   *
-   * @param autoSkipServiceCheckFailures
-   *          {@code true} to automatically skip service check failures which
-   *          are marked as being skippable.
-   */
-  public void setAutoSkipServiceCheckFailures(boolean autoSkipServiceCheckFailures) {
-    m_autoSkipServiceCheckFailures = autoSkipServiceCheckFailures;
-  }
-
-  /**
    * Gets whether manual verification tasks can be automatically skipped.
    *
    * @return the skipManualVerification
@@ -588,58 +637,43 @@ public class UpgradeContext {
   }
 
   /**
-   * Sets whether manual verification checks are automatically skipped.
-   *
-   * @param autoSkipManualVerification
-   *          {@code true} to automatically skip manual verification tasks.
-   */
-  public void setAutoSkipManualVerification(boolean autoSkipManualVerification) {
-    m_autoSkipManualVerification = autoSkipManualVerification;
-  }
-
-  /**
-   * Sets the service names that are supported by an upgrade.  This is used for
-   * {@link RepositoryType#PATCH} and {@link RepositoryType#SERVICE}.
+   * Gets the services participating in the upgrade.
    *
-   * @param services  the set of specific services
-   */
-  @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
-  public void setSupportedServices(Set<String> services) {
-    m_supported = services;
-  }
-
-  /**
-   * @return the set of supported services, or an empty set if ALL services
-   * are supported
+   * @return the set of supported services. This collection should never be
+   *         empty.
    */
   @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
   public Set<String> getSupportedServices() {
-    return Collections.unmodifiableSet(m_supported);
+    return Collections.unmodifiableSet(m_services);
   }
 
   /**
-   * Gets if a service is supported.  If there are no services marked for the context,
-   * then ALL services are supported
-   * @param serviceName the service name to check.
+   * Gets if a service is supported.
+   *
+   * @param serviceName
+   *          the service name to check.
    * @return {@code true} when the service is supported
    */
   @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
   public boolean isServiceSupported(String serviceName) {
-    if (m_supported.isEmpty() || m_supported.contains(serviceName)) {
+    return m_services.contains(serviceName);
+  }
+
+  @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
+  public boolean isScoped(UpgradeScope scope) {
+    if (scope == UpgradeScope.ANY) {
       return true;
     }
 
-    return false;
-  }
-
-  @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
-  public void setScope(UpgradeScope scope) {
-    m_scope = scope;
-  }
+    switch (m_repositoryVersion.getType()) {
+      case PATCH:
+      case SERVICE:
+        return scope == UpgradeScope.PARTIAL;
+      case STANDARD:
+        return scope == UpgradeScope.COMPLETE;
+    }
 
-  @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
-  public boolean isScoped(UpgradeScope scope) {
-    return m_scope.isScoped(scope);
+    return false;
   }
 
   /**
@@ -661,15 +695,21 @@ public class UpgradeContext {
   }
 
   /**
+   * Gets the repository type to determine if this upgrade is a complete upgrade
+   * or a service/patch.
+   *
+   * @return the repository type.
+   */
+  public RepositoryType getRepositoryType() {
+    return m_repositoryVersion.getType();
+  }
+
+  /**
    * Gets a map initialized with parameters required for upgrades to work. The
    * following properties are already set:
    * <ul>
    * <li>{@link #COMMAND_PARAM_CLUSTER_NAME}
-   * <li>{@link #COMMAND_PARAM_VERSION}
    * <li>{@link #COMMAND_PARAM_DIRECTION}
-   * <li>{@link #COMMAND_PARAM_ORIGINAL_STACK}
-   * <li>{@link #COMMAND_PARAM_TARGET_STACK}
-   * <li>{@link #COMMAND_DOWNGRADE_FROM_VERSION}
    * <li>{@link #COMMAND_PARAM_UPGRADE_TYPE}
    * <li>{@link KeyNames#REFRESH_CONFIG_TAGS_BEFORE_EXECUTION} - necessary in
    * order to have the commands contain the correct configurations. Otherwise,
@@ -685,11 +725,7 @@ public class UpgradeContext {
     Map<String, String> parameters = new HashMap<>();
 
     parameters.put(COMMAND_PARAM_CLUSTER_NAME, m_cluster.getClusterName());
-    parameters.put(COMMAND_PARAM_VERSION, getVersion());
     parameters.put(COMMAND_PARAM_DIRECTION, getDirection().name().toLowerCase());
-    parameters.put(COMMAND_PARAM_ORIGINAL_STACK, getOriginalStackId().getStackId());
-    parameters.put(COMMAND_PARAM_TARGET_STACK, getTargetStackId().getStackId());
-    parameters.put(COMMAND_DOWNGRADE_FROM_VERSION, getDowngradeFromVersion());
 
     if (null != getType()) {
       // use the serialized attributes of the enum to convert it to a string,
@@ -712,6 +748,328 @@ public class UpgradeContext {
     return Objects.toStringHelper(this)
         .add("direction", m_direction)
         .add("type", m_type)
-        .add("target",m_targetRepositoryVersion).toString();
+        .add("target", m_repositoryVersion).toString();
+  }
+
+  /**
+   * 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.
+   */
+  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;
+    }
+
+    preReqValidator.setNextValidator(upgradeTypeValidator);
+    return validator;
+  }
+
+  /**
+   * 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;
+
+    /**
+     * 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)
+        throws AmbariException {
+
+      // run this instance's check
+      check(upgradeContext, upgradeContext.getUpgradePack());
+
+      // pass along to the next
+      if( null != m_nextValidator ) {
+        m_nextValidator.validate(upgradeContext);
+      }
+    }
+
+    /**
+     * 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 direction = (String) requestMap.get(UPGRADE_DIRECTION);
+
+      if (StringUtils.isBlank(clusterName)) {
+        throw new AmbariException(String.format("%s is required", UPGRADE_CLUSTER_NAME));
+      }
+
+      if (StringUtils.isBlank(direction)) {
+        throw new AmbariException(String.format("%s is required", UPGRADE_DIRECTION));
+      }
+
+      if (Direction.valueOf(direction) == Direction.UPGRADE) {
+        String repositoryVersionId = (String) requestMap.get(UPGRADE_REPO_VERSION_ID);
+        if (StringUtils.isBlank(repositoryVersionId)) {
+          throw new AmbariException(
+              String.format("%s is required for upgrades", UPGRADE_REPO_VERSION_ID));
+        }
+      }
+    }
+  }
+
+  /**
+   * 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 repositoryVersionId = (String) requestMap.get(UPGRADE_REPO_VERSION_ID);
+      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;
+      }
+
+      RepositoryVersionEntity repositoryVersion = m_repoVersionDAO.findByPK(
+          Long.valueOf(repositoryVersionId));
+
+      // Validate pre-req checks pass
+      PreUpgradeCheckResourceProvider provider = (PreUpgradeCheckResourceProvider) AbstractControllerResourceProvider.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(repositoryVersion.getVersion()).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 = provider.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), m_gson.toJson(failedResources)));
+      }
+    }
+  }
+
+  /**
+   * Ensures that for {@link UpgradeType#HOST_ORDERED}, the properties supplied
+   * are valid.
+   */
+  @SuppressWarnings("unchecked")
+  private final class HostOrderedUpgradeValidator 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();
+
+      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());
+      }
+
+      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);
+        }
+      }
+    }
+  }
+
+  /**
+   * Builds the list of {@link HostOrderItem}s from the upgrade request. If the
+   * upgrade request does not contain the hosts
+   *
+   * @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.
+   */
+  @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"));
+      }
+
+      if (CollectionUtils.isNotEmpty(hosts)) {
+        hostOrderItems.add(new HostOrderItem(HostOrderActionType.HOST_UPGRADE, hosts));
+      }
+
+      if (CollectionUtils.isNotEmpty(serviceChecks)) {
+        hostOrderItems.add(new HostOrderItem(HostOrderActionType.SERVICE_CHECK, serviceChecks));
+      }
+    }
+
+    return hostOrderItems;
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java
index 4f15ee2..eaccd53 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeContextFactory.java
@@ -19,9 +19,8 @@ package org.apache.ambari.server.state;
 
 import java.util.Map;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
-import org.apache.ambari.server.state.stack.upgrade.Direction;
-import org.apache.ambari.server.state.stack.upgrade.UpgradeType;
 
 /**
  * The {@link UpgradeContextFactory} is used to create dependency-injected
@@ -34,22 +33,14 @@ public interface UpgradeContextFactory {
    *
    * @param cluster
    *          the cluster that the upgrade is for (not {@code null}).
-   * @param type
-   *          the type of upgrade, either rolling or non_rolling (not
-   *          {@code null}).
-   * @param direction
-   *          the direction for the upgrade
-   * @param version
-   *          the version being upgrade-to or downgraded-from (not
-   *          {@code null}).
    * @param upgradeRequestMap
    *          the original map of parameters used to create the upgrade (not
    *          {@code null}).
    *
    * @return an initialized {@link UpgradeContext}.
    */
-  UpgradeContext create(Cluster cluster, UpgradeType type, Direction direction,
-      String version, Map<String, Object> upgradeRequestMap);
+  UpgradeContext create(Cluster cluster, Map<String, Object> upgradeRequestMap)
+      throws AmbariException;
 
   /**
    * Creates an {@link UpgradeContext} which is injected with dependencies.

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
index 3ec907f..0f39e60 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/UpgradeHelper.java
@@ -19,9 +19,9 @@ package org.apache.ambari.server.state;
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -263,7 +263,6 @@ public class UpgradeHelper {
   public List<UpgradeGroupHolder> createSequence(UpgradePack upgradePack,
       UpgradeContext context) throws AmbariException {
 
-    context.setAmbariMetaInfo(m_ambariMetaInfo.get());
     Cluster cluster = context.getCluster();
     MasterHostResolver mhr = context.getResolver();
 
@@ -541,7 +540,6 @@ public class UpgradeHelper {
   private String tokenReplace(UpgradeContext ctx, String source, String service, String component) {
     Cluster cluster = ctx.getCluster();
     MasterHostResolver mhr = ctx.getResolver();
-    String version = ctx.getVersion();
 
     String result = source;
 
@@ -578,7 +576,7 @@ public class UpgradeHelper {
           break;
         }
         case VERSION:
-          value = version;
+          value = ctx.getRepositoryVersion().getVersion();
           break;
         case DIRECTION_VERB:
         case DIRECTION_VERB_PROPER:
@@ -732,29 +730,17 @@ public class UpgradeHelper {
   @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES)
   public void putComponentsToUpgradingState(UpgradeContext upgradeContext) throws AmbariException {
 
-    // determine which services/components will participate in the upgrade
     Cluster cluster = upgradeContext.getCluster();
-    Set<Service> services = new HashSet<>(cluster.getServices().values());
-    Map<Service, Set<ServiceComponent>> targetServices = new HashMap<>();
-    for (Service service : services) {
-      if (upgradeContext.isServiceSupported(service.getName())) {
-        Set<ServiceComponent> serviceComponents = new HashSet<>(
-            service.getServiceComponents().values());
-
-        targetServices.put(service, serviceComponents);
-      }
-    }
+    Set<String> services = upgradeContext.getSupportedServices();
 
-    RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion();
-    StackId targetStack = targetRepositoryVersion.getStackId();
-
-    for (Map.Entry<Service, Set<ServiceComponent>> entry: targetServices.entrySet()) {
-      // set service desired repo
-      Service service = entry.getKey();
+    for (String serviceName : services) {
+      Service service = cluster.getService(serviceName);
+      RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion(serviceName);
+      StackId targetStack = targetRepositoryVersion.getStackId();
       service.setDesiredRepositoryVersion(targetRepositoryVersion);
 
-      for (ServiceComponent serviceComponent: entry.getValue()) {
-
+      Collection<ServiceComponent> components = service.getServiceComponents().values();
+      for (ServiceComponent serviceComponent : components) {
         boolean versionAdvertised = false;
         try {
           ComponentInfo ci = m_ambariMetaInfo.get().getComponent(targetStack.getStackName(),
@@ -773,12 +759,13 @@ public class UpgradeHelper {
           upgradeStateToSet = UpgradeState.NONE;
         }
 
-        for (ServiceComponentHost serviceComponentHost: serviceComponent.getServiceComponentHosts().values()) {
+        for (ServiceComponentHost serviceComponentHost : serviceComponent.getServiceComponentHosts().values()) {
           if (serviceComponentHost.getUpgradeState() != upgradeStateToSet) {
             serviceComponentHost.setUpgradeState(upgradeStateToSet);
           }
 
-          // !!! if we aren't version advertised, but there IS a version, set it.
+          // !!! if we aren't version advertised, but there IS a version, set
+          // it.
           if (!versionAdvertised && !StringUtils.equals(StackVersionListener.UNKNOWN_VERSION,
               serviceComponentHost.getVersion())) {
             serviceComponentHost.setVersion(StackVersionListener.UNKNOWN_VERSION);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/state/services/RetryUpgradeActionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/services/RetryUpgradeActionService.java b/ambari-server/src/main/java/org/apache/ambari/server/state/services/RetryUpgradeActionService.java
index c43d3ba..cc9c168 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/services/RetryUpgradeActionService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/services/RetryUpgradeActionService.java
@@ -31,9 +31,11 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
 import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -168,12 +170,17 @@ public class RetryUpgradeActionService extends AbstractScheduledService {
     // May be null, and either upgrade or downgrade
     UpgradeEntity currentUpgrade = cluster.getUpgradeInProgress();
     if (currentUpgrade == null) {
-      LOG.debug("There is no active stack upgrade in progress. Skip retrying failed tasks.");
+      LOG.debug("There is no active upgrade in progress. Skip retrying failed tasks.");
       return null;
     }
-    LOG.debug("Found an active stack upgrade with id: {}, direction: {}, type: {}, from version: {}, to version: {}",
-        currentUpgrade.getId(), currentUpgrade.getDirection(), currentUpgrade.getUpgradeType(),
-        currentUpgrade.getFromVersion(), currentUpgrade.getToVersion());
+
+    Direction direction = currentUpgrade.getDirection();
+    RepositoryVersionEntity repositoryVersion = currentUpgrade.getRepositoryVersion();
+
+    LOG.debug(
+        "Found an active upgrade with id: {}, direction: {}, {} {}", currentUpgrade.getId(),
+        direction, currentUpgrade.getUpgradeType(), direction.getPreposition(),
+        repositoryVersion.getVersion());
 
     return currentUpgrade.getRequestId();
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Direction.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Direction.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Direction.java
index cb4f501..9bdfe5d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Direction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/Direction.java
@@ -79,4 +79,13 @@ public enum Direction {
   }
 
 
+  /**
+   * Gets the preposition based on the direction. Since the repository is
+   * singular, it will either be "to repo" or "from repo".
+   *
+   * @return "to" or "from"
+   */
+  public String getPreposition() {
+    return (this == UPGRADE) ? "to" : "from";
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
index d19406e..5fb4c76 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/stack/upgrade/HostOrderGrouping.java
@@ -33,6 +33,7 @@ import org.apache.ambari.server.actionmanager.HostRoleCommand;
 import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.stack.HostsType;
 import org.apache.ambari.server.stageplanner.RoleGraph;
 import org.apache.ambari.server.stageplanner.RoleGraphFactory;
@@ -173,9 +174,14 @@ public class HostOrderGrouping extends Grouping {
           // either doesn't exist or the downgrade is to the current target version.
           // hostsType better not be null either, but check anyway
           if (null != hostsType && !hostsType.hosts.contains(hostName)) {
+            RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion(
+                sch.getServiceName());
+
             LOG.warn("Host {} could not be orchestrated. Either there are no components for {}/{} " +
                 "or the target version {} is already current.",
-                hostName, sch.getServiceName(), sch.getServiceComponentName(), upgradeContext.getVersion());
+                hostName, sch.getServiceName(), sch.getServiceComponentName(),
+                targetRepositoryVersion.getVersion());
+
             continue;
           }
 
@@ -225,7 +231,7 @@ public class HostOrderGrouping extends Grouping {
           // create task wrappers
           List<TaskWrapper> taskWrappers = new ArrayList<>();
           for (HostRoleCommand command : stageCommandsForHost) {
-            StackId stackId = upgradeContext.getEffectiveStackId();
+            StackId stackId = upgradeContext.getRepositoryVersion().getStackId();
             String componentName = command.getRole().name();
 
             String serviceName = null;
@@ -328,7 +334,10 @@ public class HostOrderGrouping extends Grouping {
      * @return                {@code true} if the host component advertises its version
      */
     private boolean isVersionAdvertised(UpgradeContext upgradeContext, ServiceComponentHost sch) {
-      StackId targetStack = upgradeContext.getTargetStackId();
+      RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion(
+          sch.getServiceName());
+
+      StackId targetStack = targetRepositoryVersion.getStackId();
 
       try {
         ComponentInfo component = upgradeContext.getAmbariMetaInfo().getComponent(

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java
index a11fd96..9cf7bbd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog220.java
@@ -312,9 +312,7 @@ public class UpgradeCatalog220 extends AbstractUpgradeCatalog {
       // apply changes
       upgradeDAO.merge(upgrade);
 
-      LOG.info(String.format("Updated upgrade id %s, upgrade pack %s from version %s to %s",
-        upgrade.getId(), upgrade.getUpgradePackage(), upgrade.getFromVersion(),
-        upgrade.getToVersion()));
+      LOG.info(String.format("Updated upgrade id %s", upgrade.getId()));
     }
 
     // make the columns nullable now that they have defaults

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
----------------------------------------------------------------------
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 a2a1ea9..36a46cf 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql
@@ -812,18 +812,18 @@ CREATE TABLE upgrade (
   upgrade_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
   request_id BIGINT NOT NULL,
-  from_version VARCHAR(255) DEFAULT '' NOT NULL,
-  to_version VARCHAR(255) DEFAULT '' NOT NULL,
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
+  repo_version_id BIGINT NOT NULL,
   skip_failures SMALLINT DEFAULT 0 NOT NULL,
   skip_sc_failures SMALLINT DEFAULT 0 NOT NULL,
   downgrade_allowed SMALLINT DEFAULT 1 NOT NULL,
   suspended SMALLINT DEFAULT 0 NOT NULL,
   CONSTRAINT PK_upgrade PRIMARY KEY (upgrade_id),
   FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),
-  FOREIGN KEY (request_id) REFERENCES request(request_id)
+  FOREIGN KEY (request_id) REFERENCES request(request_id),
+  FOREIGN KEY (repo_version_id) REFERENCES repo_version(repo_version_id)
 );
 
 CREATE TABLE upgrade_group (
@@ -847,17 +847,18 @@ CREATE TABLE upgrade_item (
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
-CREATE TABLE servicecomponent_history(
+CREATE TABLE upgrade_history(
   id BIGINT NOT NULL,
-  component_id BIGINT NOT NULL,
   upgrade_id BIGINT NOT NULL,
-  from_stack_id BIGINT NOT NULL,
-  to_stack_id BIGINT NOT NULL,
-  CONSTRAINT PK_sc_history PRIMARY KEY (id),
-  CONSTRAINT FK_sc_history_component_id FOREIGN KEY (component_id) REFERENCES servicecomponentdesiredstate (id),
-  CONSTRAINT FK_sc_history_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
-  CONSTRAINT FK_sc_history_from_stack_id FOREIGN KEY (from_stack_id) REFERENCES stack (stack_id),
-  CONSTRAINT FK_sc_history_to_stack_id FOREIGN KEY (to_stack_id) REFERENCES stack (stack_id)
+  service_name VARCHAR(255) NOT NULL,
+  component_name VARCHAR(255) NOT NULL,
+  from_repo_version_id BIGINT NOT NULL,
+  target_repo_version_id BIGINT NOT NULL,
+  CONSTRAINT PK_upgrade_hist PRIMARY KEY (id),
+  CONSTRAINT FK_upgrade_hist_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
+  CONSTRAINT FK_upgrade_hist_from_repo FOREIGN KEY (from_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT FK_upgrade_hist_target_repo FOREIGN KEY (target_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT UQ_upgrade_hist UNIQUE (upgrade_id, component_name, service_name)
 );
 
 CREATE TABLE servicecomponent_version(
@@ -1131,7 +1132,7 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value)
   union all
   select 'servicecomponentdesiredstate_id_seq', 0 FROM SYSIBM.SYSDUMMY1
   union all
-  select 'servicecomponent_history_id_seq', 0 FROM SYSIBM.SYSDUMMY1
+  select 'upgrade_history_id_seq', 0 FROM SYSIBM.SYSDUMMY1
   union all
   select 'blueprint_setting_id_seq', 0 FROM SYSIBM.SYSDUMMY1
   union all

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
index 6dcbf3d..21200bf 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql
@@ -830,18 +830,18 @@ CREATE TABLE upgrade (
   upgrade_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
   request_id BIGINT NOT NULL,
-  from_version VARCHAR(255) DEFAULT '' NOT NULL,
-  to_version VARCHAR(255) DEFAULT '' NOT NULL,
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
+  repo_version_id BIGINT NOT NULL,
   skip_failures TINYINT(1) NOT NULL DEFAULT 0,
   skip_sc_failures TINYINT(1) NOT NULL DEFAULT 0,
   downgrade_allowed TINYINT(1) NOT NULL DEFAULT 1,
   suspended TINYINT(1) DEFAULT 0 NOT NULL,
   CONSTRAINT PK_upgrade PRIMARY KEY (upgrade_id),
   FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),
-  FOREIGN KEY (request_id) REFERENCES request(request_id)
+  FOREIGN KEY (request_id) REFERENCES request(request_id),
+  FOREIGN KEY (repo_version_id) REFERENCES repo_version(repo_version_id)
 );
 
 CREATE TABLE upgrade_group (
@@ -865,17 +865,18 @@ CREATE TABLE upgrade_item (
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
-CREATE TABLE servicecomponent_history(
+CREATE TABLE upgrade_history(
   id BIGINT NOT NULL,
-  component_id BIGINT NOT NULL,
   upgrade_id BIGINT NOT NULL,
-  from_stack_id BIGINT NOT NULL,
-  to_stack_id BIGINT NOT NULL,
-  CONSTRAINT PK_sc_history PRIMARY KEY (id),
-  CONSTRAINT FK_sc_history_component_id FOREIGN KEY (component_id) REFERENCES servicecomponentdesiredstate (id),
-  CONSTRAINT FK_sc_history_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
-  CONSTRAINT FK_sc_history_from_stack_id FOREIGN KEY (from_stack_id) REFERENCES stack (stack_id),
-  CONSTRAINT FK_sc_history_to_stack_id FOREIGN KEY (to_stack_id) REFERENCES stack (stack_id)
+  service_name VARCHAR(255) NOT NULL,
+  component_name VARCHAR(255) NOT NULL,
+  from_repo_version_id BIGINT NOT NULL,
+  target_repo_version_id BIGINT NOT NULL,
+  CONSTRAINT PK_upgrade_hist PRIMARY KEY (id),
+  CONSTRAINT FK_upgrade_hist_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
+  CONSTRAINT FK_upgrade_hist_from_repo FOREIGN KEY (from_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT FK_upgrade_hist_target_repo FOREIGN KEY (target_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT UQ_upgrade_hist UNIQUE (upgrade_id, component_name, service_name)
 );
 
 CREATE TABLE servicecomponent_version(

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
index 15de29c..d148781 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql
@@ -809,18 +809,18 @@ CREATE TABLE upgrade (
   upgrade_id NUMBER(19) NOT NULL,
   cluster_id NUMBER(19) NOT NULL,
   request_id NUMBER(19) NOT NULL,
-  from_version VARCHAR2(255) DEFAULT '' NOT NULL,
-  to_version VARCHAR2(255) DEFAULT '' NOT NULL,
   direction VARCHAR2(255) DEFAULT 'UPGRADE' NOT NULL,
   upgrade_package 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,
   skip_sc_failures NUMBER(1) DEFAULT 0 NOT NULL,
   downgrade_allowed NUMBER(1) DEFAULT 1 NOT NULL,
   suspended NUMBER(1) DEFAULT 0 NOT NULL,
   CONSTRAINT PK_upgrade PRIMARY KEY (upgrade_id),
   FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),
-  FOREIGN KEY (request_id) REFERENCES request(request_id)
+  FOREIGN KEY (request_id) REFERENCES request(request_id),
+  FOREIGN KEY (repo_version_id) REFERENCES repo_version(repo_version_id)
 );
 
 CREATE TABLE upgrade_group (
@@ -844,17 +844,18 @@ CREATE TABLE upgrade_item (
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
-CREATE TABLE servicecomponent_history(
-  id NUMBER(19) NOT NULL,
-  component_id NUMBER(19) NOT NULL,
-  upgrade_id NUMBER(19) NOT NULL,
-  from_stack_id NUMBER(19) NOT NULL,
-  to_stack_id NUMBER(19) NOT NULL,
-  CONSTRAINT PK_sc_history PRIMARY KEY (id),
-  CONSTRAINT FK_sc_history_component_id FOREIGN KEY (component_id) REFERENCES servicecomponentdesiredstate (id),
-  CONSTRAINT FK_sc_history_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
-  CONSTRAINT FK_sc_history_from_stack_id FOREIGN KEY (from_stack_id) REFERENCES stack (stack_id),
-  CONSTRAINT FK_sc_history_to_stack_id FOREIGN KEY (to_stack_id) REFERENCES stack (stack_id)
+CREATE TABLE upgrade_history(
+  id BIGINT NOT NULL,
+  upgrade_id BIGINT NOT NULL,
+  service_name VARCHAR2(255) NOT NULL,
+  component_name VARCHAR2(255) NOT NULL,
+  from_repo_version_id BIGINT NOT NULL,
+  target_repo_version_id BIGINT NOT NULL,
+  CONSTRAINT PK_upgrade_hist PRIMARY KEY (id),
+  CONSTRAINT FK_upgrade_hist_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
+  CONSTRAINT FK_upgrade_hist_from_repo FOREIGN KEY (from_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT FK_upgrade_hist_target_repo FOREIGN KEY (target_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT UQ_upgrade_hist UNIQUE (upgrade_id, component_name, service_name)
 );
 
 CREATE TABLE servicecomponent_version(
@@ -1081,7 +1082,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('topology_ho
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('setting_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('hostcomponentstate_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponentdesiredstate_id_seq', 0);
-INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_history_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_history_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('blueprint_setting_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('ambari_operation_history_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_id_seq', 0);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 9e2f2a7..fc40d44 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -811,18 +811,18 @@ CREATE TABLE upgrade (
   upgrade_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
   request_id BIGINT NOT NULL,
-  from_version VARCHAR(255) DEFAULT '' NOT NULL,
-  to_version VARCHAR(255) DEFAULT '' NOT NULL,
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
+  repo_version_id BIGINT NOT NULL,
   skip_failures SMALLINT DEFAULT 0 NOT NULL,
   skip_sc_failures SMALLINT DEFAULT 0 NOT NULL,
   downgrade_allowed SMALLINT DEFAULT 1 NOT NULL,
   suspended SMALLINT DEFAULT 0 NOT NULL,
   CONSTRAINT PK_upgrade PRIMARY KEY (upgrade_id),
   FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),
-  FOREIGN KEY (request_id) REFERENCES request(request_id)
+  FOREIGN KEY (request_id) REFERENCES request(request_id),
+  FOREIGN KEY (repo_version_id) REFERENCES repo_version(repo_version_id)
 );
 
 CREATE TABLE upgrade_group (
@@ -846,17 +846,18 @@ CREATE TABLE upgrade_item (
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
-CREATE TABLE servicecomponent_history(
+CREATE TABLE upgrade_history(
   id BIGINT NOT NULL,
-  component_id BIGINT NOT NULL,
   upgrade_id BIGINT NOT NULL,
-  from_stack_id BIGINT NOT NULL,
-  to_stack_id BIGINT NOT NULL,
-  CONSTRAINT PK_sc_history PRIMARY KEY (id),
-  CONSTRAINT FK_sc_history_component_id FOREIGN KEY (component_id) REFERENCES servicecomponentdesiredstate (id),
-  CONSTRAINT FK_sc_history_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
-  CONSTRAINT FK_sc_history_from_stack_id FOREIGN KEY (from_stack_id) REFERENCES stack (stack_id),
-  CONSTRAINT FK_sc_history_to_stack_id FOREIGN KEY (to_stack_id) REFERENCES stack (stack_id)
+  service_name VARCHAR(255) NOT NULL,
+  component_name VARCHAR(255) NOT NULL,
+  from_repo_version_id BIGINT NOT NULL,
+  target_repo_version_id BIGINT NOT NULL,
+  CONSTRAINT PK_upgrade_hist PRIMARY KEY (id),
+  CONSTRAINT FK_upgrade_hist_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
+  CONSTRAINT FK_upgrade_hist_from_repo FOREIGN KEY (from_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT FK_upgrade_hist_target_repo FOREIGN KEY (target_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT UQ_upgrade_hist UNIQUE (upgrade_id, component_name, service_name)
 );
 
 CREATE TABLE servicecomponent_version(
@@ -1082,7 +1083,7 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) VALUES
   ('setting_id_seq', 0),
   ('hostcomponentstate_id_seq', 0),
   ('servicecomponentdesiredstate_id_seq', 0),
-  ('servicecomponent_history_id_seq', 0),
+  ('upgrade_history_id_seq', 0),
   ('blueprint_setting_id_seq', 0),
   ('ambari_operation_history_id_seq', 0),
   ('remote_cluster_id_seq', 0),

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
----------------------------------------------------------------------
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 473e8ca..d654016 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql
@@ -807,10 +807,9 @@ CREATE TABLE upgrade (
   upgrade_id NUMERIC(19) NOT NULL,
   cluster_id NUMERIC(19) NOT NULL,
   request_id NUMERIC(19) NOT NULL,
-  from_version VARCHAR(255) DEFAULT '' NOT NULL,
-  to_version VARCHAR(255) DEFAULT '' NOT NULL,
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
+  repo_version_id NUMERIC(19) NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
   skip_failures BIT NOT NULL DEFAULT 0,
   skip_sc_failures BIT NOT NULL DEFAULT 0,
@@ -818,7 +817,8 @@ CREATE TABLE upgrade (
   suspended BIT DEFAULT 0 NOT NULL,
   CONSTRAINT PK_upgrade PRIMARY KEY (upgrade_id),
   FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),
-  FOREIGN KEY (request_id) REFERENCES request(request_id)
+  FOREIGN KEY (request_id) REFERENCES request(request_id),
+  FOREIGN KEY (repo_version_id) REFERENCES repo_version(repo_version_id)
 );
 
 CREATE TABLE upgrade_group (
@@ -842,17 +842,18 @@ CREATE TABLE upgrade_item (
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
-CREATE TABLE servicecomponent_history(
-  id NUMERIC(19) NOT NULL,
-  component_id NUMERIC(19) NOT NULL,
-  upgrade_id NUMERIC(19) NOT NULL,
-  from_stack_id NUMERIC(19) NOT NULL,
-  to_stack_id NUMERIC(19) NOT NULL,
-  CONSTRAINT PK_sc_history PRIMARY KEY (id),
-  CONSTRAINT FK_sc_history_component_id FOREIGN KEY (component_id) REFERENCES servicecomponentdesiredstate (id),
-  CONSTRAINT FK_sc_history_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
-  CONSTRAINT FK_sc_history_from_stack_id FOREIGN KEY (from_stack_id) REFERENCES stack (stack_id),
-  CONSTRAINT FK_sc_history_to_stack_id FOREIGN KEY (to_stack_id) REFERENCES stack (stack_id)
+CREATE TABLE upgrade_history(
+  id BIGINT NOT NULL,
+  upgrade_id BIGINT NOT NULL,
+  service_name VARCHAR(255) NOT NULL,
+  component_name VARCHAR(255) NOT NULL,
+  from_repo_version_id BIGINT NOT NULL,
+  target_repo_version_id BIGINT NOT NULL,
+  CONSTRAINT PK_upgrade_hist PRIMARY KEY (id),
+  CONSTRAINT FK_upgrade_hist_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
+  CONSTRAINT FK_upgrade_hist_from_repo FOREIGN KEY (from_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT FK_upgrade_hist_target_repo FOREIGN KEY (target_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT UQ_upgrade_hist UNIQUE (upgrade_id, component_name, service_name)
 );
 
 CREATE TABLE servicecomponent_version(
@@ -1079,7 +1080,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('topology_ho
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('setting_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('hostcomponentstate_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponentdesiredstate_id_seq', 0);
-INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_history_id_seq', 0);
+INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('upgrade_history_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('blueprint_setting_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('ambari_operation_history_id_seq', 0);
 INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('remote_cluster_id_seq', 0);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
----------------------------------------------------------------------
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 72189aa..f89e720 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql
@@ -829,18 +829,18 @@ CREATE TABLE upgrade (
   upgrade_id BIGINT NOT NULL,
   cluster_id BIGINT NOT NULL,
   request_id BIGINT NOT NULL,
-  from_version VARCHAR(255) DEFAULT '' NOT NULL,
-  to_version VARCHAR(255) DEFAULT '' NOT NULL,
   direction VARCHAR(255) DEFAULT 'UPGRADE' NOT NULL,
   upgrade_package VARCHAR(255) NOT NULL,
   upgrade_type VARCHAR(32) NOT NULL,
+  repo_version_id BIGINT NOT NULL,
   skip_failures BIT NOT NULL DEFAULT 0,
   skip_sc_failures BIT NOT NULL DEFAULT 0,
   downgrade_allowed BIT NOT NULL DEFAULT 1,
   suspended BIT DEFAULT 0 NOT NULL,
   CONSTRAINT PK_upgrade PRIMARY KEY CLUSTERED (upgrade_id),
   FOREIGN KEY (cluster_id) REFERENCES clusters(cluster_id),
-  FOREIGN KEY (request_id) REFERENCES request(request_id)
+  FOREIGN KEY (request_id) REFERENCES request(request_id),
+  FOREIGN KEY (repo_version_id) REFERENCES repo_version(repo_version_id)
 );
 
 CREATE TABLE upgrade_group (
@@ -864,17 +864,18 @@ CREATE TABLE upgrade_item (
   FOREIGN KEY (upgrade_group_id) REFERENCES upgrade_group(upgrade_group_id)
 );
 
-CREATE TABLE servicecomponent_history(
+CREATE TABLE upgrade_history(
   id BIGINT NOT NULL,
-  component_id BIGINT NOT NULL,
   upgrade_id BIGINT NOT NULL,
-  from_stack_id BIGINT NOT NULL,
-  to_stack_id BIGINT NOT NULL,
-  CONSTRAINT PK_sc_history PRIMARY KEY (id),
-  CONSTRAINT FK_sc_history_component_id FOREIGN KEY (component_id) REFERENCES servicecomponentdesiredstate (id),
-  CONSTRAINT FK_sc_history_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
-  CONSTRAINT FK_sc_history_from_stack_id FOREIGN KEY (from_stack_id) REFERENCES stack (stack_id),
-  CONSTRAINT FK_sc_history_to_stack_id FOREIGN KEY (to_stack_id) REFERENCES stack (stack_id)
+  service_name VARCHAR(255) NOT NULL,
+  component_name VARCHAR(255) NOT NULL,
+  from_repo_version_id BIGINT NOT NULL,
+  target_repo_version_id BIGINT NOT NULL,
+  CONSTRAINT PK_upgrade_hist PRIMARY KEY (id),
+  CONSTRAINT FK_upgrade_hist_upgrade_id FOREIGN KEY (upgrade_id) REFERENCES upgrade (upgrade_id),
+  CONSTRAINT FK_upgrade_hist_from_repo FOREIGN KEY (from_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT FK_upgrade_hist_target_repo FOREIGN KEY (target_repo_version_id) REFERENCES repo_version (repo_version_id),
+  CONSTRAINT UQ_upgrade_hist UNIQUE (upgrade_id, component_name, service_name)
 );
 
 CREATE TABLE servicecomponent_version(
@@ -1106,7 +1107,7 @@ BEGIN TRANSACTION
     ('setting_id_seq', 0),
     ('hostcomponentstate_id_seq', 0),
     ('servicecomponentdesiredstate_id_seq', 0),
-    ('servicecomponent_history_id_seq', 0),
+    ('upgrade_history_id_seq', 0),
     ('blueprint_setting_id_seq', 0),
     ('ambari_operation_history_id_seq', 0),
     ('remote_cluster_id_seq', 0),

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/resources/META-INF/persistence.xml
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml
index 8fd539a..e4045ef 100644
--- a/ambari-server/src/main/resources/META-INF/persistence.xml
+++ b/ambari-server/src/main/resources/META-INF/persistence.xml
@@ -64,7 +64,6 @@
     <class>org.apache.ambari.server.orm.entities.ResourceTypeEntity</class>
     <class>org.apache.ambari.server.orm.entities.RoleSuccessCriteriaEntity</class>
     <class>org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity</class>
-    <class>org.apache.ambari.server.orm.entities.ServiceComponentHistoryEntity</class>
     <class>org.apache.ambari.server.orm.entities.ServiceComponentVersionEntity</class>
     <class>org.apache.ambari.server.orm.entities.ServiceConfigEntity</class>
     <class>org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity</class>
@@ -73,6 +72,7 @@
     <class>org.apache.ambari.server.orm.entities.UpgradeEntity</class>
     <class>org.apache.ambari.server.orm.entities.UpgradeGroupEntity</class>
     <class>org.apache.ambari.server.orm.entities.UpgradeItemEntity</class>
+    <class>org.apache.ambari.server.orm.entities.UpgradeHistoryEntity</class>
     <class>org.apache.ambari.server.orm.entities.UserEntity</class>
     <class>org.apache.ambari.server.orm.entities.WidgetEntity</class>
     <class>org.apache.ambari.server.orm.entities.ViewEntity</class>

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnableTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnableTest.java b/ambari-server/src/test/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnableTest.java
index b361418..4542bb3 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnableTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnableTest.java
@@ -52,6 +52,7 @@ import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.stack.OsFamily;
+import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.easymock.EasyMock;
 import org.easymock.EasyMockSupport;
 import org.junit.After;
@@ -225,7 +226,7 @@ public class ComponentVersionAlertRunnableTest extends EasyMockSupport {
   @Test
   public void testUpgradeInProgress() throws Exception {
     UpgradeEntity upgrade = createNiceMock(UpgradeEntity.class);
-    expect(upgrade.getToVersion()).andReturn("VERSION").once();
+    expect(upgrade.getDirection()).andReturn(Direction.UPGRADE).atLeastOnce();
     expect(m_cluster.getUpgradeInProgress()).andReturn(upgrade).once();
 
     replayAll();

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/UpgradeEventCreatorTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/UpgradeEventCreatorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/UpgradeEventCreatorTest.java
index db76d4e..a8e21f6 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/UpgradeEventCreatorTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/audit/request/creator/UpgradeEventCreatorTest.java
@@ -40,7 +40,7 @@ public class UpgradeEventCreatorTest extends AuditEventCreatorTestBase{
     UpgradeEventCreator creator = new UpgradeEventCreator();
 
     Map<String,Object> properties = new HashMap<>();
-    properties.put(UpgradeResourceProvider.UPGRADE_VERSION, "1.9");
+    properties.put(UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID, "1234");
     properties.put(UpgradeResourceProvider.UPGRADE_TYPE, "ROLLING");
     properties.put(UpgradeResourceProvider.UPGRADE_CLUSTER_NAME, "mycluster");
 
@@ -50,7 +50,7 @@ public class UpgradeEventCreatorTest extends AuditEventCreatorTestBase{
     AuditEvent event = AuditEventCreatorTestHelper.getEvent(creator, request, result);
 
     String actual = event.getAuditMessage();
-    String expected = "User(" + userName + "), RemoteIp(1.2.3.4), Operation(Upgrade addition), RequestType(POST), url(http://example.com:8080/api/v1/test), ResultStatus(200 OK), Repository version(1.9), Upgrade type(ROLLING), Cluster name(mycluster)";
+    String expected = "User(" + userName + "), RemoteIp(1.2.3.4), Operation(Upgrade addition), RequestType(POST), url(http://example.com:8080/api/v1/test), ResultStatus(200 OK), Repository version ID(1234), Upgrade type(ROLLING), Cluster name(mycluster)";
 
     Assert.assertTrue("Class mismatch", event instanceof AddUpgradeRequestAuditEvent);
     Assert.assertEquals(expected, actual);

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/test/java/org/apache/ambari/server/checks/PreviousUpgradeCompletedTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/PreviousUpgradeCompletedTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/PreviousUpgradeCompletedTest.java
index 4bfa8d4..3233e55 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/checks/PreviousUpgradeCompletedTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/PreviousUpgradeCompletedTest.java
@@ -18,6 +18,7 @@
 package org.apache.ambari.server.checks;
 
 import org.apache.ambari.server.controller.PrereqCheckRequest;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.StackEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.state.Cluster;
@@ -49,6 +50,8 @@ public class PreviousUpgradeCompletedTest {
   private PrereqCheckRequest checkRequest = new PrereqCheckRequest(clusterName);
   private PreviousUpgradeCompleted puc = new PreviousUpgradeCompleted();
 
+  private RepositoryVersionEntity toRepsitoryVersion;
+
   /**
    *
    */
@@ -75,6 +78,8 @@ public class PreviousUpgradeCompletedTest {
       }
     };
 
+    toRepsitoryVersion = Mockito.mock(RepositoryVersionEntity.class);
+    Mockito.when(toRepsitoryVersion.getVersion()).thenReturn(destRepositoryVersion);
   }
 
   @Test
@@ -89,8 +94,7 @@ public class PreviousUpgradeCompletedTest {
     UpgradeEntity upgradeInProgress = Mockito.mock(UpgradeEntity.class);
     Mockito.when(upgradeInProgress.getDirection()).thenReturn(Direction.UPGRADE);
     Mockito.when(upgradeInProgress.getClusterId()).thenReturn(1L);
-    Mockito.when(upgradeInProgress.getFromVersion()).thenReturn(sourceRepositoryVersion);
-    Mockito.when(upgradeInProgress.getToVersion()).thenReturn(destRepositoryVersion);
+    Mockito.when(upgradeInProgress.getRepositoryVersion()).thenReturn(toRepsitoryVersion);
 
     Mockito.when(cluster.getUpgradeInProgress()).thenReturn(upgradeInProgress);
     check = new PrerequisiteCheck(null, null);


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

Posted by jo...@apache.org.
AMBARI-21022 - Upgrades Should Be Associated With Repositories Instead of String Versions (jonathanhurley)


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

Branch: refs/heads/branch-feature-AMBARI-12556
Commit: 522039ebd3f259c2a54db5102108209b94d5d004
Parents: 87e8bdf
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Mon May 15 13:32:05 2017 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Tue May 16 12:45:14 2017 -0400

----------------------------------------------------------------------
 .../actionmanager/ExecutionCommandWrapper.java  |  32 +
 .../ambari/server/agent/ExecutionCommand.java   |  21 +-
 .../alerts/ComponentVersionAlertRunnable.java   |   6 +-
 .../request/AddUpgradeRequestAuditEvent.java    |  10 +-
 .../eventcreator/UpgradeEventCreator.java       |   2 +-
 .../server/checks/PreviousUpgradeCompleted.java |   7 +-
 .../AmbariCustomCommandExecutionHelper.java     |  49 +-
 .../AmbariManagementControllerImpl.java         |  15 +-
 .../AbstractControllerResourceProvider.java     |   2 +-
 .../internal/UpgradeResourceProvider.java       | 708 +++-----------
 .../dao/ServiceComponentDesiredStateDAO.java    |  52 -
 .../ServiceComponentDesiredStateEntity.java     |  36 -
 .../entities/ServiceComponentHistoryEntity.java | 181 ----
 .../server/orm/entities/UpgradeEntity.java      | 165 ++--
 .../orm/entities/UpgradeHistoryEntity.java      | 232 +++++
 .../upgrades/AbstractUpgradeServerAction.java   |  41 -
 .../upgrades/ComponentVersionCheckAction.java   |  14 +-
 .../upgrades/FinalizeUpgradeAction.java         | 292 +++---
 .../upgrades/UpdateDesiredStackAction.java      |  91 +-
 .../ambari/server/stack/MasterHostResolver.java |  56 +-
 .../ambari/server/state/UpgradeContext.java     | 956 +++++++++++++------
 .../server/state/UpgradeContextFactory.java     |  15 +-
 .../ambari/server/state/UpgradeHelper.java      |  37 +-
 .../services/RetryUpgradeActionService.java     |  15 +-
 .../server/state/stack/upgrade/Direction.java   |   9 +
 .../state/stack/upgrade/HostOrderGrouping.java  |  15 +-
 .../server/upgrade/UpgradeCatalog220.java       |   4 +-
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |  27 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |  25 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |  31 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |  27 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |  31 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |  27 +-
 .../src/main/resources/META-INF/persistence.xml |   2 +-
 .../ComponentVersionAlertRunnableTest.java      |   3 +-
 .../creator/UpgradeEventCreatorTest.java        |   4 +-
 .../checks/PreviousUpgradeCompletedTest.java    |   8 +-
 .../StackUpgradeConfigurationMergeTest.java     |  13 +-
 .../internal/UpgradeResourceProviderTest.java   |  73 +-
 .../UpgradeSummaryResourceProviderTest.java     |  14 +-
 .../ambari/server/orm/dao/UpgradeDAOTest.java   |  26 +-
 .../ComponentVersionCheckActionTest.java        |  21 +-
 .../upgrades/UpgradeActionTest.java             | 123 +--
 .../server/state/ServiceComponentTest.java      | 175 ----
 .../ambari/server/state/UpgradeHelperTest.java  | 446 ++++++---
 .../services/RetryUpgradeActionServiceTest.java |   3 +-
 .../stack/upgrade/StageWrapperBuilderTest.java  |  30 +-
 47 files changed, 2012 insertions(+), 2160 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
index fe6707e..f680c09 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ExecutionCommandWrapper.java
@@ -25,11 +25,16 @@ import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.agent.AgentCommand.AgentCommandType;
 import org.apache.ambari.server.agent.ExecutionCommand;
+import org.apache.ambari.server.agent.ExecutionCommand.KeyNames;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.ConfigHelper;
 import org.apache.ambari.server.state.DesiredConfig;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -176,6 +181,33 @@ public class ExecutionCommandWrapper {
                 executionCommand.getConfigurationAttributes().get(type));
             }
         }
+
+        // set the repository version for the component this command is for -
+        // always use the current desired version
+        RepositoryVersionEntity repositoryVersion = null;
+        String serviceName = executionCommand.getServiceName();
+        if (!StringUtils.isEmpty(serviceName)) {
+          Service service = cluster.getService(serviceName);
+          if (null != service) {
+            repositoryVersion = service.getDesiredRepositoryVersion();
+          }
+
+          String componentName = executionCommand.getComponentName();
+          if (!StringUtils.isEmpty(componentName)) {
+            ServiceComponent serviceComponent = service.getServiceComponent(
+                executionCommand.getComponentName());
+
+            if (null != serviceComponent) {
+              repositoryVersion = serviceComponent.getDesiredRepositoryVersion();
+            }
+          }
+        }
+
+        if (null != repositoryVersion) {
+          executionCommand.getCommandParams().put(KeyNames.VERSION, repositoryVersion.getVersion());
+          executionCommand.getHostLevelParams().put(KeyNames.CURRENT_VERSION, repositoryVersion.getVersion());
+        }
+
       }
     } catch (ClusterNotFoundException cnfe) {
       // it's possible that there are commands without clusters; in such cases,

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
index 4ab50ea..d8a4b1e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/ExecutionCommand.java
@@ -158,7 +158,7 @@ public class ExecutionCommand extends AgentCommand {
   }
 
   public Map<String, Map<String, String>> getConfigurationCredentials() {
-    return this.configurationCredentials;
+    return configurationCredentials;
   }
 
   public String getCommandId() {
@@ -462,7 +462,6 @@ public class ExecutionCommand extends AgentCommand {
     String GROUP_LIST = "group_list";
     String USER_GROUPS = "user_groups";
     String NOT_MANAGED_HDFS_PATH_LIST = "not_managed_hdfs_path_list";
-    String VERSION = "version";
     String REFRESH_TOPOLOGY = "refresh_topology";
     String HOST_SYS_PREPPED = "host_sys_prepped";
     String MAX_DURATION_OF_RETRIES = "max_duration_for_retries";
@@ -504,8 +503,24 @@ public class ExecutionCommand extends AgentCommand {
     String REPO_VERSION_ID = "repository_version_id";
 
     /**
-     * Put on hostLevelParams to indicate the version that the component should be.
+     * The version of the component to send down with the command. Normally,
+     * this is simply the repository version of the component. However, during
+     * ugprades, this value may change depending on the progress of the upgrade
+     * and the type/direction.
+     */
+    @Experimental(
+        feature = ExperimentalFeature.PATCH_UPGRADES,
+        comment = "Change this to reflect the component version")
+    String VERSION = "version";
+
+    /**
+     * Put on hostLevelParams to indicate the version that the component should
+     * be.
      */
+    @Deprecated
+    @Experimental(
+        feature = ExperimentalFeature.PATCH_UPGRADES,
+        comment = "This should be replaced by a map of all service component versions")
     String CURRENT_VERSION = "current_version";
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnable.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnable.java b/ambari-server/src/main/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnable.java
index ec5c85e..6bdcf0c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnable.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/alerts/ComponentVersionAlertRunnable.java
@@ -39,6 +39,7 @@ import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.stack.upgrade.Direction;
 import org.apache.commons.lang.StringUtils;
 
 import com.google.inject.Inject;
@@ -63,7 +64,7 @@ public class ComponentVersionAlertRunnable extends AlertRunnable {
   /**
    * The message for the alert when there is an upgrade in progress.
    */
-  private static final String UPGRADE_IN_PROGRESS_MSG = "This alert will be suspended while the upgrade to {0} is in progress.";
+  private static final String UPGRADE_IN_PROGRESS_MSG = "This alert will be suspended while the {0} is in progress.";
 
   /**
    * The unknown component error message.
@@ -95,7 +96,8 @@ public class ComponentVersionAlertRunnable extends AlertRunnable {
     // if there is an upgrade in progress, then skip running this alert
     UpgradeEntity upgrade = cluster.getUpgradeInProgress();
     if (null != upgrade) {
-      String message = MessageFormat.format(UPGRADE_IN_PROGRESS_MSG, upgrade.getToVersion());
+      Direction direction = upgrade.getDirection();
+      String message = MessageFormat.format(UPGRADE_IN_PROGRESS_MSG, direction.getText(false));
 
       return Collections.singletonList(
           buildAlert(cluster, myDefinition, AlertState.SKIPPED, message));

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUpgradeRequestAuditEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUpgradeRequestAuditEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUpgradeRequestAuditEvent.java
index 2c6df7b..215c232 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUpgradeRequestAuditEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/event/request/AddUpgradeRequestAuditEvent.java
@@ -33,7 +33,7 @@ public class AddUpgradeRequestAuditEvent extends RequestAuditEvent {
     /**
      * Repository version
      */
-    private String repositoryVersion;
+    private String repositoryVersionId;
 
     /**
      * Upgrade type (rolling, non-rolling)
@@ -65,8 +65,8 @@ public class AddUpgradeRequestAuditEvent extends RequestAuditEvent {
     protected void buildAuditMessage(StringBuilder builder) {
       super.buildAuditMessage(builder);
 
-      builder.append(", Repository version(")
-        .append(repositoryVersion)
+      builder.append(", Repository version ID(")
+        .append(repositoryVersionId)
         .append("), Upgrade type(")
         .append(upgradeType)
         .append("), Cluster name(")
@@ -74,8 +74,8 @@ public class AddUpgradeRequestAuditEvent extends RequestAuditEvent {
         .append(")");
     }
 
-    public AddUpgradeRequestAuditEventBuilder withRepositoryVersion(String repositoryVersion) {
-      this.repositoryVersion = repositoryVersion;
+    public AddUpgradeRequestAuditEventBuilder withRepositoryVersionId(String repositoryVersionId) {
+      this.repositoryVersionId = repositoryVersionId;
       return this;
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java
index 456aa00..db4549f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/audit/request/eventcreator/UpgradeEventCreator.java
@@ -83,7 +83,7 @@ public class UpgradeEventCreator implements RequestAuditEventCreator {
       .withResultStatus(result.getStatus())
       .withUrl(request.getURI())
       .withRemoteIp(request.getRemoteAddress())
-      .withRepositoryVersion(RequestAuditEventCreatorHelper.getProperty(request, UpgradeResourceProvider.UPGRADE_VERSION))
+      .withRepositoryVersionId(RequestAuditEventCreatorHelper.getProperty(request, UpgradeResourceProvider.UPGRADE_REPO_VERSION_ID))
       .withUpgradeType(RequestAuditEventCreatorHelper.getProperty(request, UpgradeResourceProvider.UPGRADE_TYPE))
       .withClusterName(RequestAuditEventCreatorHelper.getProperty(request, UpgradeResourceProvider.UPGRADE_CLUSTER_NAME))
       .build();

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/checks/PreviousUpgradeCompleted.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/PreviousUpgradeCompleted.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/PreviousUpgradeCompleted.java
index ef165a5..0292b72 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/PreviousUpgradeCompleted.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/PreviousUpgradeCompleted.java
@@ -46,7 +46,7 @@ public class PreviousUpgradeCompleted extends AbstractCheckDescriptor {
   /**
    * The message displayed as part of this pre-upgrade check.
    */
-  public static final String ERROR_MESSAGE = "There is an existing {0} from {1} to {2} which has not completed. This {3} must be completed before a new upgrade or downgrade can begin.";
+  public static final String ERROR_MESSAGE = "There is an existing {0} {1} {2} which has not completed. This {3} must be completed before a new upgrade or downgrade can begin.";
 
   /**
    * Constructor.
@@ -65,9 +65,10 @@ public class PreviousUpgradeCompleted extends AbstractCheckDescriptor {
     if (null != upgradeInProgress) {
       Direction direction = upgradeInProgress.getDirection();
       String directionText = direction.getText(false);
+      String prepositionText = direction.getPreposition();
 
-      errorMessage = MessageFormat.format(ERROR_MESSAGE, directionText,
-          upgradeInProgress.getFromVersion(), upgradeInProgress.getToVersion(), directionText);
+      errorMessage = MessageFormat.format(ERROR_MESSAGE, directionText, prepositionText,
+          upgradeInProgress.getRepositoryVersion().getVersion(), directionText);
     }
 
     if (null != errorMessage) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
index 617d7c0..397c1c2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
@@ -480,19 +480,6 @@ public class AmbariCustomCommandExecutionHelper {
       commandParams.put(SERVICE_PACKAGE_FOLDER, serviceInfo.getServicePackageFolder());
       commandParams.put(HOOKS_FOLDER, stackInfo.getStackHooksFolder());
 
-      RepositoryVersionEntity repoVersion = null;
-      if (null != component) {
-        repoVersion = component.getDesiredRepositoryVersion();
-      }
-
-      if (null == repoVersion && null != clusterService) {
-        repoVersion = clusterService.getDesiredRepositoryVersion();
-      }
-
-      if (repoVersion != null) {
-       commandParams.put(KeyNames.VERSION, repoVersion.getVersion());
-      }
-
       Map<String, String> roleParams = execCmd.getRoleParams();
       if (roleParams == null) {
         roleParams = new TreeMap<>();
@@ -1396,18 +1383,23 @@ public class AmbariCustomCommandExecutionHelper {
    * @return a wrapper of the imporant JSON structures to add to a stage
    */
   public ExecuteCommandJson getCommandJson(ActionExecutionContext actionExecContext,
-      Cluster cluster, StackId stackId) throws AmbariException {
+      Cluster cluster, RepositoryVersionEntity repositoryVersion) throws AmbariException {
 
     Map<String, String> commandParamsStage = StageUtils.getCommandParamsStage(actionExecContext);
     Map<String, String> hostParamsStage = new HashMap<>();
     Map<String, Set<String>> clusterHostInfo;
     String clusterHostInfoJson = "{}";
 
+    StackId stackId = null;
+    if (null != repositoryVersion) {
+      stackId = repositoryVersion.getStackId();
+    }
+
     if (null != cluster) {
       clusterHostInfo = StageUtils.getClusterHostInfo(cluster);
 
       // Important, because this runs during Stack Uprade, it needs to use the effective Stack Id.
-      hostParamsStage = createDefaultHostParams(cluster, null);
+      hostParamsStage = createDefaultHostParams(cluster, repositoryVersion);
 
       String componentName = null;
       String serviceName = null;
@@ -1416,7 +1408,7 @@ public class AmbariCustomCommandExecutionHelper {
         serviceName = actionExecContext.getOperationLevel().getServiceName();
       }
 
-      if (serviceName != null && componentName != null) {
+      if (serviceName != null && componentName != null && null != stackId) {
         ComponentInfo componentInfo = ambariMetaInfo.getComponent(
                 stackId.getStackName(), stackId.getStackVersion(),
                 serviceName, componentName);
@@ -1428,17 +1420,22 @@ public class AmbariCustomCommandExecutionHelper {
         String clientsToUpdateConfigs = gson.toJson(clientsToUpdateConfigsList);
         hostParamsStage.put(CLIENTS_TO_UPDATE_CONFIGS, clientsToUpdateConfigs);
       }
+
       clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo);
 
       //Propogate HCFS service type info to command params
-      Map<String, ServiceInfo> serviceInfos = ambariMetaInfo.getServices(stackId.getStackName(), stackId.getStackVersion());
-      for (ServiceInfo serviceInfoInstance : serviceInfos.values()) {
-        if (serviceInfoInstance.getServiceType() != null) {
-          LOG.debug("Adding {} to command parameters for {}", serviceInfoInstance.getServiceType(),
-              serviceInfoInstance.getName());
-
-          commandParamsStage.put("dfs_type", serviceInfoInstance.getServiceType());
-          break;
+      if (null != stackId) {
+        Map<String, ServiceInfo> serviceInfos = ambariMetaInfo.getServices(stackId.getStackName(),
+            stackId.getStackVersion());
+
+        for (ServiceInfo serviceInfoInstance : serviceInfos.values()) {
+          if (serviceInfoInstance.getServiceType() != null) {
+            LOG.debug("Adding {} to command parameters for {}",
+                serviceInfoInstance.getServiceType(), serviceInfoInstance.getName());
+
+            commandParamsStage.put("dfs_type", serviceInfoInstance.getServiceType());
+            break;
+          }
         }
       }
     }
@@ -1482,10 +1479,6 @@ public class AmbariCustomCommandExecutionHelper {
     String notManagedHdfsPathList = gson.toJson(notManagedHdfsPathSet);
     hostLevelParams.put(NOT_MANAGED_HDFS_PATH_LIST, notManagedHdfsPathList);
 
-    if (null != repositoryVersion) {
-      hostLevelParams.put(KeyNames.CURRENT_VERSION, repositoryVersion.getVersion());
-    }
-
     for (Map.Entry<String, String> dbConnectorName : configs.getDatabaseConnectorNames().entrySet()) {
       hostLevelParams.put(dbConnectorName.getKey(), dbConnectorName.getValue());
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 882f583..a4f59a5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -3988,12 +3988,19 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         actionManager,
         actionRequest);
 
-    StackId stackId = null;
-    if (null != cluster) {
-      stackId = cluster.getDesiredStackVersion();
+    RepositoryVersionEntity desiredRepositoryVersion = null;
+
+    RequestOperationLevel operationLevel = actionExecContext.getOperationLevel();
+    if (null != operationLevel) {
+      Service service = cluster.getService(operationLevel.getServiceName());
+      if (null != service) {
+        desiredRepositoryVersion = service.getDesiredRepositoryVersion();
+      }
     }
 
-    ExecuteCommandJson jsons = customCommandExecutionHelper.getCommandJson(actionExecContext, cluster, stackId);
+    ExecuteCommandJson jsons = customCommandExecutionHelper.getCommandJson(actionExecContext,
+        cluster, desiredRepositoryVersion);
+
     String commandParamsForStage = jsons.getCommandParamsForStage();
 
     Map<String, String> commandParamsStage = gson.fromJson(commandParamsForStage, new TypeToken<Map<String, String>>()

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index a762e2b..77e6250 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -266,7 +266,7 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
    *
    * @return resource provider for the specified type
    */
-  ResourceProvider getResourceProvider(Resource.Type type) {
+  public static ResourceProvider getResourceProvider(Resource.Type type) {
     return ((ClusterControllerImpl) ClusterControllerHelper.getClusterController()).
         ensureResourceProvider(type);
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/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 7ca6164..c3691bf 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
@@ -23,13 +23,11 @@ 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,8 +63,6 @@ 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;
@@ -78,20 +74,20 @@ 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.RepositoryType;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.StackInfo;
@@ -99,33 +95,26 @@ import org.apache.ambari.server.state.UpgradeContext;
 import org.apache.ambari.server.state.UpgradeContextFactory;
 import org.apache.ambari.server.state.UpgradeHelper;
 import org.apache.ambari.server.state.UpgradeHelper.UpgradeGroupHolder;
-import org.apache.ambari.server.state.repository.VersionDefinitionXml;
 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.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;
@@ -140,12 +129,12 @@ 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_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_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";
@@ -154,7 +143,6 @@ 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}
@@ -169,17 +157,17 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   /**
    * 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
@@ -200,7 +188,7 @@ 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";
 
   /*
    * Lifted from RequestResourceProvider
@@ -217,6 +205,7 @@ 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<>();
 
   /**
@@ -267,9 +256,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.
@@ -280,12 +266,12 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   static {
     // properties
     PROPERTY_IDS.add(UPGRADE_CLUSTER_NAME);
-    PROPERTY_IDS.add(UPGRADE_VERSION);
+    PROPERTY_IDS.add(UPGRADE_REPO_VERSION_ID);
     PROPERTY_IDS.add(UPGRADE_TYPE);
     PROPERTY_IDS.add(UPGRADE_PACK);
     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);
@@ -305,6 +291,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     PROPERTY_IDS.add(REQUEST_STATUS_PROPERTY_ID);
     PROPERTY_IDS.add(REQUEST_TYPE_ID);
 
+    PROPERTY_IDS.add("Upgrade/from_version");
+    PROPERTY_IDS.add("Upgrade/to_version");
+
     // keys
     KEY_PROPERTY_IDS.put(Resource.Type.Upgrade, UPGRADE_REQUEST_ID);
     KEY_PROPERTY_IDS.put(Resource.Type.Cluster, UPGRADE_CLUSTER_NAME);
@@ -355,32 +344,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)));
-          }
-        }
-
-        // the version being upgraded or downgraded to (ie 2.2.1.0-1234)
-        final String version = (String) requestMap.get(UPGRADE_VERSION);
-
-        final UpgradeContext upgradeContext = s_upgradeContextFactory.create(cluster, upgradeType,
-            direction, version, 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);
@@ -598,47 +563,33 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     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.getFromVersion(), requestedIds);
-    setResourceProperty(resource, UPGRADE_TO_VERSION, entity.getToVersion(), 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 the map of properties
-   * @return the validated upgrade pack
-   * @throws AmbariException
-   */
-  private UpgradePack validateRequest(UpgradeContext upgradeContext) throws AmbariException {
-    Cluster cluster = upgradeContext.getCluster();
-    Direction direction = upgradeContext.getDirection();
-    Map<String, Object> requestMap = upgradeContext.getUpgradeRequest();
-    UpgradeType upgradeType = upgradeContext.getType();
+    // 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 = (String) requestMap.get(UPGRADE_VERSION);
-    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, 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;
   }
 
   /**
@@ -698,112 +649,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     UpgradePack pack = upgradeContext.getUpgradePack();
     Cluster cluster = upgradeContext.getCluster();
     Direction direction = upgradeContext.getDirection();
-    Map<String, Object> requestMap = upgradeContext.getUpgradeRequest();
-    UpgradeType upgradeType = upgradeContext.getType();
 
     ConfigHelper configHelper = getManagementController().getConfigHelper();
 
-    // the upgrade context calculated these for us based on direction
-    StackId sourceStackId = upgradeContext.getOriginalStackId();
-
-    // the version being upgraded or downgraded to (ie 2.2.1.0-1234)
-    final String version = upgradeContext.getVersion();
-
-    MasterHostResolver resolver = null;
-    if (direction.isUpgrade()) {
-      resolver = new MasterHostResolver(configHelper, cluster);
-    } else {
-      resolver = new MasterHostResolver(configHelper, cluster, version);
-    }
-
-    Set<String> supportedServices = new HashSet<>();
-    UpgradeScope scope = UpgradeScope.COMPLETE;
-
-    switch (direction) {
-      case UPGRADE:
-        RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion();
-        RepositoryType repositoryType = targetRepositoryVersion.getType();
-
-        // !!! Consult the version definition and add the service names to supportedServices
-        if (repositoryType != RepositoryType.STANDARD) {
-          scope = UpgradeScope.PARTIAL;
-
-          try {
-            VersionDefinitionXml vdf = targetRepositoryVersion.getRepositoryXml();
-            supportedServices.addAll(vdf.getAvailableServiceNames());
-
-            // if this is every true, then just stop the upgrade attempt and
-            // throw an exception
-            if (supportedServices.isEmpty()) {
-              String message = String.format(
-                  "When using a VDF of type %s, the available services must be defined in the VDF",
-                  targetRepositoryVersion.getType());
-              throw new AmbariException(message);
-            }
-
-          } catch (Exception e) {
-            String msg = String.format("Could not parse version definition for %s.  Upgrade will not proceed.", version);
-            LOG.error(msg, e);
-            throw new AmbariException(msg);
-          }
-        }
-
-        break;
-      case DOWNGRADE:
-        break;
-    }
-
-    upgradeContext.setResolver(resolver);
-    upgradeContext.setSupportedServices(supportedServices);
-    upgradeContext.setScope(scope);
-
-    @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES,
-        comment = "Check for any other way downgrade to get set, if required")
-    String downgradeFromVersion = null;
-
-    if (direction.isDowngrade()) {
-      if (requestMap.containsKey(UPGRADE_FROM_VERSION)) {
-        downgradeFromVersion = (String) requestMap.get(UPGRADE_FROM_VERSION);
-      } else {
-        UpgradeEntity lastUpgradeItemForCluster = s_upgradeDAO.findLastUpgradeForCluster(
-            cluster.getClusterId(), Direction.UPGRADE);
-
-        downgradeFromVersion = lastUpgradeItemForCluster.getToVersion();
-      }
-
-      if (null == downgradeFromVersion) {
-        throw new AmbariException("When downgrading, the downgrade version must be specified");
-      }
-
-      upgradeContext.setDowngradeFromVersion(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);
-
     List<UpgradeGroupHolder> groups = s_upgradeHelper.createSequence(pack, upgradeContext);
 
     if (groups.isEmpty()) {
@@ -828,7 +676,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     }
 
     List<UpgradeGroupEntity> groupEntities = new ArrayList<>();
-    RequestStageContainer req = createRequest(direction, version);
+    RequestStageContainer req = createRequest(upgradeContext);
 
     /**
     During a Rolling Upgrade, change the desired Stack Id if jumping across
@@ -849,21 +697,24 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
       s_upgradeHelper.putComponentsToUpgradingState(upgradeContext);
     }
 
+    @Experimental(feature = ExperimentalFeature.PATCH_UPGRADES, comment = "This is wrong")
+    StackId configurationPackSourceStackId = upgradeContext.getRepositoryVersion().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, sourceStackId);
+    ConfigUpgradePack configUpgradePack = ConfigurationPackBuilder.build(pack,
+        configurationPackSourceStackId);
 
     // create the upgrade and request
     for (UpgradeGroupHolder group : groups) {
-      boolean skippable = group.skippable;
-      boolean supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
-      boolean allowRetry = group.allowRetry;
-
       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
@@ -882,20 +733,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
               itemEntity.setHosts(wrapper.getHostsJson());
               itemEntities.add(itemEntity);
 
-              // At this point, need to change the effective Stack Id so that subsequent tasks run on the newer value.
-              if (upgradeType == UpgradeType.NON_ROLLING && UpdateStackGrouping.class.equals(group.groupClass)) {
-                if (direction.isUpgrade()) {
-                  upgradeContext.setEffectiveStackId(upgradeContext.getTargetStackId());
-                } else {
-                  upgradeContext.setEffectiveStackId(upgradeContext.getOriginalStackId());
-                }
-              } else if (UpdateStackGrouping.class.equals(group.groupClass)) {
-                upgradeContext.setEffectiveStackId(upgradeContext.getTargetStackId());
-              }
-
               injectVariables(configHelper, cluster, itemEntity);
-              makeServerSideStage(upgradeContext, req, itemEntity, (ServerSideActionTask) task,
-                  skippable, supportsAutoSkipOnFailure, allowRetry, pack, configUpgradePack);
+              makeServerSideStage(group, upgradeContext, effectiveRepositoryVersion, req,
+                  itemEntity, (ServerSideActionTask) task, configUpgradePack);
             }
           }
         } else {
@@ -908,8 +748,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
           injectVariables(configHelper, cluster, itemEntity);
 
           // upgrade items match a stage
-          createStage(upgradeContext, req, itemEntity, wrapper, skippable,
-              supportsAutoSkipOnFailure, allowRetry);
+          createStage(group, upgradeContext, effectiveRepositoryVersion, req, itemEntity, wrapper);
         }
       }
 
@@ -923,21 +762,14 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     }
 
     UpgradeEntity entity = new UpgradeEntity();
-
-    if (null != downgradeFromVersion) {
-      entity.setFromVersion(downgradeFromVersion);
-    } else {
-      entity.setFromVersion("");
-    }
-
-    entity.setToVersion(version);
+    entity.setRepositoryVersion(upgradeContext.getRepositoryVersion());
     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.setAutoSkipComponentFailures(upgradeContext.isComponentFailureAutoSkipped());
+    entity.setAutoSkipServiceCheckFailures(upgradeContext.isServiceCheckFailureAutoSkipped());
 
     if (upgradeContext.getDirection().isDowngrade()) {
       // !!! You can't downgrade a Downgrade, no matter what the upgrade pack says.
@@ -946,6 +778,37 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
       entity.setDowngradeAllowed(pack.isDowngradeAllowed());
     }
 
+    // set upgrade history for every component in the upgrade
+    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(entity);
+        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) {
+          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);
+
+          history.setFromRepositoryVersion(upgradeContext.getRepositoryVersion());
+          history.setTargetRepositoryVersion(targetRepositoryVersion);
+        }
+
+        // add the history
+        entity.addHistory(history);
+      }
+    }
+
     req.getRequestStatusResponse();
     return createUpgradeInsideTransaction(cluster, req, entity);
   }
@@ -1014,8 +877,8 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     Cluster cluster = upgradeContext.getCluster();
     Direction direction = upgradeContext.getDirection();
     UpgradePack upgradePack = upgradeContext.getUpgradePack();
-    String stackName = upgradeContext.getTargetStackId().getStackName();
-    String version = upgradeContext.getVersion();
+    String stackName = upgradeContext.getRepositoryVersion().getStackId().getStackName();
+    String version = upgradeContext.getRepositoryVersion().getStackId().getStackVersion();
     String userName = getManagementController().getAuthName();
 
     RepositoryVersionEntity targetRve = s_repoVersionDAO.findByStackNameAndVersion(stackName, version);
@@ -1250,36 +1113,45 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     }
   }
 
-  private RequestStageContainer createRequest(Direction direction, String version) {
+  private RequestStageContainer createRequest(UpgradeContext upgradeContext) {
     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), version));
+
+    Direction direction = upgradeContext.getDirection();
+    RepositoryVersionEntity repositoryVersion = upgradeContext.getRepositoryVersion();
+
+    requestStages.setRequestContext(String.format("%s %s %s", direction.getVerb(true),
+        direction.getPreposition(), repositoryVersion.getVersion()));
 
     return requestStages;
   }
 
-  private void createStage(UpgradeContext context, RequestStageContainer request,
-      UpgradeItemEntity entity, StageWrapper wrapper, boolean skippable,
-      boolean supportsAutoSkipOnFailure, boolean allowRetry)
+  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, entity, wrapper, skippable, supportsAutoSkipOnFailure,
-            allowRetry);
+        makeCommandStage(context, request, effectiveRepositoryVersion, entity, wrapper, skippable,
+            supportsAutoSkipOnFailure, allowRetry);
         break;
       case RU_TASKS:
-        makeActionStage(context, request, entity, wrapper, skippable, supportsAutoSkipOnFailure,
-            allowRetry);
+        makeActionStage(context, request, effectiveRepositoryVersion, entity, wrapper, skippable,
+            supportsAutoSkipOnFailure, allowRetry);
         break;
       case SERVICE_CHECK:
-        makeServiceCheckStage(context, request, entity, wrapper, skippable,
-            supportsAutoSkipOnFailure, allowRetry);
+        makeServiceCheckStage(context, request, effectiveRepositoryVersion, entity, wrapper,
+            skippable, supportsAutoSkipOnFailure, allowRetry);
         break;
       default:
         break;
@@ -1302,9 +1174,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   }
 
   private void makeActionStage(UpgradeContext context, RequestStageContainer request,
-      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(
@@ -1328,7 +1200,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     // service, it is necessary to set the
     // service_package_folder and hooks_folder params.
     AmbariMetaInfo ambariMetaInfo = s_metaProvider.get();
-    StackId stackId = context.getEffectiveStackId();
+    StackId stackId = effectiveRepositoryVersion.getStackId();
 
     StackInfo stackInfo = ambariMetaInfo.getStack(stackId.getStackName(),
         stackId.getStackVersion());
@@ -1354,7 +1226,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
-        cluster, context.getEffectiveStackId());
+        cluster, effectiveRepositoryVersion);
 
     Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari",
         cluster.getClusterName(), cluster.getClusterId(), entity.getText(),
@@ -1395,9 +1267,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
    * @throws AmbariException
    */
   private void makeCommandStage(UpgradeContext context, RequestStageContainer request,
-      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();
 
@@ -1437,7 +1309,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     actionContext.setMaintenanceModeHostExcluded(true);
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
-        cluster, context.getEffectiveStackId());
+        cluster, effectiveRepositoryVersion);
 
     Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari",
         cluster.getClusterName(), cluster.getClusterId(), entity.getText(),
@@ -1470,9 +1342,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
   }
 
   private void makeServiceCheckStage(UpgradeContext context, RequestStageContainer request,
-      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<>();
 
@@ -1499,7 +1371,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     actionContext.setMaintenanceModeHostExcluded(true);
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
-        cluster, context.getEffectiveStackId());
+        cluster, effectiveRepositoryVersion);
 
     Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari",
         cluster.getClusterName(), cluster.getClusterId(), entity.getText(),
@@ -1536,13 +1408,13 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
    * upgrade
    * @throws AmbariException
    */
-  private void makeServerSideStage(UpgradeContext context, RequestStageContainer request,
-      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());
@@ -1624,21 +1496,21 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         commandParams);
 
     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, context.getEffectiveStackId());
+        cluster, null);
 
     Stage stage = s_stageFactory.get().createNew(request.getId().longValue(), "/tmp/ambari",
         cluster.getClusterName(), cluster.getClusterId(), stageText, jsons.getClusterHostInfo(),
         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) {
@@ -1652,7 +1524,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));
@@ -1663,11 +1535,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,
@@ -1778,57 +1646,6 @@ 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
-   *
-   * @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.
-   */
-  @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"));
-      }
-
-      if (CollectionUtils.isNotEmpty(hosts)) {
-        hostOrderItems.add(new HostOrderItem(HostOrderActionType.HOST_UPGRADE, hosts));
-      }
-
-      if (CollectionUtils.isNotEmpty(serviceChecks)) {
-        hostOrderItems.add(new HostOrderItem(HostOrderActionType.SERVICE_CHECK, serviceChecks));
-      }
-    }
-
-    return hostOrderItems;
-  }
-
-  /**
    * Builds the correct {@link ConfigUpgradePack} based on the upgrade and
    * source stack.
    * <ul>
@@ -1887,267 +1704,34 @@ 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.
-   */
-  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;
-    }
-
-    preReqValidator.setNextValidator(upgradeTypeValidator);
-    return validator;
-  }
-
-  /**
-   * 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.
+   * The {@link RepositoryVersions} class is used to represent to/from versions
+   * of a service during an upgrade or downgrade.
    */
-  private abstract class UpgradeRequestValidator {
-    /**
-     * The next validator.
-     */
-    UpgradeRequestValidator m_nextValidator;
+  final static class RepositoryVersions {
+    @JsonProperty("from_repository_id")
+    final long fromRepositoryId;
 
-    /**
-     * 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;
-    }
+    @JsonProperty("from_repository_version")
+    final String fromRepositoryVersion;
 
-    /**
-     * 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 {
+    @JsonProperty("to_repository_id")
+    final long toRepositoryId;
 
-      // run this instance's check
-      check(upgradeContext, upgradePack);
-
-      // pass along to the next
-      if( null != m_nextValidator ) {
-        m_nextValidator.validate(upgradeContext, upgradePack);
-      }
-    }
+    @JsonProperty("to_repository_version")
+    final String toRepositoryVersion;
 
     /**
-     * Checks to ensure that upgrade request is valid given the specific
-     * arguments.
+     * Constructor.
      *
-     * @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 version = (String) requestMap.get(UPGRADE_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(version)) {
-        throw new AmbariException(String.format("%s is required", UPGRADE_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_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 {
-
-    /**
-     * {@inheritDoc}
+     * @param from
+     * @param target
      */
-    @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));
-      }
+    public RepositoryVersions(RepositoryVersionEntity from, RepositoryVersionEntity to) {
+      fromRepositoryId = from.getId();
+      fromRepositoryVersion = from.getVersion();
 
-      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());
-      }
-
-      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/522039eb/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
index 92f1d09..a65a94a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
@@ -20,14 +20,12 @@ package org.apache.ambari.server.orm.dao;
 
 import java.util.List;
 
-import javax.persistence.CascadeType;
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
 
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
-import org.apache.ambari.server.orm.entities.ServiceComponentHistoryEntity;
 import org.apache.ambari.server.orm.entities.ServiceComponentVersionEntity;
 
 import com.google.inject.Inject;
@@ -130,56 +128,6 @@ public class ServiceComponentDesiredStateDAO {
   }
 
   /**
-   * Creates a service component upgrade/downgrade historical event.
-   *
-   * @param serviceComponentHistoryEntity
-   */
-  @Transactional
-  public void create(ServiceComponentHistoryEntity serviceComponentHistoryEntity) {
-    entityManagerProvider.get().persist(serviceComponentHistoryEntity);
-  }
-
-  /**
-   * Merges a service component upgrade/downgrade historical event, creating it
-   * in the process if it does not already exist. The associated
-   * {@link ServiceComponentDesiredStateEntity} is automatically merged via its
-   * {@link CascadeType}.
-   *
-   * @param serviceComponentHistoryEntity
-   * @return
-   */
-  @Transactional
-  public ServiceComponentHistoryEntity merge(
-      ServiceComponentHistoryEntity serviceComponentHistoryEntity) {
-    return entityManagerProvider.get().merge(serviceComponentHistoryEntity);
-  }
-
-  /**
-   * Gets the history for a component.
-   *
-   * @param clusterId
-   *          the component's cluster.
-   * @param serviceName
-   *          the component's service (not {@code null}).
-   * @param componentName
-   *          the component's name (not {@code null}).
-   * @return
-   */
-  @RequiresSession
-  public List<ServiceComponentHistoryEntity> findHistory(long clusterId, String serviceName,
-      String componentName) {
-    EntityManager entityManager = entityManagerProvider.get();
-    TypedQuery<ServiceComponentHistoryEntity> query = entityManager.createNamedQuery(
-        "ServiceComponentHistoryEntity.findByComponent", ServiceComponentHistoryEntity.class);
-
-    query.setParameter("clusterId", clusterId);
-    query.setParameter("serviceName", serviceName);
-    query.setParameter("componentName", componentName);
-
-    return daoUtils.selectList(query);
-  }
-
-  /**
    * @param clusterId     the cluster id
    * @param serviceName   the service name
    * @param componentName the component name

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
index 7576e00..baba85e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentDesiredStateEntity.java
@@ -113,15 +113,6 @@ public class ServiceComponentDesiredStateEntity {
   @OneToMany(mappedBy = "serviceComponentDesiredStateEntity")
   private Collection<HostComponentDesiredStateEntity> hostComponentDesiredStateEntities;
 
-  /**
-   * All of the upgrades and downgrades which have occurred for this component.
-   * Can be {@code null} for none.
-   */
-  @OneToMany(
-      mappedBy = "m_serviceComponentDesiredStateEntity",
-      cascade = { CascadeType.ALL })
-  private Collection<ServiceComponentHistoryEntity> serviceComponentHistory;
-
   @OneToMany(mappedBy = "m_serviceComponentDesiredStateEntity", cascade = { CascadeType.ALL })
   private Collection<ServiceComponentVersionEntity> serviceComponentVersions;
 
@@ -178,33 +169,6 @@ public class ServiceComponentDesiredStateEntity {
   }
 
   /**
-   * Adds a historical entry for the version of this service component. New
-   * entries are automatically created when this entity is merged via a
-   * {@link CascadeType#MERGE}.
-   *
-   * @param historicalEntry
-   *          the entry to add.
-   */
-  public void addHistory(ServiceComponentHistoryEntity historicalEntry) {
-    if (null == serviceComponentHistory) {
-      serviceComponentHistory = new ArrayList<>();
-    }
-
-    serviceComponentHistory.add(historicalEntry);
-    historicalEntry.setServiceComponentDesiredState(this);
-  }
-
-  /**
-   * Gets the history of this component's upgrades and downgrades.
-   *
-   * @return the component history, or {@code null} if none.
-   */
-  public Collection<ServiceComponentHistoryEntity> getHistory() {
-    return serviceComponentHistory;
-  }
-
-
-  /**
    * @param versionEntity the version to add
    */
   public void addVersion(ServiceComponentVersionEntity versionEntity) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/522039eb/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentHistoryEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentHistoryEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentHistoryEntity.java
deleted file mode 100644
index 1521468..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceComponentHistoryEntity.java
+++ /dev/null
@@ -1,181 +0,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.
- */
-package org.apache.ambari.server.orm.entities;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import javax.persistence.TableGenerator;
-
-import org.apache.commons.lang.builder.HashCodeBuilder;
-
-import com.google.common.base.Objects;
-
-/**
- * The {@link ServiceComponentHistoryEntity} class is used to represent an
- * upgrade or downgrade which was performed on an individual service component.
- */
-@Entity
-@Table(name = "servicecomponent_history")
-@TableGenerator(
-    name = "servicecomponent_history_id_generator",
-    table = "ambari_sequences",
-    pkColumnName = "sequence_name",
-    valueColumnName = "sequence_value",
-    pkColumnValue = "servicecomponent_history_id_seq",
-    initialValue = 0)
-@NamedQueries({ @NamedQuery(
-    name = "ServiceComponentHistoryEntity.findByComponent",
-    query = "SELECT history FROM ServiceComponentHistoryEntity history WHERE history.m_serviceComponentDesiredStateEntity.clusterId = :clusterId AND history.m_serviceComponentDesiredStateEntity.serviceName = :serviceName AND history.m_serviceComponentDesiredStateEntity.componentName = :componentName") })
-public class ServiceComponentHistoryEntity {
-
-  @Id
-  @GeneratedValue(
-      strategy = GenerationType.TABLE,
-      generator = "servicecomponent_history_id_generator")
-  @Column(name = "id", nullable = false, updatable = false)
-  private long m_id;
-
-  @ManyToOne(optional = false, cascade = { CascadeType.MERGE })
-  @JoinColumn(name = "component_id", referencedColumnName = "id", nullable = false)
-  private ServiceComponentDesiredStateEntity m_serviceComponentDesiredStateEntity;
-
-  @ManyToOne(optional = false)
-  @JoinColumn(name = "from_stack_id", referencedColumnName = "stack_id", nullable = false)
-  private StackEntity m_fromStack;
-
-  @ManyToOne(optional = false)
-  @JoinColumn(name = "to_stack_id", referencedColumnName = "stack_id", nullable = false)
-  private StackEntity m_toStack;
-
-  @ManyToOne(optional = false)
-  @JoinColumn(name = "upgrade_id", referencedColumnName = "upgrade_id", nullable = false)
-  private UpgradeEntity m_upgradeEntity;
-
-  public ServiceComponentDesiredStateEntity getServiceComponentDesiredState() {
-    return m_serviceComponentDesiredStateEntity;
-  }
-
-  /**
-   * Sets the component associated with this historical entry.
-   *
-   * @param serviceComponentDesiredStateEntity
-   *          the component to associate with this historical entry (not
-   *          {@code null}).
-   */
-  public void setServiceComponentDesiredState(ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity) {
-    m_serviceComponentDesiredStateEntity = serviceComponentDesiredStateEntity;
-  }
-
-  /**
-   * @return the id
-   */
-  public long getId() {
-    return m_id;
-  }
-
-  /**
-   * @return the fromStack
-   */
-  public StackEntity getFromStack() {
-    return m_fromStack;
-  }
-
-  /**
-   * @param fromStack
-   *          the fromStack to set
-   */
-  public void setFromStack(StackEntity fromStack) {
-    m_fromStack = fromStack;
-  }
-
-  /**
-   * @return the toStack
-   */
-  public StackEntity getToStack() {
-    return m_toStack;
-  }
-
-  /**
-   * @param toStack
-   *          the toStack to set
-   */
-  public void setToStack(StackEntity toStack) {
-    m_toStack = toStack;
-  }
-
-  /**
-   * @return the upgradeEntity
-   */
-  public UpgradeEntity getUpgrade() {
-    return m_upgradeEntity;
-  }
-
-  /**
-   * @param upgradeEntity
-   *          the upgradeEntity to set
-   */
-  public void setUpgrade(UpgradeEntity upgradeEntity) {
-    m_upgradeEntity = upgradeEntity;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public int hashCode() {
-    HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
-    hashCodeBuilder.append(m_fromStack);
-    hashCodeBuilder.append(m_toStack);
-    hashCodeBuilder.append(m_upgradeEntity);
-    hashCodeBuilder.append(m_serviceComponentDesiredStateEntity);
-    return hashCodeBuilder.toHashCode();
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean equals(Object obj) {
-    if (this == obj) {
-      return true;
-    }
-
-    if (obj == null) {
-      return false;
-    }
-
-    if (getClass() != obj.getClass()) {
-      return false;
-    }
-
-    final ServiceComponentHistoryEntity other = (ServiceComponentHistoryEntity) obj;
-    return Objects.equal(m_fromStack, other.m_fromStack)
-        && Objects.equal(m_toStack, other.m_toStack)
-        && Objects.equal(m_upgradeEntity, other.m_upgradeEntity) 
-        && Objects.equal(m_serviceComponentDesiredStateEntity, other.m_serviceComponentDesiredStateEntity);
-  }
-}