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/03 15:13:56 UTC

[9/9] ambari git commit: AMBARI-20894 - Setting Desired Stack Ids to Correct Values During Service and Patch Upgrades (jonathanhurley)

AMBARI-20894 - Setting Desired Stack Ids to Correct Values During Service and Patch Upgrades (jonathanhurley)


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

Branch: refs/heads/branch-feature-AMBARI-12556
Commit: dcbd826c96b91c718caa519f44663b9a73f17da6
Parents: b686624
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Fri Apr 28 17:40:42 2017 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Wed May 3 11:13:19 2017 -0400

----------------------------------------------------------------------
 .../libraries/script/script.py                  |    7 +
 .../ambari/server/agent/HeartbeatProcessor.java |   15 +-
 .../alerts/ComponentVersionAlertRunnable.java   |   45 +-
 .../checks/DatabaseConsistencyCheckHelper.java  |    7 +-
 .../AmbariManagementControllerImpl.java         |   11 +-
 .../controller/ServiceComponentHostRequest.java |   19 +-
 .../ServiceComponentHostResponse.java           |   39 +-
 .../server/controller/ServiceRequest.java       |   27 +-
 .../server/controller/ServiceResponse.java      |   38 +-
 .../ClusterStackVersionResourceProvider.java    |  130 --
 .../internal/ComponentResourceProvider.java     |    2 +-
 .../internal/HostComponentResourceProvider.java |   27 +-
 .../internal/ServiceResourceProvider.java       |   43 +-
 .../internal/UpgradeResourceProvider.java       |   84 +-
 .../DistributeRepositoriesActionListener.java   |   10 +-
 .../listeners/upgrade/StackVersionListener.java |    5 +-
 .../ambari/server/orm/dao/HostVersionDAO.java   |   24 +-
 .../HostComponentDesiredStateEntity.java        |   21 -
 .../orm/entities/HostComponentStateEntity.java  |   22 -
 .../server/orm/entities/HostVersionEntity.java  |   41 +-
 .../ServiceComponentDesiredStateEntity.java     |   79 +-
 .../orm/entities/ServiceDesiredStateEntity.java |   85 +-
 .../PrepareDisableKerberosServerAction.java     |    4 +-
 .../upgrades/AbstractUpgradeServerAction.java   |   42 +-
 .../upgrades/ComponentVersionCheckAction.java   |    7 +-
 .../upgrades/FinalizeUpgradeAction.java         |  330 ++---
 .../upgrades/UpdateDesiredStackAction.java      |  112 +-
 .../org/apache/ambari/server/state/Cluster.java |   28 +-
 .../org/apache/ambari/server/state/Service.java |   13 +-
 .../ambari/server/state/ServiceComponent.java   |   12 +-
 .../server/state/ServiceComponentHost.java      |   15 +-
 .../server/state/ServiceComponentImpl.java      |   42 +-
 .../ambari/server/state/ServiceFactory.java     |   25 +-
 .../apache/ambari/server/state/ServiceImpl.java |   73 +-
 .../ambari/server/state/UpgradeContext.java     |   38 +-
 .../ambari/server/state/UpgradeHelper.java      |   55 +-
 .../server/state/cluster/ClusterImpl.java       |  116 +-
 .../svccomphost/ServiceComponentHostImpl.java   |  101 +-
 .../ambari/server/topology/AmbariContext.java   |   11 +-
 .../server/upgrade/AbstractUpgradeCatalog.java  |    2 -
 .../server/upgrade/StackUpgradeHelper.java      |  171 ---
 .../ambari/server/upgrade/StackUpgradeUtil.java |  198 ---
 ambari-server/src/main/python/ambari-server.py  |    7 +-
 .../main/python/ambari_server/serverUpgrade.py  |  140 --
 .../main/python/ambari_server/setupActions.py   |    1 -
 .../main/resources/Ambari-DDL-Derby-CREATE.sql  |   13 +-
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   13 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   13 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   14 +-
 .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql |   13 +-
 .../resources/Ambari-DDL-SQLServer-CREATE.sql   |   13 +-
 .../src/main/resources/properties.json          |    6 +-
 .../server/agent/DummyHeartbeatConstants.java   |    1 +
 .../server/agent/HeartbeatProcessorTest.java    |  149 +--
 .../server/agent/HeartbeatTestHelper.java       |   16 +-
 .../server/agent/TestHeartbeatHandler.java      |   55 +-
 .../server/agent/TestHeartbeatMonitor.java      |   29 +-
 .../ComponentVersionAlertRunnableTest.java      |   28 +-
 .../resources/BaseResourceDefinitionTest.java   |   22 +-
 .../server/api/services/AmbariMetaInfoTest.java |   16 +-
 .../configuration/RecoveryConfigHelperTest.java |   50 +-
 .../AmbariCustomCommandExecutionHelperTest.java |   45 +-
 .../AmbariManagementControllerTest.java         | 1252 +++++-------------
 .../BackgroundCustomCommandExecutionTest.java   |   24 +-
 .../server/controller/KerberosHelperTest.java   |   20 -
 ...hYarnCapacitySchedulerReleaseConfigTest.java |   74 +-
 .../AbstractControllerResourceProviderTest.java |    9 +-
 .../internal/AbstractResourceProviderTest.java  |   31 +-
 .../ClientConfigResourceProviderTest.java       |    8 +-
 ...ClusterStackVersionResourceProviderTest.java |  319 -----
 .../HostComponentResourceProviderTest.java      |   45 +-
 .../internal/HostResourceProviderTest.java      |   26 +-
 .../internal/JMXHostProviderTest.java           |   34 +-
 .../controller/internal/RequestImplTest.java    |    3 +-
 .../internal/ServiceResourceProviderTest.java   |   65 +-
 .../StackUpgradeConfigurationMergeTest.java     |   20 +-
 .../UpgradeResourceProviderHDP22Test.java       |   13 +-
 .../internal/UpgradeResourceProviderTest.java   |   69 +-
 .../UpgradeSummaryResourceProviderTest.java     |    3 +-
 .../GeneralServiceCalculatedStateTest.java      |   11 +-
 .../apache/ambari/server/events/EventsTest.java |   17 +-
 .../HostVersionOutOfSyncListenerTest.java       |   34 +-
 .../upgrade/StackVersionListenerTest.java       |    4 -
 .../apache/ambari/server/orm/OrmTestHelper.java |   16 +-
 .../ComponentVersionCheckActionTest.java        |   75 +-
 .../upgrades/ConfigureActionTest.java           |   19 +-
 .../upgrades/UpgradeActionTest.java             |  131 +-
 .../server/state/ServiceComponentTest.java      |  124 +-
 .../apache/ambari/server/state/ServiceTest.java |   74 +-
 .../ambari/server/state/UpgradeHelperTest.java  |   98 +-
 .../state/alerts/AlertEventPublisherTest.java   |   11 +-
 .../state/alerts/InitialAlertEventTest.java     |   16 +-
 .../state/cluster/ClusterDeadlockTest.java      |    9 +-
 .../server/state/cluster/ClusterImplTest.java   |   15 +-
 .../server/state/cluster/ClusterTest.java       |  106 +-
 .../state/cluster/ClustersDeadlockTest.java     |   11 +-
 .../server/state/cluster/ClustersTest.java      |   11 +-
 .../ConcurrentServiceConfigVersionTest.java     |    9 +-
 ...omponentHostConcurrentWriteDeadlockTest.java |   16 +-
 .../svccomphost/ServiceComponentHostTest.java   |   57 +-
 .../server/upgrade/StackUpgradeUtilTest.java    |  145 --
 .../server/upgrade/UpgradeCatalog200Test.java   |   11 +-
 .../server/upgrade/UpgradeCatalog210Test.java   |    7 +-
 .../server/upgrade/UpgradeCatalog220Test.java   |    2 -
 .../server/upgrade/UpgradeCatalogHelper.java    |   24 +-
 .../ambari/server/utils/StageUtilsTest.java     |   25 -
 .../src/test/python/TestAmbariServer.py         |  166 +--
 .../src/test/python/TestServerUpgrade.py        |   35 +-
 108 files changed, 2148 insertions(+), 3966 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-common/src/main/python/resource_management/libraries/script/script.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/script/script.py b/ambari-common/src/main/python/resource_management/libraries/script/script.py
