private List<StageWrapper> buildHosts(UpgradeContext upgradeContext, List<String> hosts) {
      if (CollectionUtils.isEmpty(hosts)) {
        return Collections.emptyList();
      }

      Cluster cluster = upgradeContext.getCluster();
      List<StageWrapper> wrappers = new ArrayList<>();

      HostRoleCommandFactory hrcFactory = upgradeContext.getHostRoleCommandFactory();

      // get a role command order instance that we can adjust for HOU since HOU
      // may use a different ordering than normal start operations
      RoleCommandOrder roleCommandOrder = getRoleCommandOrderForUpgrade(cluster);

      for (String hostName : hosts) {
        // initialize the collection for all stop tasks for every component on
        // the host
        List<TaskWrapper> stopTasks = new ArrayList<>();

        // initialize the collection which will be passed into the RoleGraph for
        // ordering
        Map<String, Map<String, HostRoleCommand>> restartCommandsForHost = new HashMap<>();
        Map<String, HostRoleCommand> restartCommandsByRole = new HashMap<>();
        restartCommandsForHost.put(hostName, restartCommandsByRole);

        // iterating over every host component, build the commands
        for (ServiceComponentHost sch : cluster.getServiceComponentHosts(hostName)) {
          if (!isVersionAdvertised(upgradeContext, sch)) {
            continue;
          }

          HostsType hostsType = upgradeContext.getResolver().getMasterAndHosts(
              sch.getServiceName(), sch.getServiceComponentName());

          // !!! if the hosts do not contain the current one, that means the component
          // either doesn't exist or the downgrade is to the current target version.
          // hostsType better not be null either, but check anyway
          if (null != hostsType && !hostsType.getHosts().contains(hostName)) {
            RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getTargetRepositoryVersion(
                sch.getServiceName());

            LOG.warn("Host {} could not be orchestrated. Either there are no components for {}/{} " +
                "or the target version {} is already current.",
                hostName, sch.getServiceName(), sch.getServiceComponentName(),
                targetRepositoryVersion.getVersion());

            continue;
          }

          // create a STOP task for this host component
          if (!sch.isClientComponent()) {
            stopTasks.add(new TaskWrapper(sch.getServiceName(), sch.getServiceComponentName(),
                Collections.singleton(hostName), new StopTask()));
          }

          // generate a placeholder HRC that can be used to generate the
          // dependency graph - we must use START here since that's what the
          // role command order is defined with - each of these will turn into a
          // RESTART when we create the wrappers later on
          Role role = Role.valueOf(sch.getServiceComponentName());
          HostRoleCommand hostRoleCommand = hrcFactory.create(hostName, role, null,
              RoleCommand.START);

          // add the newly created HRC RESTART
          restartCommandsByRole.put(role.name(), hostRoleCommand);
        }

        // short circuit and move to the next host if there are no commands
        if (stopTasks.isEmpty() && restartCommandsByRole.isEmpty()) {
          LOG.info("There were no {} commands generated for {}",
              upgradeContext.getDirection().getText(false), hostName);

          continue;
        }

        // now process the HRCs created so that we can create the appropriate
        // stage/task wrappers for the RESTARTs
        RoleGraphFactory roleGraphFactory = upgradeContext.getRoleGraphFactory();
        RoleGraph roleGraph = roleGraphFactory.createNew(roleCommandOrder);
        List<Map<String, List<HostRoleCommand>>> stages = roleGraph.getOrderedHostRoleCommands(
            restartCommandsForHost);

        // initialize the list of stage wrappers
        List<StageWrapper> stageWrappers = new ArrayList<>();

        // for every stage, create a stage wrapper around the tasks
        int phaseCounter = 1;
        for (Map<String, List<HostRoleCommand>> stage : stages) {
          List<HostRoleCommand> stageCommandsForHost = stage.get(hostName);
          String stageTitle = String.format("Starting components on %s (phase %d)", hostName,
              phaseCounter++);

          // create task wrappers
          List<TaskWrapper> taskWrappers = new ArrayList<>();
          for (HostRoleCommand command : stageCommandsForHost) {
            StackId stackId = upgradeContext.getRepositoryVersion().getStackId();
            String componentName = command.getRole().name();

            String serviceName = null;

            try {
              AmbariMetaInfo ambariMetaInfo = upgradeContext.getAmbariMetaInfo();
              serviceName = ambariMetaInfo.getComponentToService(stackId.getStackName(),
                  stackId.getStackVersion(), componentName);
            } catch (AmbariException ambariException) {
              LOG.error("Unable to lookup service by component {} for stack {}-{}", componentName,
                  stackId.getStackName(), stackId.getStackVersion());
            }

            TaskWrapper taskWrapper = new TaskWrapper(serviceName, componentName,
                Collections.singleton(hostName), new RestartTask());

            taskWrappers.add(taskWrapper);
          }

          if (!taskWrappers.isEmpty()) {
            StageWrapper startWrapper = new StageWrapper(StageWrapper.Type.RESTART, stageTitle,
                taskWrappers.toArray(new TaskWrapper[taskWrappers.size()]));

            stageWrappers.add(startWrapper);
          }
        }

        // create the manual task between the STOP and START stages
        ManualTask mt = new ManualTask();
        String message = String.format("Please acknowledge that host %s has been prepared.", hostName);
        mt.messages.add(message);

        JsonObject structuredOut = new JsonObject();
        structuredOut.addProperty(TYPE, HostOrderItem.HostOrderActionType.HOST_UPGRADE.toString());
        structuredOut.addProperty(HOST, hostName);
        mt.structuredOut = structuredOut.toString();

        // build the single STOP stage, but only if there are components to
        // stop; client-only hosts have no components which need stopping
        if (!stopTasks.isEmpty()) {
          StageWrapper stopWrapper = new StageWrapper(StageWrapper.Type.STOP,
              String.format("Stop on %s", hostName),
              stopTasks.toArray(new TaskWrapper[stopTasks.size()]));

          wrappers.add(stopWrapper);
        }

        StageWrapper manualWrapper = new StageWrapper(StageWrapper.Type.SERVER_SIDE_ACTION, "Manual Confirmation",
            new TaskWrapper(null, null, Collections.emptySet(), mt));

        wrappers.add(manualWrapper);

        // !!! TODO install_packages for hdp and conf-select changes.  Hopefully these will no-op.
        wrappers.addAll(stageWrappers);
      }

      return wrappers;
    }
Builds the stages for each host which typically consist of a STOP, a
manual wait, and a START. The starting of components can be a single
stage or may consist of several stages if the host components have
dependencies on each other.

@param upgradeContext
         the context
@param hosts
         the list of hostnames
@return the wrappers for a host
ambari-server/src/main/java/org/apache/ambari/server/stack/upgrade/HostOrderGrouping.java