private void findHostAndAddServiceCheckAction(final ActionExecutionContext actionExecutionContext,
      final RequestResourceFilter resourceFilter, Stage stage) throws AmbariException {

    String clusterName = actionExecutionContext.getClusterName();
    final Cluster cluster = clusters.getCluster(clusterName);
    final String componentName = actionMetadata.getClient(resourceFilter.getServiceName());
    final String serviceName = resourceFilter.getServiceName();
    String smokeTestRole = actionMetadata.getServiceCheckAction(serviceName);
    if (null == smokeTestRole) {
      smokeTestRole = actionExecutionContext.getActionName();
    }

    Set<String> candidateHosts;
    final Map<String, ServiceComponentHost> serviceHostComponents;

    if (componentName != null) {
      serviceHostComponents = cluster.getService(serviceName).getServiceComponent(componentName).getServiceComponentHosts();

      if (serviceHostComponents.isEmpty()) {
        throw new AmbariException(MessageFormat.format("No hosts found for service: {0}, component: {1} in cluster: {2}",
            serviceName, componentName, clusterName));
      }

      // If specified a specific host, run on it as long as it contains the component.
      // Otherwise, use candidates that contain the component.
      List<String> candidateHostsList = resourceFilter.getHostNames();
      if (candidateHostsList != null && !candidateHostsList.isEmpty()) {
        candidateHosts = new HashSet<>(candidateHostsList);

        // Get the intersection.
        candidateHosts.retainAll(serviceHostComponents.keySet());

        if (candidateHosts.isEmpty()) {
          throw new AmbariException(MessageFormat.format("The resource filter for hosts does not contain components for " +
                  "service: {0}, component: {1} in cluster: {2}", serviceName, componentName, clusterName));
        }
      } else {
        candidateHosts = serviceHostComponents.keySet();
      }
    } else {
      // TODO: This code branch looks unreliable (taking random component, should prefer the clients)
      Map<String, ServiceComponent> serviceComponents = cluster.getService(serviceName).getServiceComponents();

      // Filter components without any HOST
      Iterator<String> serviceComponentNameIterator = serviceComponents.keySet().iterator();
      while (serviceComponentNameIterator.hasNext()){
        String componentToCheck = serviceComponentNameIterator.next();
         if (serviceComponents.get(componentToCheck).getServiceComponentHosts().isEmpty()){
           serviceComponentNameIterator.remove();
         }
      }

      if (serviceComponents.isEmpty()) {
        throw new AmbariException(MessageFormat.format("Did not find any hosts with components for service: {0} in cluster: {1}",
            serviceName, clusterName));
      }

      // Pick a random service (should prefer clients).
      ServiceComponent serviceComponent = serviceComponents.values().iterator().next();
      serviceHostComponents = serviceComponent.getServiceComponentHosts();
      candidateHosts = serviceHostComponents.keySet();
    }

    // check if all hostnames are valid.
    for(String candidateHostName: candidateHosts) {
      ServiceComponentHost serviceComponentHost = serviceHostComponents.get(candidateHostName);

      if (serviceComponentHost == null) {
        throw new AmbariException("Provided hostname = "
            + candidateHostName + " is either not a valid cluster host or does not satisfy the filter condition.");
      }
    }

    // Filter out hosts that are in maintenance mode - they should never be included in service checks
    Set<String> hostsInMaintenanceMode = new HashSet<>();
    if (actionExecutionContext.isMaintenanceModeHostExcluded()) {
      Iterator<String> iterator = candidateHosts.iterator();
      while (iterator.hasNext()) {
        String candidateHostName = iterator.next();
        ServiceComponentHost serviceComponentHost = serviceHostComponents.get(candidateHostName);
        Host host = serviceComponentHost.getHost();
        if (host.getMaintenanceState(cluster.getClusterId()) == MaintenanceState.ON) {
          hostsInMaintenanceMode.add(candidateHostName);
          iterator.remove();
        }
      }
    }

    // Filter out hosts that are not healthy, i.e., all hosts should be heartbeating.
    // Pick one randomly. If there are none, throw an exception.
    List<String> healthyHostNames = managementController.selectHealthyHosts(candidateHosts);
    if (healthyHostNames.isEmpty()) {
      String message = MessageFormat.format(
          "While building a service check command for {0}, there were no healthy eligible hosts: unhealthy[{1}], maintenance[{2}]",
          serviceName, StringUtils.join(candidateHosts, ','),
          StringUtils.join(hostsInMaintenanceMode, ','));

      throw new AmbariException(message);
    }

    String preferredHostName = selectRandomHostNameWithPreferenceOnAvailability(healthyHostNames);

    long nowTimestamp = System.currentTimeMillis();
    Map<String, String> actionParameters = actionExecutionContext.getParameters();
    addServiceCheckAction(stage, preferredHostName, smokeTestRole, nowTimestamp, serviceName, componentName,
        actionParameters, actionExecutionContext.isRetryAllowed(),
        actionExecutionContext.isFailureAutoSkipped(),false);
  }
Called during the start/stop/restart of services, plus custom commands during Stack Upgrade.
@param actionExecutionContext Execution Context
@param resourceFilter Resource Filter
@param stage Command stage
@param additionalCommandParams Additional command params to add the the stage
@param commandDetail String for the command detail
@throws AmbariException
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java