public void addExecutionCommandsToStage()

in ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java [260:509]


  public void addExecutionCommandsToStage(final ActionExecutionContext actionContext, Stage stage,
                                          Map<String, String> requestParams, boolean checkHostIsMemberOfCluster)
      throws AmbariException {

    String actionName = actionContext.getActionName();
    String clusterName = actionContext.getClusterName();
    final Cluster cluster;
    if (null != clusterName) {
      cluster = clusters.getCluster(clusterName);
    } else {
      cluster = null;
    }

    ComponentInfo componentInfo = null;
    List<RequestResourceFilter> resourceFilters = actionContext.getResourceFilters();
    final RequestResourceFilter resourceFilter;
    if (resourceFilters != null && !resourceFilters.isEmpty()) {
      resourceFilter = resourceFilters.get(0);
    } else {
      resourceFilter = new RequestResourceFilter();
    }

    // List of host to select from
    Set<String> candidateHosts = new HashSet<>();

    final String serviceName = actionContext.getExpectedServiceName();
    final String componentName = actionContext.getExpectedComponentName();

    LOG.debug("Called addExecutionCommandsToStage() for serviceName: {}, componentName: {}.", serviceName, componentName);
    if (resourceFilter.getHostNames().isEmpty()) {
      LOG.debug("Resource filter has no hostnames.");
    } else {
      LOG.debug("Resource filter has hosts: {}", StringUtils.join(resourceFilter.getHostNames(), ", "));
    }

    if (null != cluster) {
//      StackId stackId = cluster.getCurrentStackVersion();
      if (serviceName != null && !serviceName.isEmpty()) {
        if (componentName != null && !componentName.isEmpty()) {
          Service service = cluster.getService(serviceName);
          ServiceComponent component = service.getServiceComponent(componentName);
          StackId stackId = component.getDesiredStackId();

          Map<String, ServiceComponentHost> componentHosts = component.getServiceComponentHosts();
          candidateHosts.addAll(componentHosts.keySet());

          try {
            componentInfo = ambariMetaInfo.getComponent(stackId.getStackName(),
                stackId.getStackVersion(), serviceName, componentName);
          } catch (ObjectNotFoundException e) {
            // do nothing, componentId is checked for null later
            LOG.error("Did not find service {} and component {} in stack {}.", serviceName, componentName, stackId.getStackName());
          }
        } else {
          for (String component : cluster.getService(serviceName).getServiceComponents().keySet()) {
            Map<String, ServiceComponentHost> componentHosts = cluster.getService(serviceName)
                .getServiceComponent(component).getServiceComponentHosts();
            candidateHosts.addAll(componentHosts.keySet());
          }
        }
      } else {
        // All hosts are valid target host
        candidateHosts.addAll(clusters.getHostsForCluster(cluster.getClusterName()).keySet());
      }
      LOG.debug("Request for service {} and component {} is set to run on candidate hosts: {}.", serviceName, componentName, StringUtils.join(candidateHosts, ", "));

      // Filter hosts that are in MS
      Set<String> ignoredHosts = maintenanceStateHelper.filterHostsInMaintenanceState(
              candidateHosts, new MaintenanceStateHelper.HostPredicate() {
                @Override
                public boolean shouldHostBeRemoved(final String hostname)
                        throws AmbariException {
                  return ! maintenanceStateHelper.isOperationAllowed(
                          cluster, actionContext.getOperationLevel(),
                          resourceFilter, serviceName, componentName, hostname);
                }
              }
      );

      if (! ignoredHosts.isEmpty()) {
        LOG.debug("Hosts to ignore: {}.", ignoredHosts);
        LOG.debug("Ignoring action for hosts due to maintenance state.Ignored hosts ={}, component={}, service={}, cluster={}, actionName={}",
          ignoredHosts, componentName, serviceName, cluster.getClusterName(), actionContext.getActionName());
      }
    }

    // If request did not specify hosts and there exists no host
    if (resourceFilter.getHostNames().isEmpty() && candidateHosts.isEmpty()) {
      throw new AmbariException("Suitable hosts not found, component="
              + componentName + ", service=" + serviceName
              + ((null == cluster) ? "" : ", cluster=" + cluster.getClusterName() + ", ")
              + "actionName=" + actionContext.getActionName());
    }

    if (checkHostIsMemberOfCluster) {
      // Compare specified hosts to available hosts
      if (!resourceFilter.getHostNames().isEmpty() && !candidateHosts.isEmpty()) {
        for (String hostname : resourceFilter.getHostNames()) {
          if (!candidateHosts.contains(hostname)) {
            throw new AmbariException("Request specifies host " + hostname +
              " but it is not a valid host based on the " +
              "target service=" + serviceName + " and component=" + componentName);
          }
        }
      }
    }

    List<String> targetHosts = resourceFilter.getHostNames();

    //Find target hosts to execute
    if (targetHosts.isEmpty()) {
      TargetHostType hostType = actionContext.getTargetType();
      switch (hostType) {
        case ALL:
          targetHosts.addAll(candidateHosts);
          break;
        case ANY:
          targetHosts.add(managementController.getHealthyHost(candidateHosts));
          break;
        case MAJORITY:
          for (int i = 0; i < (candidateHosts.size() / 2) + 1; i++) {
            String hostname = managementController.getHealthyHost(candidateHosts);
            targetHosts.add(hostname);
            candidateHosts.remove(hostname);
          }
          break;
        default:
          throw new AmbariException("Unsupported target type = " + hostType);
      }
    }

    setAdditionalParametersForStageAccordingToAction(stage, actionContext);

    // create tasks for each host
    for (String hostName : targetHosts) {
      // ensure that any tags that need to be refreshed are extracted from the
      // context and put onto the execution command
      Map<String, String> actionParameters = actionContext.getParameters();

      stage.addHostRoleExecutionCommand(hostName, Role.valueOf(actionContext.getActionName()),
          RoleCommand.ACTIONEXECUTE,
          new ServiceComponentHostOpInProgressEvent(actionContext.getActionName(), hostName,
              System.currentTimeMillis()),
          clusterName, serviceName, actionContext.isRetryAllowed(),
          actionContext.isFailureAutoSkipped());

      Map<String, String> commandParams = new TreeMap<>();

      int taskTimeout = Integer.parseInt(configs.getDefaultAgentTaskTimeout(false));

      // use the biggest of all these:
      // if the action context timeout is bigger than the default, use the context
      // if the action context timeout is smaller than the default, use the default
      // if the action context timeout is undefined, use the default
      if (null != actionContext.getTimeout() && actionContext.getTimeout() > taskTimeout) {
        commandParams.put(COMMAND_TIMEOUT, actionContext.getTimeout().toString());
      } else {
        commandParams.put(COMMAND_TIMEOUT, Integer.toString(taskTimeout));
      }

      if (requestParams != null && requestParams.containsKey(KeyNames.LOG_OUTPUT)) {
        LOG.info("Should command log output?: " + requestParams.get(KeyNames.LOG_OUTPUT));
        commandParams.put(KeyNames.LOG_OUTPUT, requestParams.get(KeyNames.LOG_OUTPUT));
      }

      commandParams.put(SCRIPT, actionName + "." + ACTION_FILE_EXTENSION);
      commandParams.put(SCRIPT_TYPE, TYPE_PYTHON);
      StageUtils.useAmbariJdkInCommandParams(commandParams, configs);

      ExecutionCommand execCmd = stage.getExecutionCommandWrapper(hostName,
        actionContext.getActionName()).getExecutionCommand();

      // !!! ensure that these are empty so that commands have the correct tags
      // applied when the execution is about to be scheduled to run
      execCmd.setConfigurations(new TreeMap<>());

      // if the command should fetch brand new configuration tags before
      // execution, then we don't need to fetch them now
      if (null != actionParameters && !actionParameters.isEmpty()) {
        if (actionParameters.containsKey(KeyNames.OVERRIDE_CONFIGS)) {
          execCmd.setOverrideConfigs(true);
        }
        if (actionParameters.containsKey(KeyNames.OVERRIDE_STACK_NAME)) {
          Map<String, String> clusterLevelParams = execCmd.getClusterLevelParams();
          if (clusterLevelParams == null) {
            clusterLevelParams = new HashMap<>();
          }
          clusterLevelParams.put(STACK_NAME, actionContext.getStackId().getStackName());
          execCmd.setClusterLevelParams(clusterLevelParams);
        }
      }

      execCmd.setServiceName(serviceName == null || serviceName.isEmpty() ?
        resourceFilter.getServiceName() : serviceName);

      execCmd.setComponentName(componentName == null || componentName.isEmpty() ?
        resourceFilter.getComponentName() : componentName);

      Map<String, String> hostLevelParams = execCmd.getHostLevelParams();
      hostLevelParams.put(GPL_LICENSE_ACCEPTED, configs.getGplLicenseAccepted().toString());
      hostLevelParams.put(AGENT_STACK_RETRY_ON_UNAVAILABILITY, configs.isAgentStackRetryOnInstallEnabled());
      hostLevelParams.put(AGENT_STACK_RETRY_COUNT, configs.getAgentStackRetryOnInstallCount());
      for (Map.Entry<String, String> dbConnectorName : configs.getDatabaseConnectorNames().entrySet()) {
        hostLevelParams.put(dbConnectorName.getKey(), dbConnectorName.getValue());
      }
      for (Map.Entry<String, String> previousDBConnectorName : configs.getPreviousDatabaseConnectorNames().entrySet()) {
        hostLevelParams.put(previousDBConnectorName.getKey(), previousDBConnectorName.getValue());
      }

      if (StringUtils.isNotBlank(serviceName)) {
        Service service = cluster.getService(serviceName);
        repoVersionHelper.addRepoInfoToHostLevelParams(cluster, actionContext, service.getDesiredRepositoryVersion(),
            hostLevelParams, hostName);
      } else {
        repoVersionHelper.addRepoInfoToHostLevelParams(cluster, actionContext, null, hostLevelParams, hostName);
      }


      Map<String, String> roleParams = execCmd.getRoleParams();
      if (roleParams == null) {
        roleParams = new TreeMap<>();
      }

      roleParams.putAll(actionParameters);

      SecretReference.replaceReferencesWithPasswords(roleParams, cluster);

      if (componentInfo != null) {
        roleParams.put(COMPONENT_CATEGORY, componentInfo.getCategory());
      }

      // if there is a stack upgrade which is currently suspended then pass that
      // information down with the command as some components may need to know
      if (null != cluster && cluster.isUpgradeSuspended()) {
        cluster.addSuspendedUpgradeParameters(commandParams, roleParams);
      }

      execCmd.setCommandParams(commandParams);
      execCmd.setRoleParams(roleParams);

      if (null != cluster) {
        // Generate localComponents
        for (ServiceComponentHost sch : cluster.getServiceComponentHosts(hostName)) {
          execCmd.getLocalComponents().add(sch.getServiceComponentName());
        }
      }

      actionContext.visitAll(execCmd);
    }
  }