index da47351..f54a510 100644
--- a/ambari-common/src/main/python/resource_management/libraries/script/script.py
+++ b/ambari-common/src/main/python/resource_management/libraries/script/script.py
@@ -290,6 +290,13 @@ class Script(object):
     if OSCheck.is_windows_family():
       reload_windows_env()
 
+    # !!! status commands re-use structured output files; if the status command doesn't update the
+    # the file (because it doesn't have to) then we must ensure that the file is reset to prevent
+    # old, stale structured output from a prior status command from being used
+    if self.command_name == "status":
+      Script.structuredOut = {}
+      self.put_structured_out({})
+
     try:
       with open(self.command_data_file) as f:
         pass

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
index c1028dc..17e1f9c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatProcessor.java
@@ -375,8 +375,9 @@ public class HeartbeatProcessor extends AbstractService{
       }
 
       LOG.debug("Received command report: " + report);
+
+      // get this locally; don't touch the database
       Host host = clusterFsm.getHost(hostname);
-//      HostEntity hostEntity = hostDAO.findByName(hostname); //don't touch database
       if (host == null) {
         LOG.error("Received a command report and was unable to retrieve Host for hostname = " + hostname);
         continue;
@@ -473,7 +474,8 @@ public class HeartbeatProcessor extends AbstractService{
           if (report.getStatus().equals(HostRoleStatus.COMPLETED.toString())) {
 
             // Reading component version if it is present
-            if (StringUtils.isNotBlank(report.getStructuredOut())) {
+            if (StringUtils.isNotBlank(report.getStructuredOut())
+                && !StringUtils.equals("{}", report.getStructuredOut())) {
               ComponentVersionStructuredOut structuredOutput = null;
               try {
                 structuredOutput = gson.fromJson(report.getStructuredOut(), ComponentVersionStructuredOut.class);
@@ -491,10 +493,7 @@ public class HeartbeatProcessor extends AbstractService{
               versionEventPublisher.publish(event);
             }
 
-            // Updating stack version, if needed (this is not actually for express/rolling upgrades!)
-            if (scHost.getState().equals(org.apache.ambari.server.state.State.UPGRADING)) {
-              scHost.setStackVersion(scHost.getDesiredStackVersion());
-            } else if ((report.getRoleCommand().equals(RoleCommand.START.toString()) ||
+            if ((report.getRoleCommand().equals(RoleCommand.START.toString()) ||
                 (report.getRoleCommand().equals(RoleCommand.CUSTOM_COMMAND.toString()) &&
                     ("START".equals(report.getCustomCommand()) ||
                         "RESTART".equals(report.getCustomCommand()))))
@@ -616,10 +615,6 @@ public class HeartbeatProcessor extends AbstractService{
                 }
               }
 
-              if (null != status.getStackVersion() && !status.getStackVersion().isEmpty()) {
-                scHost.setStackVersion(gson.fromJson(status.getStackVersion(), StackId.class));
-              }
-
               if (null != status.getConfigTags()) {
                 scHost.updateActualConfigs(status.getConfigTags());
               }

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/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 7dfbe47..d275eb2 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
@@ -28,7 +28,6 @@ import java.util.TreeMap;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
-import org.apache.ambari.server.orm.entities.ClusterVersionEntity;
 import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.orm.entities.UpgradeEntity;
 import org.apache.ambari.server.state.Alert;
@@ -36,9 +35,10 @@ import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.ComponentInfo;
 import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.StackId;
-import org.apache.ambari.server.state.State;
 import org.apache.commons.lang.StringUtils;
 
 import com.google.inject.Inject;
@@ -75,17 +75,6 @@ public class ComponentVersionAlertRunnable extends AlertRunnable {
    */
   private static final String MISMATCHED_VERSIONS_MSG = "The following components are reporting unexpected versions: ";
 
-  /**
-   * The message when there is no CURRENT cluster version, but the cluster is
-   * still being setup.
-   */
-  private static final String CLUSTER_PROVISIONING_MSG = "The cluster is currently being provisioned. This alert will be skipped.";
-
-  /**
-   * The message when there is no CURRENT cluster version.
-   */
-  private static final String CLUSTER_OUT_OF_SYNC_MSG = "The cluster's CURRENT version could not be determined.";
-
   @Inject
   private AmbariMetaInfo m_metaInfo;
 
@@ -102,7 +91,7 @@ public class ComponentVersionAlertRunnable extends AlertRunnable {
    * {@inheritDoc}
    */
   @Override
-  List<Alert> execute(Cluster cluster, AlertDefinitionEntity myDefinition) {
+  List<Alert> execute(Cluster cluster, AlertDefinitionEntity myDefinition) throws AmbariException {
     // if there is an upgrade in progress, then skip running this alert
     UpgradeEntity upgrade = cluster.getUpgradeInProgress();
     if (null != upgrade) {
@@ -115,27 +104,15 @@ public class ComponentVersionAlertRunnable extends AlertRunnable {
     TreeMap<Host, Set<ServiceComponentHost>> versionMismatches = new TreeMap<>();
     Collection<Host> hosts = cluster.getHosts();
 
-    // no cluster version is very bad ...
-    ClusterVersionEntity clusterVersionEntity = cluster.getCurrentClusterVersion();
-    if (null == clusterVersionEntity) {
-      if (cluster.getProvisioningState() == State.INIT
-          || cluster.getAllClusterVersions().size() == 1) {
-        return Collections.singletonList(
-            buildAlert(cluster, myDefinition, AlertState.SKIPPED, CLUSTER_PROVISIONING_MSG));
-      } else {
-        return Collections.singletonList(
-            buildAlert(cluster, myDefinition, AlertState.CRITICAL, CLUSTER_OUT_OF_SYNC_MSG));
-      }
-    }
-
-    RepositoryVersionEntity repositoryVersionEntity = clusterVersionEntity.getRepositoryVersion();
-    String clusterVersion = repositoryVersionEntity.getVersion();
-
     for (Host host : hosts) {
-      List<ServiceComponentHost> hostComponents = cluster.getServiceComponentHosts(
-          host.getHostName());
+      List<ServiceComponentHost> hostComponents = cluster.getServiceComponentHosts(host.getHostName());
       for (ServiceComponentHost hostComponent : hostComponents) {
-        StackId desiredStackId = hostComponent.getDesiredStackVersion();
+        Service service = cluster.getService(hostComponent.getServiceName());
+        ServiceComponent serviceComponent = service.getServiceComponent(hostComponent.getServiceComponentName());
+
+        RepositoryVersionEntity desiredRepositoryVersion = service.getDesiredRepositoryVersion();
+        StackId desiredStackId = serviceComponent.getDesiredStackVersion();
+        String desiredVersion = desiredRepositoryVersion.getVersion();
 
         final ComponentInfo componentInfo;
         try {
@@ -157,7 +134,7 @@ public class ComponentVersionAlertRunnable extends AlertRunnable {
         }
 
         String version = hostComponent.getVersion();
-        if (!StringUtils.equals(version, clusterVersion)) {
+        if (!StringUtils.equals(version, desiredVersion)) {
           Set<ServiceComponentHost> mismatchedComponents = versionMismatches.get(host);
           if (null == mismatchedComponents) {
             mismatchedComponents = new HashSet<>();

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
index b2a03e4..f8e9e14 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/DatabaseConsistencyCheckHelper.java
@@ -57,6 +57,7 @@ import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
 import org.apache.ambari.server.orm.entities.HostComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.HostComponentStateEntity;
 import org.apache.ambari.server.orm.entities.MetainfoEntity;
+import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 import org.apache.ambari.server.state.SecurityState;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.State;
@@ -165,7 +166,7 @@ public class DatabaseConsistencyCheckHelper {
       LOG.error("Exception occurred during connection close procedure: ", e);
     }
   }
-  
+
   public static DatabaseConsistencyCheckResult runAllDBChecks(boolean fixIssues) throws Throwable {
     LOG.info("******************************* Check database started *******************************");
     try {
@@ -693,6 +694,8 @@ public class DatabaseConsistencyCheckHelper {
     }
 
     for (HostComponentDesiredStateEntity hostComponentDesiredStateEntity : missedHostComponentDesiredStates) {
+      ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity = hostComponentDesiredStateEntity.getServiceComponentDesiredStateEntity();
+
       HostComponentStateEntity stateEntity = new HostComponentStateEntity();
       stateEntity.setClusterId(hostComponentDesiredStateEntity.getClusterId());
       stateEntity.setComponentName(hostComponentDesiredStateEntity.getComponentName());
@@ -701,7 +704,6 @@ public class DatabaseConsistencyCheckHelper {
       stateEntity.setHostEntity(hostComponentDesiredStateEntity.getHostEntity());
       stateEntity.setCurrentState(State.UNKNOWN);
       stateEntity.setUpgradeState(UpgradeState.NONE);
-      stateEntity.setCurrentStack(hostComponentDesiredStateEntity.getDesiredStack());
       stateEntity.setSecurityState(SecurityState.UNKNOWN);
       stateEntity.setServiceComponentDesiredStateEntity(hostComponentDesiredStateEntity.getServiceComponentDesiredStateEntity());
 
@@ -717,7 +719,6 @@ public class DatabaseConsistencyCheckHelper {
       stateEntity.setServiceName(missedHostComponentState.getServiceName());
       stateEntity.setHostEntity(missedHostComponentState.getHostEntity());
       stateEntity.setDesiredState(State.UNKNOWN);
-      stateEntity.setDesiredStack(missedHostComponentState.getCurrentStack());
       stateEntity.setServiceComponentDesiredStateEntity(missedHostComponentState.getServiceComponentDesiredStateEntity());
 
       LOG.error("Trying to add missing record in hostcomponentdesiredstate: {}", stateEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/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 04b72ea..8995e51 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
@@ -697,8 +697,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         sch.setDesiredState(state);
       }
 
-      sch.setDesiredStackVersion(sc.getDesiredStackVersion());
-
       schMap.put(cluster, sch);
     }
 
@@ -2741,6 +2739,9 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           for (ServiceComponentHost scHost :
               changedScHosts.get(compName).get(newState)) {
 
+            Service service = cluster.getService(scHost.getServiceName());
+            ServiceComponent serviceComponent = service.getServiceComponent(compName);
+
             // Do not create role command for hosts that are not responding
             if (scHost.getHostState().equals(HostState.HEARTBEAT_LOST)) {
               LOG.info("Command is not created for servicecomponenthost "
@@ -2779,7 +2780,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
                     event = new ServiceComponentHostInstallEvent(
                         scHost.getServiceComponentName(), scHost.getHostName(),
                         nowTimestamp,
-                        scHost.getDesiredStackVersion().getStackId());
+                        serviceComponent.getDesiredStackVersion().getStackId());
                   }
                 } else if (oldSchState == State.STARTED
                       // TODO: oldSchState == State.INSTALLED is always false, looks like a bug
@@ -2793,7 +2794,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
                   roleCommand = RoleCommand.UPGRADE;
                   event = new ServiceComponentHostUpgradeEvent(
                       scHost.getServiceComponentName(), scHost.getHostName(),
-                      nowTimestamp, scHost.getDesiredStackVersion().getStackId());
+                      nowTimestamp, serviceComponent.getDesiredStackVersion().getStackId());
                 } else {
                   throw new AmbariException("Invalid transition for"
                       + " servicecomponenthost"
@@ -2807,7 +2808,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
                 }
                 break;
               case STARTED:
-                StackId stackId = scHost.getDesiredStackVersion();
+                StackId stackId = serviceComponent.getDesiredStackVersion();
                 ComponentInfo compInfo = ambariMetaInfo.getComponent(
                     stackId.getStackName(), stackId.getStackVersion(), scHost.getServiceName(),
                     scHost.getServiceComponentName());

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostRequest.java
index 5b6c739..2cf3909 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostRequest.java
@@ -118,20 +118,6 @@ public class ServiceComponentHostRequest {
   }
 
   /**
-   * @return the desiredStackId
-   */
-  public String getDesiredStackId() {
-    return desiredStackId;
-  }
-
-  /**
-   * @param desiredStackId the desiredStackId to set
-   */
-  public void setDesiredStackId(String desiredStackId) {
-    this.desiredStackId = desiredStackId;
-  }
-
-  /**
    * @return the clusterName
    */
   public String getClusterName() {
@@ -156,7 +142,7 @@ public class ServiceComponentHostRequest {
    * @return Stale config indicator
    */
   public String getStaleConfig() {
-    return this.staleConfig;
+    return staleConfig;
   }
 
   /**
@@ -170,9 +156,10 @@ public class ServiceComponentHostRequest {
    * @return the admin state of the component
    */
   public String getAdminState() {
-    return this.adminState;
+    return adminState;
   }
 
+  @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
     sb.append("{" + " clusterName=").append(clusterName)

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java
index f6993f8..08acff7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceComponentHostResponse.java
@@ -35,21 +35,19 @@ public class ServiceComponentHostResponse {
   // type -> desired config
   private Map<String, HostConfig> actualConfigs;
   private String liveState;
-  private String stackVersion;
+  private String version;
   private String desiredStackVersion;
+  private String desiredRepositoryVersion;
   private String desiredState;
   private boolean staleConfig = false;
   private String adminState = null;
   private String maintenanceState = null;
   private UpgradeState upgradeState = UpgradeState.NONE;
 
-
-  public ServiceComponentHostResponse(String clusterName, String serviceName,
-                                      String componentName, String displayName,
-                                      String hostname, String publicHostname,
-                                      String liveState, String stackVersion,
-                                      String desiredState, String desiredStackVersion,
-                                      HostComponentAdminState adminState) {
+  public ServiceComponentHostResponse(String clusterName, String serviceName, String componentName,
+      String displayName, String hostname, String publicHostname, String liveState, String version,
+      String desiredState, String desiredStackVersion, String desiredRepositoryVersion,
+      HostComponentAdminState adminState) {
     this.clusterName = clusterName;
     this.serviceName = serviceName;
     this.componentName = componentName;
@@ -57,9 +55,10 @@ public class ServiceComponentHostResponse {
     this.hostname = hostname;
     this.publicHostname = publicHostname;
     this.liveState = liveState;
-    this.stackVersion = stackVersion;
+    this.version = version;
     this.desiredState = desiredState;
     this.desiredStackVersion = desiredStackVersion;
+    this.desiredRepositoryVersion = desiredRepositoryVersion;
     if (adminState != null) {
       this.adminState = adminState.name();
     }
@@ -143,17 +142,10 @@ public class ServiceComponentHostResponse {
   }
 
   /**
-   * @return the stackVersion
-   */
-  public String getStackVersion() {
-    return stackVersion;
-  }
-
-  /**
-   * @param stackVersion the stackVersion to set
+   * @return the version
    */
-  public void setStackVersion(String stackVersion) {
-    this.stackVersion = stackVersion;
+  public String getVersion() {
+    return version;
   }
 
   /**
@@ -185,6 +177,15 @@ public class ServiceComponentHostResponse {
   }
 
   /**
+   * Gets the desired repository of the component.
+   *
+   * @return the desired repository.
+   */
+  public String getDesiredRepositoryVersion() {
+    return desiredRepositoryVersion;
+  }
+
+  /**
    * @return the clusterName
    */
   public String getClusterName() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
index 6c0d4ea..66c1a93 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
@@ -28,17 +28,23 @@ public class ServiceRequest {
   private String credentialStoreEnabled; // CREATE/UPDATE/GET
   private String credentialStoreSupported; //GET
 
-  public ServiceRequest(String clusterName, String serviceName,
-                        String desiredState) {
-    this(clusterName, serviceName, desiredState, null);
+  private String desiredStack;
+  private String desiredRepositoryVersion;
+
+  public ServiceRequest(String clusterName, String serviceName, String desiredStack,
+      String desiredRepositoryVersion, String desiredState) {
+    this(clusterName, serviceName, desiredStack, desiredRepositoryVersion, desiredState, null);
   }
 
-  public ServiceRequest(String clusterName, String serviceName,
-                        String desiredState,
-                        String credentialStoreEnabled) {
+  public ServiceRequest(String clusterName, String serviceName, String desiredStack,
+      String desiredRepositoryVersion, String desiredState, String credentialStoreEnabled) {
     this.clusterName = clusterName;
     this.serviceName = serviceName;
     this.desiredState = desiredState;
+
+    this.desiredStack = desiredStack;
+    this.desiredRepositoryVersion = desiredRepositoryVersion;
+
     this.credentialStoreEnabled = credentialStoreEnabled;
     // Credential store supported cannot be changed after
     // creation since it comes from the stack definition.
@@ -73,6 +79,14 @@ public class ServiceRequest {
     this.desiredState = desiredState;
   }
 
+  public String getDesiredStack() {
+    return desiredStack;
+  }
+
+  public String getDesiredRepositoryVersion() {
+    return desiredRepositoryVersion;
+  }
+
   /**
    * @return the clusterName
    */
@@ -130,6 +144,7 @@ public class ServiceRequest {
     this.credentialStoreSupported = credentialStoreSupported;
   }
 
+  @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
     sb.append("clusterName=").append(clusterName)

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
index 3e35c0c..e67d124f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
@@ -25,25 +25,26 @@ public class ServiceResponse {
   private String clusterName;
   private String serviceName;
   private String desiredStackVersion;
+  private String desiredRepositoryVersion;
   private String desiredState;
   private String maintenanceState;
   private boolean credentialStoreSupported;
   private boolean credentialStoreEnabled;
 
-  public ServiceResponse(Long clusterId, String clusterName,
-                         String serviceName,
-                         String desiredStackVersion, String desiredState,
-                         boolean credentialStoreSupported, boolean credentialStoreEnabled) {
+  public ServiceResponse(Long clusterId, String clusterName, String serviceName,
+      String desiredStackVersion, String desiredRepositoryVersion, String desiredState,
+      boolean credentialStoreSupported, boolean credentialStoreEnabled) {
     this.clusterId = clusterId;
     this.clusterName = clusterName;
     this.serviceName = serviceName;
-    this.setDesiredStackVersion(desiredStackVersion);
-    this.setDesiredState(desiredState);
+    setDesiredStackVersion(desiredStackVersion);
+    setDesiredState(desiredState);
+    this.desiredRepositoryVersion = desiredRepositoryVersion;
     this.credentialStoreSupported = credentialStoreSupported;
     this.credentialStoreEnabled = credentialStoreEnabled;
   }
-  
-  
+
+
 
   /**
    * @return the serviceName
@@ -115,10 +116,23 @@ public class ServiceResponse {
     this.desiredStackVersion = desiredStackVersion;
   }
 
+  /**
+   * Gets the desired repository version.
+   *
+   * @return the desired repository version.
+   */
+  public String getDesiredRepositoryVersion() {
+    return desiredRepositoryVersion;
+  }
+
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     ServiceResponse that = (ServiceResponse) o;
 
@@ -137,11 +151,11 @@ public class ServiceResponse {
 
     return true;
   }
-  
+
   public void setMaintenanceState(String state) {
     maintenanceState = state;
   }
-  
+
   public String getMaintenanceState() {
     return maintenanceState;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
index c3e66fc..5c89ced 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterStackVersionResourceProvider.java
@@ -35,14 +35,10 @@ import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.StaticallyInject;
 import org.apache.ambari.server.actionmanager.ActionManager;
-import org.apache.ambari.server.actionmanager.HostRoleCommand;
 import org.apache.ambari.server.actionmanager.HostRoleCommandFactory;
-import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.actionmanager.RequestFactory;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.StageFactory;
-import org.apache.ambari.server.agent.CommandReport;
-import org.apache.ambari.server.agent.ExecutionCommand;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.ActionExecutionContext;
@@ -689,132 +685,6 @@ public class ClusterStackVersionResourceProvider extends AbstractControllerResou
     return requestStages;
   }
 
-  /**
-   * The only appliance of this method is triggering Finalize during
-   * manual Stack Upgrade
-   */
-  @Override
-  public RequestStatus updateResourcesAuthorized(Request request, Predicate predicate)
-      throws SystemException, UnsupportedPropertyException,
-      NoSuchResourceException, NoSuchParentResourceException {
-    try {
-      Iterator<Map<String, Object>> iterator = request.getProperties().iterator();
-      String clName;
-      final String desiredRepoVersion;
-      if (request.getProperties().size() != 1) {
-        throw new UnsupportedOperationException("Multiple requests cannot be executed at the same time.");
-      }
-      Map<String, Object> propertyMap = iterator.next();
-
-      Set<String> requiredProperties = new HashSet<>();
-      requiredProperties.add(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
-      requiredProperties.add(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID);
-      requiredProperties.add(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID);
-
-      for (String requiredProperty : requiredProperties) {
-        if (!propertyMap.containsKey(requiredProperty)) {
-          throw new IllegalArgumentException(
-                  String.format("The required property %s is not defined",
-                          requiredProperty));
-        }
-      }
-
-      clName = (String) propertyMap.get(CLUSTER_STACK_VERSION_CLUSTER_NAME_PROPERTY_ID);
-      String desiredDisplayRepoVersion = (String) propertyMap.get(CLUSTER_STACK_VERSION_REPOSITORY_VERSION_PROPERTY_ID);
-      RepositoryVersionEntity rve = repositoryVersionDAO.findByDisplayName(desiredDisplayRepoVersion);
-      if (rve == null) {
-        throw new IllegalArgumentException(
-                  String.format("Repository version with display name %s does not exist",
-                          desiredDisplayRepoVersion));
-      }
-      desiredRepoVersion = rve.getVersion();
-      String newStateStr = (String) propertyMap.get(CLUSTER_STACK_VERSION_STATE_PROPERTY_ID);
-
-      LOG.info("Initiating finalization for manual upgrade to version {} for cluster {}",
-              desiredRepoVersion, clName);
-
-      // First, set desired cluster stack version to enable cross-stack upgrade
-      StackId stackId = rve.getStackId();
-      Cluster cluster = getManagementController().getClusters().getCluster(clName);
-      cluster.setDesiredStackVersion(stackId);
-
-      String forceCurrent = (String) propertyMap.get(CLUSTER_STACK_VERSION_FORCE);
-      boolean force = false;
-      if (null != forceCurrent) {
-        force = Boolean.parseBoolean(forceCurrent);
-      }
-
-      if (!force) {
-        Map<String, String> args = new HashMap<>();
-        if (newStateStr.equals(RepositoryVersionState.CURRENT.toString())) {
-          // Finalize upgrade workflow
-          args.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "upgrade");
-        } else if (newStateStr.equals(RepositoryVersionState.INSTALLED.toString())) {
-          // Finalize downgrade workflow
-          args.put(FinalizeUpgradeAction.UPGRADE_DIRECTION_KEY, "downgrade");
-        } else {
-          throw new IllegalArgumentException(
-            String.format("Invalid desired state %s. Should be either CURRENT or INSTALLED",
-                    newStateStr));
-        }
-
-        // Get a host name to populate the hostrolecommand table's hostEntity.
-        String defaultHostName;
-        ArrayList<Host> hosts = new ArrayList<>(cluster.getHosts());
-        if (!hosts.isEmpty()) {
-          Collections.sort(hosts);
-          defaultHostName = hosts.get(0).getHostName();
-        } else {
-          throw new AmbariException("Could not find at least one host to set the command for");
-        }
-
-        args.put(FinalizeUpgradeAction.VERSION_KEY, desiredRepoVersion);
-        args.put(FinalizeUpgradeAction.CLUSTER_NAME_KEY, clName);
-
-        ExecutionCommand command = new ExecutionCommand();
-        command.setCommandParams(args);
-        command.setClusterName(clName);
-        finalizeUpgradeAction.setExecutionCommand(command);
-
-        HostRoleCommand hostRoleCommand = hostRoleCommandFactory.create(defaultHostName,
-                Role.AMBARI_SERVER_ACTION, null, null);
-        finalizeUpgradeAction.setHostRoleCommand(hostRoleCommand);
-
-        CommandReport report = finalizeUpgradeAction.execute(null);
-
-        LOG.info("Finalize output:");
-        LOG.info("STDOUT: {}", report.getStdOut());
-        LOG.info("STDERR: {}", report.getStdErr());
-
-        if (report.getStatus().equals(HostRoleStatus.COMPLETED.toString())) {
-          return getRequestStatus(null);
-        } else {
-          String detailedOutput = "Finalization failed. More details: \n" +
-                  "STDOUT: " + report.getStdOut() + "\n" +
-                  "STDERR: " + report.getStdErr();
-          throw new SystemException(detailedOutput);
-        }
-      } else {
-        // !!! revisit for PU
-        // If forcing to become CURRENT, get the Cluster Version whose state is CURRENT and make sure that
-        // the Host Version records for the same Repo Version are also marked as CURRENT.
-        @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
-        ClusterVersionEntity current = cluster.getCurrentClusterVersion();
-
-        if (!current.getRepositoryVersion().equals(rve)) {
-          updateVersionStates(current.getClusterId(), current.getRepositoryVersion(), rve);
-        }
-
-
-        return getRequestStatus(null);
-      }
-    } catch (AmbariException e) {
-      throw new SystemException("Cannot perform request", e);
-    } catch (InterruptedException e) {
-      throw new SystemException("Cannot perform request", e);
-    }
-  }
-
   @Override
   public RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate)
       throws SystemException, UnsupportedPropertyException,

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
index ff8d0be..3f4e7c2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
@@ -352,7 +352,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
       Cluster cluster = clusters.getCluster(request.getClusterName());
       Service s = cluster.getService(request.getServiceName());
       ServiceComponent sc = serviceComponentFactory.createNew(s, request.getComponentName());
-      sc.setDesiredStackVersion(s.getDesiredStackVersion());
+      sc.setDesiredRepositoryVersion(s.getDesiredRepositoryVersion());
 
       if (StringUtils.isNotEmpty(request.getDesiredState())) {
         State state = State.valueOf(request.getDesiredState());

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
index 46e791b..10bd7ac 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
@@ -50,7 +50,6 @@ import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
-import org.apache.ambari.server.orm.entities.HostVersionEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
@@ -97,10 +96,12 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
       = PropertyHelper.getPropertyId("HostRoles", "state");
   public static final String HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID
       = PropertyHelper.getPropertyId("HostRoles", "desired_state");
-  public static final String HOST_COMPONENT_STACK_ID_PROPERTY_ID
-      = PropertyHelper.getPropertyId("HostRoles", "stack_id");
+  public static final String HOST_COMPONENT_VERSION_PROPERTY_ID
+      = PropertyHelper.getPropertyId("HostRoles", "version");
   public static final String HOST_COMPONENT_DESIRED_STACK_ID_PROPERTY_ID
       = PropertyHelper.getPropertyId("HostRoles", "desired_stack_id");
+  public static final String HOST_COMPONENT_DESIRED_REPOSITORY_VERSION
+    = PropertyHelper.getPropertyId("HostRoles", "desired_repository_version");
   public static final String HOST_COMPONENT_ACTUAL_CONFIGS_PROPERTY_ID
       = PropertyHelper.getPropertyId("HostRoles", "actual_configs");
   public static final String HOST_COMPONENT_STALE_CONFIGS_PROPERTY_ID
@@ -109,8 +110,6 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
       = PropertyHelper.getPropertyId("HostRoles", "desired_admin_state");
   public static final String HOST_COMPONENT_MAINTENANCE_STATE_PROPERTY_ID
       = "HostRoles/maintenance_state";
-  public static final String HOST_COMPONENT_HDP_VERSION_PROPERTY_ID
-      = PropertyHelper.getPropertyId("HostRoles", "hdp_version");
   public static final String HOST_COMPONENT_UPGRADE_STATE_PROPERTY_ID = "HostRoles/upgrade_state";
 
   //Parameters from the predicate
@@ -237,8 +236,8 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
               response.getLiveState(), requestedIds);
       setResourceProperty(resource, HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID,
               response.getDesiredState(), requestedIds);
-      setResourceProperty(resource, HOST_COMPONENT_STACK_ID_PROPERTY_ID,
-              response.getStackVersion(), requestedIds);
+      setResourceProperty(resource, HOST_COMPONENT_VERSION_PROPERTY_ID, response.getVersion(),
+          requestedIds);
       setResourceProperty(resource, HOST_COMPONENT_DESIRED_STACK_ID_PROPERTY_ID,
               response.getDesiredStackVersion(), requestedIds);
       setResourceProperty(resource, HOST_COMPONENT_ACTUAL_CONFIGS_PROPERTY_ID,
@@ -247,15 +246,8 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
               response.isStaleConfig(), requestedIds);
       setResourceProperty(resource, HOST_COMPONENT_UPGRADE_STATE_PROPERTY_ID,
               response.getUpgradeState(), requestedIds);
-
-      if (requestedIds.contains(HOST_COMPONENT_HDP_VERSION_PROPERTY_ID)) {
-        HostVersionEntity versionEntity = hostVersionDAO.
-            findByHostAndStateCurrent(response.getClusterName(), response.getHostname());
-        if (versionEntity != null) {
-          setResourceProperty(resource, HOST_COMPONENT_HDP_VERSION_PROPERTY_ID,
-              versionEntity.getRepositoryVersion().getDisplayName(), requestedIds);
-        }
-      }
+      setResourceProperty(resource, HOST_COMPONENT_DESIRED_REPOSITORY_VERSION,
+          response.getDesiredRepositoryVersion(), requestedIds);
 
       if (response.getAdminState() != null) {
         setResourceProperty(resource, HOST_COMPONENT_DESIRED_ADMIN_STATE_PROPERTY_ID,
@@ -684,7 +676,6 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
         (String) properties.get(HOST_COMPONENT_HOST_NAME_PROPERTY_ID),
         (String) properties.get(HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID));
     serviceComponentHostRequest.setState((String) properties.get(HOST_COMPONENT_STATE_PROPERTY_ID));
-    serviceComponentHostRequest.setDesiredStackId((String) properties.get(HOST_COMPONENT_STACK_ID_PROPERTY_ID));
     if (properties.get(HOST_COMPONENT_STALE_CONFIGS_PROPERTY_ID) != null) {
       serviceComponentHostRequest.setStaleConfig(
           properties.get(HOST_COMPONENT_STALE_CONFIGS_PROPERTY_ID).toString().toLowerCase());
@@ -724,8 +715,6 @@ public class HostComponentResourceProvider extends AbstractControllerResourcePro
     if (properties.get(HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID) != null) {
       serviceComponentHostRequest.setDesiredState((String)properties.get(HOST_COMPONENT_DESIRED_STATE_PROPERTY_ID));
     }
-    serviceComponentHostRequest.setDesiredStackId(
-            (String) properties.get(HOST_COMPONENT_STACK_ID_PROPERTY_ID));
     if (properties.get(HOST_COMPONENT_STALE_CONFIGS_PROPERTY_ID) != null) {
       serviceComponentHostRequest.setStaleConfig(
               properties.get(HOST_COMPONENT_STALE_CONFIGS_PROPERTY_ID).toString().toLowerCase());

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
index 6556852..9cbcea6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
@@ -56,6 +56,8 @@ import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.controller.utilities.ServiceCalculatedStateFactory;
 import org.apache.ambari.server.controller.utilities.state.ServiceCalculatedState;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
+import org.apache.ambari.server.orm.dao.RepositoryVersionDAO;
+import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
@@ -99,6 +101,9 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
 
   public static final String SERVICE_ATTRIBUTES_PROPERTY_ID = PropertyHelper.getPropertyId("Services", "attributes");
 
+  public static final String SERVICE_DESIRED_STACK_PROPERTY_ID = PropertyHelper.getPropertyId("ServiceInfo", "desired_stack");
+  public static final String SERVICE_DESIRED_REPO_VERSION_PROPERTY_ID = PropertyHelper.getPropertyId("ServiceInfo", "desired_repository_version");
+
   //Parameters from the predicate
   private static final String QUERY_PARAMETERS_RUN_SMOKE_TEST_ID =
     "params/run_smoke_test";
@@ -123,6 +128,11 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
   @Inject
   private KerberosHelper kerberosHelper;
 
+  /**
+   * Used to lookup the repository when creating services.
+   */
+  private final RepositoryVersionDAO repositoryVersionDAO;
+
   // ----- Constructors ----------------------------------------------------
 
   /**
@@ -134,11 +144,12 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
    */
   @AssistedInject
   public ServiceResourceProvider(@Assisted Set<String> propertyIds,
-                          @Assisted Map<Resource.Type, String> keyPropertyIds,
-                          @Assisted AmbariManagementController managementController,
-                          MaintenanceStateHelper maintenanceStateHelper) {
+      @Assisted Map<Resource.Type, String> keyPropertyIds,
+      @Assisted AmbariManagementController managementController,
+      MaintenanceStateHelper maintenanceStateHelper, RepositoryVersionDAO repositoryVersionDAO) {
     super(propertyIds, keyPropertyIds, managementController);
     this.maintenanceStateHelper = maintenanceStateHelper;
+    this.repositoryVersionDAO = repositoryVersionDAO;
 
     setRequiredCreateAuthorizations(EnumSet.of(RoleAuthorization.SERVICE_ADD_DELETE_SERVICES));
     setRequiredUpdateAuthorizations(RoleAuthorization.AUTHORIZATIONS_UPDATE_SERVICE);
@@ -207,6 +218,12 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
       setResourceProperty(resource, SERVICE_CREDENTIAL_STORE_ENABLED_PROPERTY_ID,
           String.valueOf(response.isCredentialStoreEnabled()), requestedIds);
 
+      setResourceProperty(resource, SERVICE_DESIRED_STACK_PROPERTY_ID,
+          response.getDesiredStackVersion(), requestedIds);
+
+      setResourceProperty(resource, SERVICE_DESIRED_REPO_VERSION_PROPERTY_ID,
+          response.getDesiredRepositoryVersion(), requestedIds);
+
       Map<String, Object> serviceSpecificProperties = getServiceSpecificProperties(
           response.getClusterName(), response.getServiceName(), requestedIds);
 
@@ -328,9 +345,13 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
    * @return the service request object
    */
   private ServiceRequest getRequest(Map<String, Object> properties) {
+    String desiredStack = (String)properties.get(SERVICE_DESIRED_STACK_PROPERTY_ID);
+    String desiredRepositoryVersion = (String)properties.get(SERVICE_DESIRED_REPO_VERSION_PROPERTY_ID);
+
     ServiceRequest svcRequest = new ServiceRequest(
         (String) properties.get(SERVICE_CLUSTER_NAME_PROPERTY_ID),
         (String) properties.get(SERVICE_SERVICE_NAME_PROPERTY_ID),
+        desiredStack, desiredRepositoryVersion,
         (String) properties.get(SERVICE_SERVICE_STATE_PROPERTY_ID),
         (String) properties.get(SERVICE_CREDENTIAL_STORE_ENABLED_PROPERTY_ID));
 
@@ -362,8 +383,20 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
     for (ServiceRequest request : requests) {
       Cluster cluster = clusters.getCluster(request.getClusterName());
 
-      // Already checked that service does not exist
-      Service s = cluster.addService(request.getServiceName());
+
+      String desiredStack = request.getDesiredStack();
+      String desiredRepositoryVersion = request.getDesiredRepositoryVersion();
+      RepositoryVersionEntity repositoryVersion = null;
+      if( StringUtils.isNotBlank(desiredStack) && StringUtils.isNotBlank(desiredRepositoryVersion)){
+        repositoryVersion = repositoryVersionDAO.findByStackAndVersion(new StackId(desiredStack),
+            desiredRepositoryVersion);
+      }
+
+      if (null == repositoryVersion) {
+        repositoryVersion = cluster.getCurrentClusterVersion().getRepositoryVersion();
+      }
+
+      Service s = cluster.addService(request.getServiceName(), repositoryVersion);
 
       /**
        * Get the credential_store_supported field only from the stack definition.

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/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 623851a..b49b66e 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
@@ -36,8 +36,6 @@ import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.apache.ambari.annotations.Experimental;
-import org.apache.ambari.annotations.ExperimentalFeature;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
@@ -92,8 +90,6 @@ 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;
@@ -704,7 +700,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     UpgradeType upgradeType = upgradeContext.getType();
 
     ConfigHelper configHelper = getManagementController().getConfigHelper();
-    String userName = getManagementController().getAuthName();
+
+    // 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();
@@ -721,20 +719,24 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
     switch (direction) {
       case UPGRADE:
-        StackId sourceStackId = cluster.getCurrentStackVersion();
-
-        RepositoryVersionEntity targetRepositoryVersion = s_repoVersionDAO.findByStackNameAndVersion(
-            sourceStackId.getStackName(), version);
+        RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion();
+        RepositoryType repositoryType = targetRepositoryVersion.getType();
 
         // !!! Consult the version definition and add the service names to supportedServices
-        if (targetRepositoryVersion.getType() != RepositoryType.STANDARD) {
+        if (repositoryType != RepositoryType.STANDARD) {
+          scope = UpgradeScope.PARTIAL;
+
           try {
             VersionDefinitionXml vdf = targetRepositoryVersion.getRepositoryXml();
             supportedServices.addAll(vdf.getAvailableServiceNames());
 
-            // !!! better not be, but just in case
-            if (!supportedServices.isEmpty()) {
-              scope = UpgradeScope.PARTIAL;
+            // 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) {
@@ -820,10 +822,6 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     List<UpgradeGroupEntity> groupEntities = new ArrayList<>();
     RequestStageContainer req = createRequest(direction, version);
 
-    // the upgrade context calculated these for us based on direction
-    StackId sourceStackId = upgradeContext.getOriginalStackId();
-    StackId targetStackId = upgradeContext.getTargetStackId();
-
     /**
     During a Rolling Upgrade, change the desired Stack Id if jumping across
     major stack versions (e.g., HDP 2.2 -> 2.3), and then set config changes
@@ -837,7 +835,10 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     if (pack.getType() == UpgradeType.ROLLING) {
       // Desired configs must be set before creating stages because the config tag
       // names are read and set on the command for filling in later
-      applyStackAndProcessConfigurations(targetStackId.getStackName(), cluster, version, direction, pack, userName);
+      applyStackAndProcessConfigurations(upgradeContext);
+
+      // move component desired version and upgrade state
+      s_upgradeHelper.putComponentsToUpgradingState(upgradeContext);
     }
 
     // resolve or build a proper config upgrade pack - always start out with the config pack
@@ -847,26 +848,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     // 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);
 
-    // TODO: for now, all service components are transitioned to upgrading state
-    // TODO: When performing patch upgrade, we should only target supported services/components
-    // from upgrade pack
-    @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
-    Set<Service> services = new HashSet<>(cluster.getServices().values());
-
-    @Experimental(feature=ExperimentalFeature.PATCH_UPGRADES)
-    Map<Service, Set<ServiceComponent>> targetComponents = new HashMap<>();
-    for (Service service: services) {
-      if (upgradeContext.isServiceSupported(service.getName())) {
-        Set<ServiceComponent> serviceComponents = new HashSet<>(service.getServiceComponents().values());
-        targetComponents.put(service, serviceComponents);
-      }
-    }
-
-    // !!! determine which stack to check for component isAdvertised
-    StackId componentStack = upgradeContext.getDirection() == Direction.UPGRADE ?
-        upgradeContext.getTargetStackId() : upgradeContext.getOriginalStackId();
-    s_upgradeHelper.putComponentsToUpgradingState(version, targetComponents, componentStack);
-
+    // create the upgrade and request
     for (UpgradeGroupHolder group : groups) {
       boolean skippable = group.skippable;
       boolean supportsAutoSkipOnFailure = group.supportsAutoSkipOnFailure;
@@ -1015,23 +997,19 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
    * fail due to missing configurations.</li>
    * </ul>
    *
-   *
-   * @param stackName Stack name such as HDP, HDPWIN, BIGTOP
-   * @param cluster
-   *          the cluster
-   * @param version
-   *          the version
-   * @param direction
-   *          upgrade or downgrade
-   * @param upgradePack
-   *          upgrade pack used for upgrade or downgrade. This is needed to determine
-   *          which services are effected.
-   * @param userName
-   *          username performing the action
+   * @param upgradeContext  the upgrade context (not {@code null}).
    * @throws AmbariException
    */
-  public void applyStackAndProcessConfigurations(String stackName, Cluster cluster, String version, Direction direction, UpgradePack upgradePack, String userName)
+  public void applyStackAndProcessConfigurations(UpgradeContext upgradeContext)
     throws AmbariException {
+
+    Cluster cluster = upgradeContext.getCluster();
+    Direction direction = upgradeContext.getDirection();
+    UpgradePack upgradePack = upgradeContext.getUpgradePack();
+    String stackName = upgradeContext.getTargetStackId().getStackName();
+    String version = upgradeContext.getVersion();
+    String userName = getManagementController().getAuthName();
+
     RepositoryVersionEntity targetRve = s_repoVersionDAO.findByStackNameAndVersion(stackName, version);
     if (null == targetRve) {
       LOG.info("Could not find version entity for {}; not setting new configs", version);
@@ -1255,7 +1233,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
     // !!! update the stack
     cluster.setDesiredStackVersion(
-        new StackId(targetStack.getStackName(), targetStack.getStackVersion()), true);
+        new StackId(targetStack.getStackName(), targetStack.getStackVersion()));
 
     // !!! configs must be created after setting the stack version
     if (null != newConfigurationsByType) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/DistributeRepositoriesActionListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/DistributeRepositoriesActionListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/DistributeRepositoriesActionListener.java
index cd82957..3fda160 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/DistributeRepositoriesActionListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/DistributeRepositoriesActionListener.java
@@ -34,6 +34,7 @@ import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.utils.StageUtils;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -118,10 +119,11 @@ public class DistributeRepositoriesActionListener {
 
         // Handle the case in which the version to install did not contain the build number,
         // but the structured output does contain the build number.
-        if (null != structuredOutput.getActualVersion() && !structuredOutput.getActualVersion().isEmpty() &&
-            null != structuredOutput.getInstalledRepositoryVersion() && !structuredOutput.getInstalledRepositoryVersion().isEmpty() &&
-            null != structuredOutput.getStackId() && !structuredOutput.getStackId().isEmpty() &&
-            !structuredOutput.getActualVersion().equals(structuredOutput.getInstalledRepositoryVersion())) {
+        if (!StringUtils.isEmpty(structuredOutput.getActualVersion())
+            && !StringUtils.isEmpty(structuredOutput.getInstalledRepositoryVersion())
+            && !StringUtils.isEmpty(structuredOutput.getStackId())
+            && !StringUtils.equals(structuredOutput.getActualVersion(),
+                structuredOutput.getInstalledRepositoryVersion())) {
 
           // !!! getInstalledRepositoryVersion() from the agent is the one
           // entered in the UI.  getActualVersion() is computed.

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java
index abf8e6b..33c622f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/upgrade/StackVersionListener.java
@@ -184,7 +184,6 @@ public class StackVersionListener {
   private void processUnknownDesiredVersion(Cluster cluster, ServiceComponent sc,
                                             ServiceComponentHost sch,
                                             String newVersion) throws AmbariException {
-    sc.setDesiredVersion(newVersion);
     sch.setUpgradeState(UpgradeState.NONE);
     sch.setVersion(newVersion);
     bootstrapVersion(cluster, sch);
@@ -205,8 +204,8 @@ public class StackVersionListener {
     if (upgradeState == UpgradeState.IN_PROGRESS) {
       // Component status update is received during upgrade process
       if (desiredVersion.equals(newVersion)) {
-        sch.setUpgradeState(UpgradeState.COMPLETE);  // Component upgrade confirmed
-        sch.setStackVersion(cluster.getDesiredStackVersion());
+        // Component upgrade confirmed
+        sch.setUpgradeState(UpgradeState.COMPLETE);
       } else { // Unexpected (wrong) version received
         // Even during failed upgrade, we should not receive wrong version
         // That's why mark as VERSION_MISMATCH

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
index 930a535..3871b67 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostVersionDAO.java
@@ -275,9 +275,31 @@ public class HostVersionDAO extends CrudDAO<HostVersionEntity, Long> {
     return daoUtils.selectSingle(query);
   }
 
+  /**
+   * Gets all host version entities assocaited with the specified cluster and
+   * repository.
+   *
+   * @param clusterId
+   *          the cluster ID.
+   * @param repositoryVersion
+   *          the repository (not {@code null}).
+   * @return the host versions.
+   */
+  @RequiresSession
+  public List<HostVersionEntity> findHostVersionByClusterAndRepository(long clusterId,
+      RepositoryVersionEntity repositoryVersion) {
+    TypedQuery<HostVersionEntity> query = entityManagerProvider.get().createNamedQuery(
+        "findHostVersionByClusterAndRepository", HostVersionEntity.class);
+
+    query.setParameter("clusterId", clusterId);
+    query.setParameter("repositoryVersion", repositoryVersion);
+
+    return daoUtils.selectList(query);
+  }
+
   @Transactional
   public void removeByHostName(String hostName) {
-    Collection<HostVersionEntity> hostVersions = this.findByHost(hostName);
+    Collection<HostVersionEntity> hostVersions = findByHost(hostName);
     this.remove(hostVersions);
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
index ea2938b..2049969 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentDesiredStateEntity.java
@@ -32,7 +32,6 @@ import javax.persistence.JoinColumns;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
-import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 import javax.persistence.UniqueConstraint;
@@ -100,13 +99,6 @@ public class HostComponentDesiredStateEntity {
   @Enumerated(value = EnumType.STRING)
   private SecurityState securityState = SecurityState.UNSECURED;
 
-  /**
-   * Unidirectional one-to-one association to {@link StackEntity}
-   */
-  @OneToOne
-  @JoinColumn(name = "desired_stack_id", unique = false, nullable = false)
-  private StackEntity desiredStack;
-
   @Enumerated(value = EnumType.STRING)
   @Column(name = "admin_state", nullable = true, insertable = true, updatable = true)
   private HostComponentAdminState adminState;
@@ -176,14 +168,6 @@ public class HostComponentDesiredStateEntity {
     this.securityState = securityState;
   }
 
-  public StackEntity getDesiredStack() {
-    return desiredStack;
-  }
-
-  public void setDesiredStack(StackEntity desiredStack) {
-    this.desiredStack = desiredStack;
-  }
-
   public HostComponentAdminState getAdminState() {
     return adminState;
   }
@@ -223,10 +207,6 @@ public class HostComponentDesiredStateEntity {
       return false;
     }
 
-    if (!Objects.equal(desiredStack, that.desiredStack)) {
-      return false;
-    }
-
     if (!Objects.equal(desiredState, that.desiredState)) {
       return false;
     }
@@ -249,7 +229,6 @@ public class HostComponentDesiredStateEntity {
     result = 31 * result + (hostEntity != null ? hostEntity.hashCode() : 0);
     result = 31 * result + (componentName != null ? componentName.hashCode() : 0);
     result = 31 * result + (desiredState != null ? desiredState.hashCode() : 0);
-    result = 31 * result + (desiredStack != null ? desiredStack.hashCode() : 0);
     result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
     return result;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
index 0b3d8ce..0151a41 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostComponentStateEntity.java
@@ -30,7 +30,6 @@ import javax.persistence.JoinColumns;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
-import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.persistence.TableGenerator;
 
@@ -110,13 +109,6 @@ public class HostComponentStateEntity {
   @Column(name = "security_state", nullable = false, insertable = true, updatable = true)
   private SecurityState securityState = SecurityState.UNSECURED;
 
-  /**
-   * Unidirectional one-to-one association to {@link StackEntity}
-   */
-  @OneToOne
-  @JoinColumn(name = "current_stack_id", unique = false, nullable = false, insertable = true, updatable = true)
-  private StackEntity currentStack;
-
   @ManyToOne
   @JoinColumns({
       @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false),
@@ -188,14 +180,6 @@ public class HostComponentStateEntity {
     this.upgradeState = upgradeState;
   }
 
-  public StackEntity getCurrentStack() {
-    return currentStack;
-  }
-
-  public void setCurrentStack(StackEntity currentStack) {
-    this.currentStack = currentStack;
-  }
-
   public String getVersion() {
     return version;
   }
@@ -229,11 +213,6 @@ public class HostComponentStateEntity {
       return false;
     }
 
-    if (currentStack != null ? !currentStack.equals(that.currentStack)
-        : that.currentStack != null) {
-      return false;
-    }
-
     if (currentState != null ? !currentState.equals(that.currentState)
         : that.currentState != null) {
       return false;
@@ -267,7 +246,6 @@ public class HostComponentStateEntity {
     result = 31 * result + (componentName != null ? componentName.hashCode() : 0);
     result = 31 * result + (currentState != null ? currentState.hashCode() : 0);
     result = 31 * result + (upgradeState != null ? upgradeState.hashCode() : 0);
-    result = 31 * result + (currentStack != null ? currentStack.hashCode() : 0);
     result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
     result = 31 * result + (version != null ? version.hashCode() : 0);
     return result;

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
index 4ed9617..9be30a3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/HostVersionEntity.java
@@ -71,7 +71,12 @@ import org.apache.ambari.server.state.RepositoryVersionState;
     @NamedQuery(name = "hostVersionByClusterStackVersionAndHostId", query =
         "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN host.clusterEntities clusters " +
         "WHERE hostVersion.hostId=:hostId AND clusters.clusterId=:clusterId AND hostVersion.repositoryVersion.stack.stackName=:stackName " +
-        "AND hostVersion.repositoryVersion.stack.stackVersion=:stackVersion AND hostVersion.repositoryVersion.version=:version")
+        "AND hostVersion.repositoryVersion.stack.stackVersion=:stackVersion AND hostVersion.repositoryVersion.version=:version"),
+
+    @NamedQuery(
+        name = "findHostVersionByClusterAndRepository",
+        query = "SELECT hostVersion FROM HostVersionEntity hostVersion JOIN hostVersion.hostEntity host JOIN host.clusterEntities clusters "
+            + "WHERE clusters.clusterId = :clusterId AND hostVersion.repositoryVersion = :repositoryVersion") 
 })
 public class HostVersionEntity {
 
@@ -115,9 +120,9 @@ public class HostVersionEntity {
    * This constructor is mainly used by the unit tests in order to construct an object without the id.
    */
   public HostVersionEntity(HostVersionEntity other) {
-    this.hostEntity = other.hostEntity;
-    this.repositoryVersion = other.repositoryVersion;
-    this.state = other.state;
+    hostEntity = other.hostEntity;
+    repositoryVersion = other.repositoryVersion;
+    state = other.state;
   }
 
   public Long getId() {
@@ -169,15 +174,29 @@ public class HostVersionEntity {
 
   @Override
   public boolean equals(Object obj) {
-    if (this == obj) return true;
-    if (obj == null) return false;
-    if (getClass() != obj.getClass()) return false;
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
 
     HostVersionEntity other = (HostVersionEntity) obj;
-    if (id != null ? id != other.id : other.id != null) return false;
-    if (hostEntity != null ? !hostEntity.equals(other.hostEntity) : other.hostEntity != null) return false;
-    if (repositoryVersion != null ? !repositoryVersion.equals(other.repositoryVersion) : other.repositoryVersion != null) return false;
-    if (state != other.state) return false;
+    if (id != null ? id != other.id : other.id != null) {
+      return false;
+    }
+    if (hostEntity != null ? !hostEntity.equals(other.hostEntity) : other.hostEntity != null) {
+      return false;
+    }
+    if (repositoryVersion != null ? !repositoryVersion.equals(other.repositoryVersion) : other.repositoryVersion != null) {
+      return false;
+    }
+    if (state != other.state) {
+      return false;
+    }
     return true;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/dcbd826c/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 17fd323..eb1b187 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
@@ -20,6 +20,7 @@ package org.apache.ambari.server.orm.entities;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Objects;
 
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
@@ -42,6 +43,7 @@ import javax.persistence.UniqueConstraint;
 
 import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.State;
+import org.apache.commons.lang.builder.EqualsBuilder;
 
 @Entity
 @Table(
@@ -90,18 +92,16 @@ public class ServiceComponentDesiredStateEntity {
   private RepositoryVersionState repoState = RepositoryVersionState.INIT;
 
   /**
-   * Unidirectional one-to-one association to {@link StackEntity}
+   * Unidirectional one-to-one association to {@link RepositoryVersionEntity}
    */
   @OneToOne
-  @JoinColumn(name = "desired_stack_id", unique = false, nullable = false, insertable = true, updatable = true)
-  private StackEntity desiredStack;
-
-  /**
-   * Version string that should be followed by instances
-   * of component on hosts. Includes both stack version and build
-   */
-  @Column(name = "desired_version", nullable = false, insertable = true, updatable = true)
-  private String desiredVersion = State.UNKNOWN.toString();
+  @JoinColumn(
+      name = "desired_repo_version_id",
+      unique = false,
+      nullable = true,
+      insertable = true,
+      updatable = true)
+  private RepositoryVersionEntity desiredRepositoryVersion;
 
   @ManyToOne
   @JoinColumns({@javax.persistence.JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false), @JoinColumn(name = "service_name", referencedColumnName = "service_name", nullable = false)})
@@ -161,20 +161,20 @@ public class ServiceComponentDesiredStateEntity {
     this.desiredState = desiredState;
   }
 
-  public StackEntity getDesiredStack() {
-    return desiredStack;
+  public RepositoryVersionEntity getDesiredRepositoryVersion() {
+    return desiredRepositoryVersion;
   }
 
-  public void setDesiredStack(StackEntity desiredStack) {
-    this.desiredStack = desiredStack;
+  public void setDesiredRepositoryVersion(RepositoryVersionEntity desiredRepositoryVersion) {
+    this.desiredRepositoryVersion = desiredRepositoryVersion;
   }
 
-  public String getDesiredVersion() {
-    return desiredVersion;
+  public StackEntity getDesiredStack() {
+    return desiredRepositoryVersion.getStack();
   }
 
-  public void setDesiredVersion(String desiredVersion) {
-    this.desiredVersion = desiredVersion;
+  public String getDesiredVersion() {
+    return desiredRepositoryVersion.getVersion();
   }
 
   /**
@@ -232,6 +232,9 @@ public class ServiceComponentDesiredStateEntity {
     this.recoveryEnabled = (recoveryEnabled == false) ? 0 : 1;
   }
 
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public boolean equals(Object o) {
     if (this == o) {
@@ -243,39 +246,21 @@ public class ServiceComponentDesiredStateEntity {
     }
 
     ServiceComponentDesiredStateEntity that = (ServiceComponentDesiredStateEntity) o;
-
-    if (id != null ? !id.equals(that.id) : that.id != null) {
-      return false;
-    }
-    if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) {
-      return false;
-    }
-    if (componentName != null ? !componentName.equals(that.componentName) : that.componentName != null) {
-      return false;
-    }
-    if (desiredState != null ? !desiredState.equals(that.desiredState) : that.desiredState != null) {
-      return false;
-    }
-    if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) {
-      return false;
-    }
-    if (desiredStack != null ? !desiredStack.equals(that.desiredStack)
-        : that.desiredStack != null) {
-      return false;
-    }
-    return true;
+    EqualsBuilder equalsBuilder = new EqualsBuilder();
+    equalsBuilder.append(id, that.id);
+    equalsBuilder.append(clusterId, that.clusterId);
+    equalsBuilder.append(componentName, that.componentName);
+    equalsBuilder.append(desiredState, that.desiredState);
+    equalsBuilder.append(serviceName, that.serviceName);
+    equalsBuilder.append(desiredRepositoryVersion, that.desiredRepositoryVersion);
+
+    return equalsBuilder.isEquals();
   }
 
   @Override
   public int hashCode() {
-    int result = id != null ? id.hashCode() : 0;
-    result = 31 * result + (clusterId != null ? clusterId.hashCode() : 0);
-    result = 31 * result + (serviceName != null ? serviceName.hashCode() : 0);
-    result = 31 * result + (componentName != null ? componentName.hashCode() : 0);
-    result = 31 * result + (desiredState != null ? desiredState.hashCode() : 0);
-    result = 31 * result + (desiredStack != null ? desiredStack.hashCode() : 0);
-
-    return result;
+    return Objects.hash(id, clusterId, serviceName, componentName, desiredState,
+        desiredRepositoryVersion);
   }
 
   public ClusterServiceEntity getClusterServiceEntity() {

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