private void finalizeHostVersionsNotDesired(Cluster cluster, UpgradeContext upgradeContext)
      throws AmbariException {
    // create a set of all of the repos that the services are on
    Set<RepositoryVersionEntity> desiredRepoVersions = new HashSet<>();
    Set<String> serviceNames = cluster.getServices().keySet();
    for (String serviceName : serviceNames) {
      Service service = cluster.getService(serviceName);
      desiredRepoVersions.add(service.getDesiredRepositoryVersion());
    }

    // if any CURRENT host version is for a repo which is no longer desired by
    // ANY service, move it to INSTALLED
    List<HostVersionEntity> currentHostVersions = hostVersionDAO.findByClusterAndState(
        cluster.getClusterName(), RepositoryVersionState.CURRENT);

    for (HostVersionEntity hostVersionEntity : currentHostVersions) {
      RepositoryVersionEntity hostRepoVersion = hostVersionEntity.getRepositoryVersion();
      if (!desiredRepoVersions.contains(hostRepoVersion)) {
        hostVersionEntity.setState(RepositoryVersionState.INSTALLED);
        hostVersionEntity = hostVersionDAO.merge(hostVersionEntity);
      }
    }

    // reverting a patch requires us to check the repository state and
    // possibly set it to OUT_OF_SYNC if services were added after this patch
    // was originally distributed
    if (upgradeContext.isPatchRevert()) {
      RepositoryVersionEntity repositoryVersionEntity = upgradeContext.getRepositoryVersion();

      final VersionDefinitionXml vdfXml;
      try {
        vdfXml = repositoryVersionEntity.getRepositoryXml();
      } catch (Exception exception) {
        throw new AmbariException("The VDF's XML could not be deserialized", exception);
      }

      StackInfo stack = ambariMetaInfo.getStack(repositoryVersionEntity.getStackId());

      // grab the services in the VDF, the services which were part of the
      // revert, and the services in the cluster to determine if a service was
      // added to the cluster after the patch was originally applied
      Collection<AvailableService> availableServices = vdfXml.getAvailableServices(stack);
      Set<String> participatingServices = upgradeContext.getSupportedServices();
      Set<String> clusterServices = cluster.getServices().keySet();

      boolean resetRepoStateToOutOfSync = false;
      for (AvailableService availableService : availableServices) {
        if (clusterServices.contains(availableService.getName())
            && !participatingServices.contains(availableService.getName())) {
          resetRepoStateToOutOfSync = true;
          break;
        }
      }

      if (resetRepoStateToOutOfSync) {
        List<HostVersionEntity> hostVersions = hostVersionDAO.findHostVersionByClusterAndRepository(
            cluster.getClusterId(), repositoryVersionEntity);
        for (HostVersionEntity hostVersion : hostVersions) {
          hostVersion.setState(RepositoryVersionState.OUT_OF_SYNC);
          hostVersion = hostVersionDAO.merge(hostVersion);
        }
      }
    }
  }
Moves any {@link HostVersionEntity}s which are
{@link RepositoryVersionState#CURRENT} to either
{@link RepositoryVersionState#INSTALLED} or
{@link RepositoryVersionState#NOT_REQUIRED} if their assocaited
repositories are no longer in use.
<p/>
If this is a patch reversion, then this method will also attempt to
determine if the downgrade-from repository needs to be set to
{@link RepositoryVersionState#OUT_OF_SYNC}. If a patch upgrade was
completed and then a service added after that happens to be specified in
the VDF, then we must mark the repository as OUT_OF_SYNC since those
service's packages were never distributed.

@param cluster
@throws AmbariException
ambari-server/src/main/java/org/apache/ambari/server/serveraction/upgrades/FinalizeUpgradeAction.java