class UpgradeHelper {

  public UpgradePack suggestUpgradePack(String clusterName,
      StackId sourceStackId, StackId targetStackId, Direction direction, UpgradeType upgradeType,
      String preferredUpgradePackName) throws AmbariException {

    // Find upgrade packs based on current stack. This is where to upgrade from
    Cluster cluster = m_clusters.get().getCluster(clusterName);
    StackId currentStack = cluster.getCurrentStackVersion();

    StackId stackForUpgradePack = targetStackId;

    if (direction.isDowngrade()) {
      stackForUpgradePack = sourceStackId;
    }

    Map<String, UpgradePack> packs = m_ambariMetaInfoProvider.get().getUpgradePacks(
        currentStack.getStackName(), currentStack.getStackVersion());

    UpgradePack pack = null;

    if (StringUtils.isNotEmpty(preferredUpgradePackName) && packs.containsKey(preferredUpgradePackName)) {
      pack = packs.get(preferredUpgradePackName);

      LOG.warn("Upgrade pack '{}' not found for stack {}", preferredUpgradePackName, currentStack);
    }

    // Best-attempt at picking an upgrade pack assuming within the same stack whose target stack version matches.
    // If multiple candidates are found, raise an exception.
    if (null == pack) {
      for (UpgradePack upgradePack : packs.values()) {
        if (null != upgradePack.getTargetStack()
            && StringUtils.equals(upgradePack.getTargetStack(), stackForUpgradePack.getStackId())
            && upgradeType == upgradePack.getType()) {
          if (null == pack) {
            // Pick the pack.
            pack = upgradePack;
          } else {
            throw new AmbariException(
                String.format(
                    "Unable to perform %s. Found multiple upgrade packs for type %s and stack %s",
                    direction.getText(false), upgradeType.toString(), stackForUpgradePack));
          }
        }
      }
    }

    if (null == pack) {
      throw new AmbariException(
          String.format("Unable to perform %s. Could not locate %s upgrade pack for stack %s",
              direction.getText(false), upgradeType.toString(), stackForUpgradePack));
    }

   return pack;
  }

}