You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2014/02/25 19:20:34 UTC

[3/3] git commit: AMBARI-4791. API call to restart all components on one or more hosts should result in one request. (swagle)

AMBARI-4791. API call to restart all components on one or more hosts should result in one request. (swagle)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c6987eee
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c6987eee
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c6987eee

Branch: refs/heads/trunk
Commit: c6987eeef05bce7404635a9a88a4f30b94c134e0
Parents: 0b15548
Author: Siddharth Wagle <sw...@hortonworks.com>
Authored: Mon Feb 24 19:39:57 2014 -0800
Committer: Siddharth Wagle <sw...@hortonworks.com>
Committed: Tue Feb 25 10:18:15 2014 -0800

----------------------------------------------------------------------
 .../ambari/server/actionmanager/Request.java    |  81 +--
 .../controller/ActionExecutionContext.java      |  87 ++--
 .../controller/AmbariActionExecutionHelper.java | 320 ++++++------
 .../AmbariCustomCommandExecutionHelper.java     | 494 ++++++++-----------
 .../AmbariManagementControllerImpl.java         | 280 +++++++++--
 .../ambari/server/controller/AmbariServer.java  |   1 +
 .../server/controller/ControllerModule.java     |   5 +-
 .../server/controller/ExecuteActionRequest.java |  48 +-
 .../controller/MaintenanceStateHelper.java      |  15 +-
 .../internal/RequestResourceFilter.java         |  69 +++
 .../internal/RequestResourceProvider.java       |  49 +-
 .../server/orm/entities/RequestEntity.java      |  49 +-
 .../entities/RequestResourceFilterEntity.java   |  94 ++++
 .../server/upgrade/UpgradeCatalog150.java       |  10 +
 .../main/resources/Ambari-DDL-MySQL-CREATE.sql  |   4 +-
 .../main/resources/Ambari-DDL-Oracle-CREATE.sql |   4 +-
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   7 +-
 .../src/main/resources/META-INF/persistence.xml |   2 +-
 .../src/main/resources/properties.json          |   4 +-
 .../actionmanager/TestActionDBAccessorImpl.java |   8 +-
 .../AmbariManagementControllerTest.java         | 431 +++++++++++++---
 .../controller/MaintenanceStateHelperTest.java  |  26 +-
 .../internal/RequestResourceProviderTest.java   |  72 ++-
 23 files changed, 1411 insertions(+), 749 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/c6987eee/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
index d1047a7..22731ee 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/Request.java
@@ -23,7 +23,9 @@ import com.google.inject.assistedinject.Assisted;
 import com.google.inject.assistedinject.AssistedInject;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.ExecuteActionRequest;
+import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.orm.entities.RequestEntity;
+import org.apache.ambari.server.orm.entities.RequestResourceFilterEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.state.Clusters;
 import org.slf4j.Logger;
@@ -47,9 +49,7 @@ public class Request {
   private long endTime;
   private HostRoleStatus status; // not persisted yet
   private String inputs;
-  private String targetService;
-  private String targetComponent;
-  private String targetHosts;
+  private List<RequestResourceFilter> resourceFilters;
   private RequestType requestType;
 
   private Collection<Stage> stages = new ArrayList<Stage>();
@@ -112,9 +112,7 @@ public class Request {
                  Clusters clusters, Gson gson) throws AmbariException {
     this(stages, clusters);
     if (actionRequest != null) {
-      this.targetService = actionRequest.getServiceName();
-      this.targetComponent = actionRequest.getComponentName();
-      this.targetHosts = gson.toJson(actionRequest.getHosts());
+      this.resourceFilters = actionRequest.getResourceFilters();
       this.inputs = gson.toJson(actionRequest.getParameters());
       this.requestType = actionRequest.isCommand() ? RequestType.COMMAND : RequestType.ACTION;
       this.commandName = actionRequest.isCommand() ? actionRequest.getCommandName() : actionRequest.getActionName();
@@ -138,13 +136,11 @@ public class Request {
     this.endTime = entity.getEndTime();
     this.requestContext = entity.getRequestContext();
     this.inputs = entity.getInputs();
-    this.targetService = entity.getTargetService();
-    this.targetComponent = entity.getTargetComponent();
-    this.targetHosts = entity.getTargetHosts();
+
     this.requestType = entity.getRequestType();
     this.commandName = entity.getCommandName();
     this.status = entity.getStatus();
-    if (entity.getRequestScheduleEntity() !=null) {
+    if (entity.getRequestScheduleEntity() != null) {
       this.requestScheduleId = entity.getRequestScheduleEntity().getScheduleId();
     }
 
@@ -152,6 +148,28 @@ public class Request {
       Stage stage = stageFactory.createExisting(stageEntity);
       stages.add(stage);
     }
+
+    for (RequestResourceFilterEntity resourceFilterEntity : entity.getResourceFilterEntities()) {
+      RequestResourceFilter resourceFilter =
+        new RequestResourceFilter(
+            resourceFilterEntity.getServiceName(),
+            resourceFilterEntity.getComponentName(),
+            getHostsList(resourceFilterEntity.getHosts()));
+      this.resourceFilters.add(resourceFilter);
+    }
+
+  }
+
+  private List<String> getHostsList(String hosts) {
+    List<String> hostList = new ArrayList<String>();
+    if (hosts != null && !hosts.isEmpty()) {
+      for (String host : hosts.split(",")) {
+        if (!host.trim().isEmpty()) {
+          hostList.add(host.trim());
+        }
+      }
+    }
+    return hostList;
   }
 
   public Collection<Stage> getStages() {
@@ -176,13 +194,22 @@ public class Request {
     requestEntity.setEndTime(endTime);
     requestEntity.setRequestContext(requestContext);
     requestEntity.setInputs(inputs);
-    requestEntity.setTargetService(targetService);
-    requestEntity.setTargetComponent(targetComponent);
-    requestEntity.setTargetHosts(targetHosts);
     requestEntity.setRequestType(requestType);
     requestEntity.setRequestScheduleId(requestScheduleId);
     //TODO set all fields
 
+    if (resourceFilters != null) {
+      List<RequestResourceFilterEntity> filterEntities = new ArrayList<RequestResourceFilterEntity>();
+      for (RequestResourceFilter resourceFilter : resourceFilters) {
+        RequestResourceFilterEntity filterEntity = new RequestResourceFilterEntity();
+        filterEntity.setServiceName(resourceFilter.getServiceName());
+        filterEntity.setComponentName(resourceFilter.getComponentName());
+        filterEntity.setRequestEntity(requestEntity);
+        filterEntity.setRequestId(requestId);
+      }
+      requestEntity.setResourceFilterEntities(filterEntities);
+    }
+
     return requestEntity;
   }
 
@@ -231,28 +258,12 @@ public class Request {
     this.inputs = inputs;
   }
 
-  public String getTargetService() {
-    return targetService;
-  }
-
-  public void setTargetService(String targetService) {
-    this.targetService = targetService;
-  }
-
-  public String getTargetComponent() {
-    return targetComponent;
-  }
-
-  public void setTargetComponent(String targetComponent) {
-    this.targetComponent = targetComponent;
-  }
-
-  public String getTargetHosts() {
-    return targetHosts;
+  public List<RequestResourceFilter> getResourceFilters() {
+    return resourceFilters;
   }
 
-  public void setTargetHosts(String targetHosts) {
-    this.targetHosts = targetHosts;
+  public void setResourceFilters(List<RequestResourceFilter> resourceFilters) {
+    this.resourceFilters = resourceFilters;
   }
 
   public RequestType getRequestType() {
@@ -298,9 +309,7 @@ public class Request {
         ", startTime=" + startTime +
         ", endTime=" + endTime +
         ", inputs='" + inputs + '\'' +
-        ", targetService='" + targetService + '\'' +
-        ", targetComponent='" + targetComponent + '\'' +
-        ", targetHosts='" + targetHosts + '\'' +
+        ", resourceFilters='" + resourceFilters + '\'' +
         ", requestType=" + requestType +
         ", stages=" + stages +
         '}';

http://git-wip-us.apache.org/repos/asf/ambari/blob/c6987eee/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
index b59eff1..37a404f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
@@ -20,8 +20,8 @@
 package org.apache.ambari.server.controller;
 
 import org.apache.ambari.server.actionmanager.TargetHostType;
+import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -31,59 +31,60 @@ import java.util.Map;
 public class ActionExecutionContext {
   private final String clusterName;
   private final String actionName;
-  private final String serviceName;
-  private final String componentName;
-  private final String componentCategory;
-  private final List<String> hosts;
-  private final Map<String, String> parameters;
-  private final TargetHostType targetType;
-  private final Short timeout;
+  private List<RequestResourceFilter> resourceFilters;
+  private Map<String, String> parameters;
+  private TargetHostType targetType;
+  private Short timeout;
+  private String expectedServiceName;
+  private String expectedComponentName;
 
   /**
    * Create an ActionExecutionContext to execute an action from a request
    */
-  public ActionExecutionContext(String clusterName, String actionName, String serviceName,
-                                String componentName, String componentCategory,
-                                List<String> hosts, Map<String, String> parameters,
-                                TargetHostType targetType, Short timeout) {
+  public ActionExecutionContext(String clusterName, String actionName,
+      List<RequestResourceFilter> resourceFilters,
+      Map<String, String> parameters, TargetHostType targetType,
+      Short timeout, String expectedServiceName,
+      String expectedComponentName) {
+
     this.clusterName = clusterName;
     this.actionName = actionName;
-    this.serviceName = serviceName;
-    this.componentName = componentName;
-    this.componentCategory = componentCategory;
+    this.resourceFilters = resourceFilters;
     this.parameters = parameters;
-    this.hosts = new ArrayList<String>();
-    if (hosts != null) {
-      this.hosts.addAll(hosts);
-    }
     this.targetType = targetType;
     this.timeout = timeout;
+    this.expectedServiceName = expectedServiceName;
+    this.expectedComponentName = expectedComponentName;
   }
 
-  public String getClusterName() {
-    return clusterName;
+  public ActionExecutionContext(String clusterName, String actionName,
+                                List<RequestResourceFilter> resourceFilters) {
+    this.clusterName = clusterName;
+    this.actionName = actionName;
+    this.resourceFilters = resourceFilters;
   }
 
-  public String getActionName() {
-    return actionName;
+  public ActionExecutionContext(String clusterName, String commandName,
+                                List<RequestResourceFilter> resourceFilters,
+                                Map<String, String> parameters) {
+    this.clusterName = clusterName;
+    this.actionName = commandName;
+    this.resourceFilters = resourceFilters;
+    this.parameters = parameters;
   }
 
-  public String getServiceName() {
-    return serviceName;
+  public String getClusterName() {
+    return clusterName;
   }
 
-  public String getComponentName() {
-    return componentName;
+  public String getActionName() {
+    return actionName;
   }
 
   public Map<String, String> getParameters() {
     return parameters;
   }
 
-  public List<String> getHosts() {
-    return hosts;
-  }
-
   public TargetHostType getTargetType() {
     return targetType;
   }
@@ -92,7 +93,27 @@ public class ActionExecutionContext {
     return timeout;
   }
 
-  public String getComponentCategory() {
-    return componentCategory;
+  public List<RequestResourceFilter> getResourceFilters() {
+    return resourceFilters;
+  }
+
+  public String getExpectedServiceName() {
+    return expectedServiceName;
+  }
+
+  public String getExpectedComponentName() {
+    return expectedComponentName;
+  }
+
+  @Override
+  public String toString() {
+    return "ActionExecutionContext{" +
+      "clusterName='" + clusterName + '\'' +
+      ", actionName='" + actionName + '\'' +
+      ", resourceFilters=" + resourceFilters +
+      ", parameters=" + parameters +
+      ", targetType=" + targetType +
+      ", timeout=" + timeout +
+      '}';
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/c6987eee/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
index 74aa1fd..85f9078 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java
@@ -18,16 +18,8 @@
 
 package org.apache.ambari.server.controller;
 
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCHEMA_VERSION;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
@@ -37,7 +29,7 @@ import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.TargetHostType;
 import org.apache.ambari.server.agent.ExecutionCommand;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
-import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.customactions.ActionDefinition;
 import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.state.Cluster;
@@ -51,45 +43,51 @@ import org.apache.ambari.server.utils.StageUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMPONENT_CATEGORY;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCHEMA_VERSION;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMPONENT_CATEGORY;
 
 /**
  * Helper class containing logic to process custom action execution requests
  */
+@Singleton
 public class AmbariActionExecutionHelper {
   private final static Logger LOG =
       LoggerFactory.getLogger(AmbariActionExecutionHelper.class);
   private static final String TYPE_PYTHON = "PYTHON";
+
+  @Inject
   private ActionMetadata actionMetadata;
+  @Inject
   private Clusters clusters;
-  private AmbariManagementControllerImpl amcImpl;
+  @Inject
+  private AmbariManagementController managementController;
+  @Inject
   private ActionManager actionManager;
+  @Inject
   private AmbariMetaInfo ambariMetaInfo;
 
-  public AmbariActionExecutionHelper(ActionMetadata actionMetadata, Clusters clusters,
-                                     AmbariManagementControllerImpl amcImpl) {
-    this.amcImpl = amcImpl;
-    this.actionMetadata = actionMetadata;
-    this.clusters = clusters;
-    this.actionManager = amcImpl.getActionManager();
-    this.ambariMetaInfo = amcImpl.getAmbariMetaInfo();
-  }
-
-  // TODO: validate should not return context, should make it consistent with Command Execution helper
   /**
-   * Validates the request to execute an action
-   *
+   * Validates the request to execute an action.
    * @param actionRequest
-   * @param cluster
-   * @return
    * @throws AmbariException
    */
-  public ActionExecutionContext validateCustomAction(ExecuteActionRequest actionRequest, Cluster cluster)
-      throws AmbariException {
+  public void validateAction(ExecuteActionRequest actionRequest) throws AmbariException {
+    Cluster cluster = clusters.getCluster(actionRequest.getClusterName());
+
+    if (cluster == null) {
+      throw new AmbariException("Unable to find cluster. clusterName = " +
+        actionRequest.getClusterName());
+    }
+
     if (actionRequest.getActionName() == null || actionRequest.getActionName().isEmpty()) {
       throw new AmbariException("Action name must be specified");
     }
@@ -99,196 +97,214 @@ public class AmbariActionExecutionHelper {
       throw new AmbariException("Action " + actionRequest.getActionName() + " does not exist");
     }
 
+    if (actionDef.getInputs() != null) {
+      String[] inputs = actionDef.getInputs().split(",");
+      for (String input : inputs) {
+        String inputName = input.trim();
+        if (!inputName.isEmpty()) {
+          boolean mandatory = true;
+          if (inputName.startsWith("[") && inputName.endsWith("]")) {
+            mandatory = false;
+          }
+          if (mandatory && !actionRequest.getParameters().containsKey(inputName)) {
+            throw new AmbariException("Action " + actionRequest.getActionName() + " requires input '" +
+              input.trim() + "' that is not provided.");
+          }
+        }
+      }
+    }
+
+
     StackId stackId = cluster.getCurrentStackVersion();
     String expectedService = actionDef.getTargetService() == null ? "" : actionDef.getTargetService();
-    String actualService = actionRequest.getServiceName() == null ? "" : actionRequest.getServiceName();
-    if (!expectedService.isEmpty() && !actualService.isEmpty() && !expectedService.equals(actualService)) {
-      throw new AmbariException("Action " + actionRequest.getActionName() + " targets service " + actualService +
+
+    List<RequestResourceFilter> resourceFilters = actionRequest.getResourceFilters();
+    String targetService = "";
+    String targetComponent = "";
+    RequestResourceFilter resourceFilter = null;
+
+    if (resourceFilters != null && !resourceFilters.isEmpty()) {
+      if (resourceFilters.size() > 1) {
+        throw new AmbariException("Custom action definition only allows one " +
+          "resource filter to be specified.");
+      }
+
+      resourceFilter = resourceFilters.get(0);
+      String actualService = resourceFilter.getServiceName() == null ? "" : resourceFilter.getServiceName();
+      if (!expectedService.isEmpty() && !actualService.isEmpty() && !expectedService.equals(actualService)) {
+        throw new AmbariException("Action " + actionRequest.getActionName() + " targets service " + actualService +
           " that does not match with expected " + expectedService);
-    }
+      }
 
-    String targetService = expectedService;
-    if (targetService == null || targetService.isEmpty()) {
-      targetService = actualService;
-    }
+      targetService = expectedService;
+      if (targetService == null || targetService.isEmpty()) {
+        targetService = actualService;
+      }
 
-    if (targetService != null && !targetService.isEmpty()) {
-      ServiceInfo serviceInfo;
-      try {
-        serviceInfo = ambariMetaInfo.getService(stackId.getStackName(), stackId.getStackVersion(),
+      if (targetService != null && !targetService.isEmpty()) {
+        ServiceInfo serviceInfo;
+        try {
+          serviceInfo = ambariMetaInfo.getService(stackId.getStackName(), stackId.getStackVersion(),
             targetService);
-      } catch (StackAccessException se) {
-        serviceInfo = null;
-      }
+        } catch (StackAccessException se) {
+          serviceInfo = null;
+        }
 
-      if (serviceInfo == null) {
-        throw new AmbariException("Action " + actionRequest.getActionName() + " targets service " + targetService +
-            " that does not exist.");
+        if (serviceInfo == null) {
+          throw new AmbariException("Action " + actionRequest.getActionName() +
+            " targets service " + targetService + " that does not exist.");
+        }
       }
-    }
 
-    String expectedComponent = actionDef.getTargetComponent() == null ? "" : actionDef.getTargetComponent();
-    String actualComponent = actionRequest.getComponentName() == null ? "" : actionRequest.getComponentName();
-    if (!expectedComponent.isEmpty() && !actualComponent.isEmpty() && !expectedComponent.equals(actualComponent)) {
-      throw new AmbariException("Action " + actionRequest.getActionName() + " targets component " + actualComponent +
+      String expectedComponent = actionDef.getTargetComponent() == null ? "" : actionDef.getTargetComponent();
+      String actualComponent = resourceFilter.getComponentName() == null ? "" : resourceFilter.getComponentName();
+      if (!expectedComponent.isEmpty() && !actualComponent.isEmpty() && !expectedComponent.equals(actualComponent)) {
+        throw new AmbariException("Action " + actionRequest.getActionName() + " targets component " + actualComponent +
           " that does not match with expected " + expectedComponent);
-    }
+      }
 
-    String targetComponent = expectedComponent;
-    String componentCategory = "";
-    if (targetComponent == null || targetComponent.isEmpty()) {
-      targetComponent = actualComponent;
-    }
+      targetComponent = expectedComponent;
+      if (targetComponent == null || targetComponent.isEmpty()) {
+        targetComponent = actualComponent;
+      }
 
-    if (!targetComponent.isEmpty() && targetService.isEmpty()) {
-      throw new AmbariException("Action " + actionRequest.getActionName() + " targets component " + targetComponent +
+      if (!targetComponent.isEmpty() && targetService.isEmpty()) {
+        throw new AmbariException("Action " + actionRequest.getActionName() + " targets component " + targetComponent +
           " without specifying the target service.");
-    }
+      }
 
-    if (targetComponent != null && !targetComponent.isEmpty()) {
-      ComponentInfo compInfo;
-      try {
-        compInfo = ambariMetaInfo.getComponent(stackId.getStackName(), stackId.getStackVersion(),
+      if (targetComponent != null && !targetComponent.isEmpty()) {
+        ComponentInfo compInfo;
+        try {
+          compInfo = ambariMetaInfo.getComponent(stackId.getStackName(), stackId.getStackVersion(),
             targetService, targetComponent);
-      } catch (StackAccessException se) {
-        compInfo = null;
-      }
+        } catch (StackAccessException se) {
+          compInfo = null;
+        }
 
-      if (compInfo == null) {
-        throw new AmbariException("Action " + actionRequest.getActionName() + " targets component " + targetComponent +
+        if (compInfo == null) {
+          throw new AmbariException("Action " + actionRequest.getActionName() + " targets component " + targetComponent +
             " that does not exist.");
-      }
-      componentCategory = compInfo.getCategory();
-    }
-
-    if (actionDef.getInputs() != null) {
-      String[] inputs = actionDef.getInputs().split(",");
-      for (String input : inputs) {
-        String inputName = input.trim();
-        if (!inputName.isEmpty()) {
-          boolean mandatory = true;
-          if (inputName.startsWith("[") && inputName.endsWith("]")) {
-            mandatory = false;
-          }
-          if (mandatory && !actionRequest.getParameters().containsKey(inputName)) {
-            throw new AmbariException("Action " + actionRequest.getActionName() + " requires input '" +
-                input.trim() + "' that is not provided.");
-          }
         }
       }
     }
 
-    if (TargetHostType.SPECIFIC.name().equals(actionDef.getTargetType())
-        || (targetService.isEmpty() && targetService.isEmpty())) {
-      if (actionRequest.getHosts().size() == 0) {
+    if (TargetHostType.SPECIFIC.equals(actionDef.getTargetType())
+      || (targetService.isEmpty() && targetComponent.isEmpty())) {
+      if (resourceFilter == null || resourceFilter.getHostNames().size() == 0) {
         throw new AmbariException("Action " + actionRequest.getActionName() + " requires explicit target host(s)" +
-            " that is not provided.");
+          " that is not provided.");
       }
     }
-
-    LOG.info("Received action execution request"
-        + ", clusterName=" + actionRequest.getClusterName()
-        + ", request=" + actionRequest.toString());
-
-    ActionExecutionContext actionExecutionContext = new ActionExecutionContext(
-      actionRequest.getClusterName(), actionRequest.getActionName(),
-      targetService, targetComponent, componentCategory, actionRequest.getHosts(),
-      actionRequest.getParameters(), actionDef.getTargetType(), actionDef.getDefaultTimeout());
-
-    return actionExecutionContext;
   }
 
+
   /**
    * Add tasks to the stage based on the requested action execution
-   *
-   * @param actionContext   the context associated with the action
-   * @param stage           stage into which tasks must be inserted
-   * @param configuration
-   * @param hostsMap
-   * @param hostLevelParams
+   * @param actionContext the context associated with the action
+   * @param stage stage into which tasks must be inserted
+   * @param hostLevelParams host level params to send with the command
    * @throws AmbariException
    */
-  public void addAction(ActionExecutionContext actionContext, Stage stage,
-                        Configuration configuration, HostsMap hostsMap, Map<String, String> hostLevelParams)
+  public void addExecutionCommandsToStage(ActionExecutionContext
+    actionContext, Stage stage, Map<String, String> hostLevelParams)
       throws AmbariException {
+
     String actionName = actionContext.getActionName();
     String clusterName = actionContext.getClusterName();
-    String serviceName = actionContext.getServiceName();
-    String componentName = actionContext.getComponentName();
+    Cluster cluster = clusters.getCluster(clusterName);
+
+    List<RequestResourceFilter> resourceFilters = actionContext.getResourceFilters();
+
+    RequestResourceFilter resourceFilter = new RequestResourceFilter();
+    if (resourceFilters != null && !resourceFilters.isEmpty()) {
+      resourceFilter = resourceFilters.get(0);
+    }
 
     // List of host to select from
     Set<String> candidateHosts = new HashSet<String>();
-    if (!serviceName.isEmpty()) {
-      if (!componentName.isEmpty()) {
+
+    String serviceName = actionContext.getExpectedServiceName();
+    String componentName = actionContext.getExpectedComponentName();
+    StackId stackId = cluster.getCurrentStackVersion();
+    ComponentInfo componentInfo = null;
+
+    if (serviceName != null && !serviceName.isEmpty()) {
+      if (componentName != null && !componentName.isEmpty()) {
         Map<String, ServiceComponentHost> componentHosts =
-            clusters.getCluster(clusterName).getService(serviceName)
-                .getServiceComponent(componentName).getServiceComponentHosts();
+          cluster.getService(serviceName)
+            .getServiceComponent(componentName).getServiceComponentHosts();
         candidateHosts.addAll(componentHosts.keySet());
+        componentInfo = ambariMetaInfo.getComponentCategory(stackId.getStackName(),
+          stackId.getStackVersion(), serviceName, componentName);
       } else {
-        for (String component : clusters.getCluster(clusterName).getService(serviceName)
-            .getServiceComponents().keySet()) {
+        for (String component : cluster.getService(serviceName).getServiceComponents().keySet()) {
           Map<String, ServiceComponentHost> componentHosts =
-              clusters.getCluster(clusterName).getService(serviceName)
-                  .getServiceComponent(component).getServiceComponentHosts();
+            cluster.getService(serviceName)
+              .getServiceComponent(component).getServiceComponentHosts();
           candidateHosts.addAll(componentHosts.keySet());
         }
       }
     } else {
       // All hosts are valid target host
-      candidateHosts.addAll(amcImpl.getClusters().getHostsForCluster(clusterName).keySet());
+      candidateHosts.addAll(clusters.getHostsForCluster(cluster.getClusterName()).keySet());
     }
 
     // If request did not specify hosts and there exists no host
-    if (actionContext.getHosts().isEmpty() && candidateHosts.isEmpty()) {
+    if (resourceFilter.getHostNames().isEmpty() && candidateHosts.isEmpty()) {
       throw new AmbariException("Suitable hosts not found, component="
-          + componentName + ", service=" + serviceName
-          + ", cluster=" + clusterName + ", actionName=" + actionName);
+        + componentName + ", service=" + serviceName
+        + ", cluster=" + cluster.getClusterName() + ", " +
+        "actionName=" + actionContext.getActionName());
     }
 
     // Compare specified hosts to available hosts
-    if (!actionContext.getHosts().isEmpty() && !candidateHosts.isEmpty()) {
-      for (String hostname : actionContext.getHosts()) {
+    if (!resourceFilter.getHostNames().isEmpty() && !candidateHosts.isEmpty()) {
+      for (String hostname : resourceFilter.getHostNames()) {
         if (!candidateHosts.contains(hostname)) {
-          throw new AmbariException("Request specifies host " + hostname + " but its not a valid host based on the " +
-              "target service=" + serviceName + " and component=" + componentName);
+          throw new AmbariException("Request specifies host " + hostname +
+            " but its not a valid host based on the " +
+            "target service=" + serviceName + " and component=" + componentName);
         }
       }
     }
 
+    List<String> targetHosts = resourceFilter.getHostNames();
+
     //Find target hosts to execute
-    if (actionContext.getHosts().isEmpty()) {
+    if (targetHosts.isEmpty()) {
       TargetHostType hostType = actionContext.getTargetType();
       switch (hostType) {
         case ALL:
-          actionContext.getHosts().addAll(candidateHosts);
+          targetHosts.addAll(candidateHosts);
           break;
         case ANY:
-          actionContext.getHosts().add(amcImpl.getHealthyHost(candidateHosts));
+          targetHosts.add(managementController.getHealthyHost(candidateHosts));
           break;
         case MAJORITY:
           for (int i = 0; i < (candidateHosts.size() / 2) + 1; i++) {
-            String hostname = amcImpl.getHealthyHost(candidateHosts);
-            actionContext.getHosts().add(hostname);
+            String hostname = managementController.getHealthyHost(candidateHosts);
+            targetHosts.add(hostname);
             candidateHosts.remove(hostname);
           }
           break;
         default:
-          throw new AmbariException("Unsupported target type=" + hostType);
+          throw new AmbariException("Unsupported target type = " + hostType);
       }
     }
 
     //create tasks for each host
-    for (String hostName : actionContext.getHosts()) {
-      stage.addHostRoleExecutionCommand(hostName, Role.valueOf(actionContext.getActionName()), RoleCommand.ACTIONEXECUTE,
-          new ServiceComponentHostOpInProgressEvent(actionContext.getActionName(), hostName,
-              System.currentTimeMillis()), clusterName, actionContext.getServiceName());
-
-      Cluster cluster = clusters.getCluster(clusterName);
+    for (String hostName : targetHosts) {
+      stage.addHostRoleExecutionCommand(hostName,
+        Role.valueOf(actionContext.getActionName()), RoleCommand.ACTIONEXECUTE,
+          new ServiceComponentHostOpInProgressEvent(actionContext.getActionName(),
+            hostName, System.currentTimeMillis()), clusterName,
+              serviceName);
 
       Map<String, Map<String, String>> configurations = new TreeMap<String, Map<String, String>>();
       Map<String, Map<String, String>> configTags = null;
-      if (!actionContext.getServiceName().isEmpty()) {
-        configTags = amcImpl.findConfigurationTagsWithOverrides(cluster, hostName);
+      if (!serviceName.isEmpty()) {
+        configTags = managementController.findConfigurationTagsWithOverrides(cluster, hostName);
       }
 
       Map<String, String> commandParams = actionContext.getParameters();
@@ -298,7 +314,7 @@ public class AmbariActionExecutionHelper {
       commandParams.put(SCHEMA_VERSION, AmbariMetaInfo.SCHEMA_VERSION_2);
 
       ExecutionCommand execCmd = stage.getExecutionCommandWrapper(hostName,
-          actionContext.getActionName()).getExecutionCommand();
+        actionContext.getActionName()).getExecutionCommand();
 
       /*
        * TODO Execution command field population should be (partially?)
@@ -308,25 +324,27 @@ public class AmbariActionExecutionHelper {
       execCmd.setConfigurationTags(configTags);
       execCmd.setHostLevelParams(hostLevelParams);
       execCmd.setCommandParams(commandParams);
-      execCmd.setServiceName(serviceName);
-      execCmd.setComponentName(componentName);
+      execCmd.setServiceName(serviceName == null || serviceName.isEmpty() ?
+        resourceFilter.getServiceName() : serviceName);
+      execCmd.setComponentName(componentName == null || componentName.isEmpty() ?
+        resourceFilter.getComponentName() : componentName);
 
       Map<String, String> roleParams = execCmd.getRoleParams();
       if (roleParams == null) {
         roleParams = new TreeMap<String, String>();
       }
       roleParams.putAll(actionContext.getParameters());
-      roleParams.put(COMPONENT_CATEGORY, actionContext.getComponentCategory());
+      if (componentInfo != null) {
+        roleParams.put(COMPONENT_CATEGORY, componentInfo.getCategory());
+      }
       execCmd.setRoleParams(roleParams);
 
       // Generate cluster host info
       execCmd.setClusterHostInfo(
-          StageUtils.getClusterHostInfo(clusters.getHostsForCluster(clusterName), cluster));
-      
+        StageUtils.getClusterHostInfo(clusters.getHostsForCluster(clusterName), cluster));
+
       // cluster passive map
-      execCmd.setPassiveInfo(
-          MaintenanceStateHelper.getMaintenanceHostCompoments(clusters, cluster));
-          
+      execCmd.setPassiveInfo(MaintenanceStateHelper.getMaintenanceHostCompoments(clusters, cluster));
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/c6987eee/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
index ba42cc5..abd82ac 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java
@@ -29,6 +29,7 @@ import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.agent.ExecutionCommand;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
@@ -42,9 +43,7 @@ import org.apache.ambari.server.state.RepositoryInfo;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
-import org.apache.ambari.server.state.ServiceComponentHostEvent;
 import org.apache.ambari.server.state.ServiceInfo;
-import org.apache.ambari.server.state.ServiceOsSpecific;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.StackInfo;
 import org.apache.ambari.server.state.State;
@@ -53,7 +52,6 @@ import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -62,29 +60,15 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
-
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMMAND_TIMEOUT;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.COMPONENT_CATEGORY;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.CUSTOM_COMMAND;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_DRIVER_FILENAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.DB_NAME;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JAVA_HOME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JCE_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_LOCATION;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.JDK_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.MYSQL_JDBC_URL;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.ORACLE_JDBC_URL;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.PACKAGE_LIST;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.REPO_INFO;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCHEMA_VERSION;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SCRIPT_TYPE;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_REPO_INFO;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_NAME;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_VERSION;
-
 
 /**
  * Helper class containing logic to process custom command execution requests .
@@ -116,7 +100,7 @@ public class AmbariCustomCommandExecutionHelper {
   @Inject
   private Clusters clusters;
   @Inject
-  private AmbariManagementController amc;
+  private AmbariManagementController managementController;
   @Inject
   private Gson gson;
   @Inject
@@ -126,6 +110,10 @@ public class AmbariCustomCommandExecutionHelper {
   @Inject
   private ConfigHelper configHelper;
 
+  protected static final String SERVICE_CHECK_COMMAND_NAME = "SERVICE_CHECK";
+  protected static final String DECOMMISSION_COMMAND_NAME = "DECOMMISSION";
+
+
   private Boolean isServiceCheckCommand(String command, String service) {
     List<String> actions = actionMetadata.getActions(service);
     if (actions == null || actions.size() == 0) {
@@ -139,114 +127,98 @@ public class AmbariCustomCommandExecutionHelper {
     return true;
   }
 
-  private Boolean isValidCustomCommand(ExecuteActionRequest actionRequest) throws AmbariException {
-    String clustername = actionRequest.getClusterName();
-    Cluster cluster = clusters.getCluster(clustername);
+  private Boolean isValidCustomCommand(String clusterName,
+      String serviceName, String componentName, String commandName)
+      throws AmbariException {
+
+    Cluster cluster = clusters.getCluster(clusterName);
     StackId stackId = cluster.getDesiredStackVersion();
-    String serviceName = actionRequest.getServiceName();
-    String componentName = actionRequest.getComponentName();
-    String commandName = actionRequest.getCommandName();
 
     if (componentName == null) {
       return false;
     }
     ComponentInfo componentInfo = ambariMetaInfo.getComponent(
-        stackId.getStackName(), stackId.getStackVersion(),
-        serviceName, componentName);
+      stackId.getStackName(), stackId.getStackVersion(),
+      serviceName, componentName);
 
-    if (!componentInfo.isCustomCommand(commandName) &&
-        !actionMetadata.isDefaultHostComponentCommand(commandName)) {
-      return false;
-    }
-    return true;
+    return !(!componentInfo.isCustomCommand(commandName) &&
+      !actionMetadata.isDefaultHostComponentCommand(commandName));
   }
 
-  public void validateCustomCommand(ExecuteActionRequest actionRequest) throws AmbariException {
-    if (actionRequest.getServiceName() == null
-        || actionRequest.getServiceName().isEmpty()
-        || actionRequest.getCommandName() == null
-        || actionRequest.getCommandName().isEmpty()) {
-      throw new AmbariException("Invalid request : " + "cluster="
-          + actionRequest.getClusterName() + ", service="
-          + actionRequest.getServiceName() + ", command="
-          + actionRequest.getCommandName());
-    }
-
-    LOG.info("Received a command execution request"
-        + ", clusterName=" + actionRequest.getClusterName()
-        + ", serviceName=" + actionRequest.getServiceName()
-        + ", request=" + actionRequest.toString());
+  private Boolean isValidCustomCommand(ActionExecutionContext
+      actionExecutionContext, RequestResourceFilter resourceFilter)
+      throws AmbariException {
+    String clusterName = actionExecutionContext.getClusterName();
+    String serviceName = resourceFilter.getServiceName();
+    String componentName = resourceFilter.getComponentName();
+    String commandName = actionExecutionContext.getActionName();
 
-    if (!isServiceCheckCommand(actionRequest.getCommandName(), actionRequest.getServiceName())
-        && !isValidCustomCommand(actionRequest)) {
-      throw new AmbariException(
-          "Unsupported action " + actionRequest.getCommandName() + " for Service: " + actionRequest.getServiceName()
-              + " and Component: " + actionRequest.getComponentName());
+    if (componentName == null) {
+      return false;
     }
+
+    return isValidCustomCommand(clusterName, serviceName, componentName, commandName);
   }
 
-  /**
-   * Other than Service_Check and Decommission all other commands are pass-through
-   *
-   * @param actionRequest   received request to execute a command
-   * @param stage           the initial stage for task creation
-   * @param hostLevelParams specific parameters for the hosts
-   * @throws AmbariException
-   */
-  public void addAction(ExecuteActionRequest actionRequest, Stage stage,
-                        Map<String, String> hostLevelParams)
-      throws AmbariException {
-    if (actionRequest.getCommandName().contains("SERVICE_CHECK")) {
-      findHostAndAddServiceCheckAction(actionRequest, stage, hostLevelParams);
-    } else if (actionRequest.getCommandName().equals("DECOMMISSION")) {
-      addDecommissionAction(actionRequest, stage, hostLevelParams);
-    } else if (isValidCustomCommand(actionRequest)) {
-      String commandDetail = getReadableCustomCommandDetail(actionRequest);
-      addCustomCommandAction(actionRequest, stage, hostLevelParams, null, commandDetail);
-    } else {
-      throw new AmbariException("Unsupported action " + actionRequest.getCommandName());
+  private Boolean isValidCustomCommand(ExecuteActionRequest actionRequest,
+      RequestResourceFilter resourceFilter) throws AmbariException {
+    String clusterName = actionRequest.getClusterName();
+    String serviceName = resourceFilter.getServiceName();
+    String componentName = resourceFilter.getComponentName();
+    String commandName = actionRequest.getCommandName();
+
+    if (componentName == null) {
+      return false;
     }
+
+    return isValidCustomCommand(clusterName, serviceName, componentName, commandName);
   }
 
-  private String getReadableCustomCommandDetail(ExecuteActionRequest actionRequest) {
-    StringBuffer sb = new StringBuffer();
-    sb.append(actionRequest.getCommandName());
-    if (actionRequest.getServiceName() != null && !actionRequest.getServiceName().equals("")) {
-      sb.append(" " + actionRequest.getServiceName());
+  private String getReadableCustomCommandDetail(ActionExecutionContext
+        actionRequest, RequestResourceFilter resourceFilter) {
+    StringBuilder sb = new StringBuilder();
+    sb.append(actionRequest.getActionName());
+    if (resourceFilter.getServiceName() != null
+        && !resourceFilter.getServiceName().equals("")) {
+      sb.append(" ");
+      sb.append(resourceFilter.getServiceName());
     }
-    if (actionRequest.getComponentName() != null && !actionRequest.getComponentName().equals("")) {
-      sb.append("/" + actionRequest.getComponentName());
+    if (resourceFilter.getComponentName() != null
+        && !resourceFilter.getComponentName().equals("")) {
+      sb.append("/");
+      sb.append(resourceFilter.getComponentName());
     }
     return sb.toString();
   }
 
-  private void addCustomCommandAction(ExecuteActionRequest actionRequest,
+  private void addCustomCommandAction(ActionExecutionContext actionExecutionContext,
+                                      RequestResourceFilter resourceFilter,
                                       Stage stage, Map<String, String> hostLevelParams,
                                       Map<String, String> additionalCommandParams,
                                       String commandDetail)
-      throws AmbariException {
+                                      throws AmbariException {
 
-    if (actionRequest.getHosts().isEmpty()) {
+    List<String> hosts = resourceFilter.getHostNames();
+    if (hosts.isEmpty()) {
       throw new AmbariException("Invalid request : No hosts specified.");
     }
 
-    String serviceName = actionRequest.getServiceName();
-    String componentName = actionRequest.getComponentName();
-    String commandName = actionRequest.getCommandName();
+    String serviceName = resourceFilter.getServiceName();
+    String componentName = resourceFilter.getComponentName();
+    String commandName = actionExecutionContext.getActionName();
 
     String clusterName = stage.getClusterName();
     Cluster cluster = clusters.getCluster(clusterName);
     StackId stackId = cluster.getDesiredStackVersion();
-    AmbariMetaInfo ambariMetaInfo = amc.getAmbariMetaInfo();
-    ServiceInfo serviceInfo =
-        ambariMetaInfo.getServiceInfo(stackId.getStackName(),
-            stackId.getStackVersion(), serviceName);
-    StackInfo stackInfo = ambariMetaInfo.getStackInfo(stackId.getStackName(),
-        stackId.getStackVersion());
+    AmbariMetaInfo ambariMetaInfo = managementController.getAmbariMetaInfo();
+    ServiceInfo serviceInfo = ambariMetaInfo.getServiceInfo
+      (stackId.getStackName(), stackId.getStackVersion(), serviceName);
+    StackInfo stackInfo = ambariMetaInfo.getStackInfo
+      (stackId.getStackName(), stackId.getStackVersion());
 
     long nowTimestamp = System.currentTimeMillis();
 
-    for (String hostName : actionRequest.getHosts()) {
+    for (String hostName : hosts) {
 
       Host host = clusters.getHost(hostName);
 
@@ -258,12 +230,12 @@ public class AmbariCustomCommandExecutionHelper {
       Map<String, Map<String, String>> configurations =
           new TreeMap<String, Map<String, String>>();
       Map<String, Map<String, String>> configTags =
-          amc.findConfigurationTagsWithOverrides(cluster, hostName);
+          managementController.findConfigurationTagsWithOverrides(cluster, hostName);
 
       HostRoleCommand cmd = stage.getHostRoleCommand(hostName, componentName);
       if (cmd != null) {
         cmd.setCommandDetail(commandDetail);
-        cmd.setCustomCommandName(actionRequest.getCommandName());
+        cmd.setCustomCommandName(commandName);
       }
 
       ExecutionCommand execCmd = stage.getExecutionCommandWrapper(hostName,
@@ -277,7 +249,8 @@ public class AmbariCustomCommandExecutionHelper {
 
       hostLevelParams.put(CUSTOM_COMMAND, commandName);
       // Set parameters required for re-installing clients on restart
-      hostLevelParams.put(REPO_INFO, getRepoInfo(cluster, host));
+      hostLevelParams.put(REPO_INFO, getRepoInfo
+        (cluster, host));
       execCmd.setHostLevelParams(hostLevelParams);
 
       Map<String, String> commandParams = new TreeMap<String, String>();
@@ -329,37 +302,50 @@ public class AmbariCustomCommandExecutionHelper {
     }
   }
 
-  private void findHostAndAddServiceCheckAction(ExecuteActionRequest actionRequest, Stage stage,
-                                                Map<String, String> hostLevelParams)
+  private void findHostAndAddServiceCheckAction(ActionExecutionContext
+      actionExecutionContext, RequestResourceFilter resourceFilter,
+      Stage stage, Map<String, String> hostLevelParams)
       throws AmbariException {
-    String clusterName = actionRequest.getClusterName();
-    String componentName = actionMetadata.getClient(actionRequest
-        .getServiceName());
-    String serviceName = actionRequest.getServiceName();
-    String smokeTestRole = actionRequest.getCommandName();
+
+    String clusterName = actionExecutionContext.getClusterName();
+    String componentName = actionMetadata.getClient(resourceFilter.getServiceName());
+    String serviceName = resourceFilter.getServiceName();
+    String smokeTestRole = actionExecutionContext.getActionName();
     long nowTimestamp = System.currentTimeMillis();
-    Map<String, String> actionParameters = actionRequest.getParameters();
+    Map<String, String> actionParameters = actionExecutionContext.getParameters();
 
     String hostName;
     if (componentName != null) {
-      Map<String, ServiceComponentHost> components = clusters
-          .getCluster(clusterName).getService(actionRequest.getServiceName())
+      Map<String, ServiceComponentHost> components =
+        clusters.getCluster(clusterName).getService(serviceName)
           .getServiceComponent(componentName).getServiceComponentHosts();
 
       if (components.isEmpty()) {
         throw new AmbariException("Hosts not found, component="
-            + componentName + ", service=" + actionRequest.getServiceName()
-            + ", cluster=" + clusterName);
+            + componentName + ", service = " + serviceName
+            + ", cluster = " + clusterName);
+      }
+
+      List<String> candidateHosts = resourceFilter.getHostNames();
+      if (candidateHosts != null && !candidateHosts.isEmpty()) {
+        hostName = managementController.getHealthyHost
+          (new HashSet<String>(candidateHosts));
+
+        if (hostName == null) {
+          LOG.info("Unable to find a healthy host amongst the provided set of " +
+            "hosts. " + candidateHosts);
+        }
+      } else {
+        hostName = managementController.getHealthyHost(components.keySet());
       }
-      hostName = amc.getHealthyHost(components.keySet());
+
     } else {
       Map<String, ServiceComponent> components = clusters
-          .getCluster(clusterName).getService(actionRequest.getServiceName())
-          .getServiceComponents();
+        .getCluster(clusterName).getService(serviceName).getServiceComponents();
 
       if (components.isEmpty()) {
-        throw new AmbariException("Components not found, service="
-            + actionRequest.getServiceName() + ", cluster=" + clusterName);
+        throw new AmbariException("Components not found, service = "
+            + serviceName + ", cluster = " + clusterName);
       }
 
       ServiceComponent serviceComponent = components.values().iterator()
@@ -367,12 +353,11 @@ public class AmbariCustomCommandExecutionHelper {
 
       if (serviceComponent.getServiceComponentHosts().isEmpty()) {
         throw new AmbariException("Hosts not found, component="
-            + serviceComponent.getName() + ", service="
-            + actionRequest.getServiceName() + ", cluster=" + clusterName);
+            + serviceComponent.getName() + ", service = "
+            + serviceName + ", cluster = " + clusterName);
       }
 
-      hostName = serviceComponent.getServiceComponentHosts().keySet()
-          .iterator().next();
+      hostName = serviceComponent.getServiceComponentHosts().keySet().iterator().next();
     }
 
     addServiceCheckAction(stage, hostName, smokeTestRole, nowTimestamp,
@@ -392,17 +377,17 @@ public class AmbariCustomCommandExecutionHelper {
                                     String componentName,
                                     Map<String, String> actionParameters,
                                     Map<String, String> hostLevelParams)
-      throws AmbariException {
+                                    throws AmbariException {
 
     String clusterName = stage.getClusterName();
     Cluster cluster = clusters.getCluster(clusterName);
     StackId stackId = cluster.getDesiredStackVersion();
-    AmbariMetaInfo ambariMetaInfo = amc.getAmbariMetaInfo();
+    AmbariMetaInfo ambariMetaInfo = managementController.getAmbariMetaInfo();
     ServiceInfo serviceInfo =
         ambariMetaInfo.getServiceInfo(stackId.getStackName(),
             stackId.getStackVersion(), serviceName);
     StackInfo stackInfo = ambariMetaInfo.getStackInfo(stackId.getStackName(),
-        stackId.getStackVersion());
+      stackId.getStackVersion());
 
 
     stage.addHostRoleExecutionCommand(hostname,
@@ -419,7 +404,7 @@ public class AmbariCustomCommandExecutionHelper {
     Map<String, Map<String, String>> configurations =
         new TreeMap<String, Map<String, String>>();
     Map<String, Map<String, String>> configTags =
-        amc.findConfigurationTagsWithOverrides(cluster, hostname);
+        managementController.findConfigurationTagsWithOverrides(cluster, hostname);
 
     ExecutionCommand execCmd = stage.getExecutionCommandWrapper(hostname,
         smokeTestRole).getExecutionCommand();
@@ -489,46 +474,53 @@ public class AmbariCustomCommandExecutionHelper {
    * Processes decommission command. Modifies the host components as needed and then
    * calls into the implementation of a custom command
    */
-  private void addDecommissionAction(ExecuteActionRequest request, Stage stage,
-                                     Map<String, String> hostLevelParams)
-      throws AmbariException {
+  private void addDecommissionAction(ActionExecutionContext actionExecutionContext,
+                                     RequestResourceFilter resourceFilter,
+                                     Stage stage, Map<String, String> hostLevelParams)
+                                     throws AmbariException {
 
-    String clusterName = request.getClusterName();
+    String clusterName = actionExecutionContext.getClusterName();
     Cluster cluster = clusters.getCluster(clusterName);
-    String serviceName = request.getServiceName();
+    String serviceName = resourceFilter.getServiceName();
+    String componentName = resourceFilter.getComponentName();
+    List<String> hosts = resourceFilter.getHostNames();
 
-    if (request.getHosts() != null && request.getHosts().size() != 0) {
-      throw new AmbariException("Decommission command cannot be issued with target host(s) specified.");
+    if (hosts != null && !hosts.isEmpty()) {
+      throw new AmbariException("Decommission command cannot be issued with " +
+        "target host(s) specified.");
     }
 
     //Get all hosts to be added and removed
-    Set<String> excludedHosts = getHostList(request.getParameters(), DECOM_EXCLUDED_HOSTS);
-    Set<String> includedHosts = getHostList(request.getParameters(), DECOM_INCLUDED_HOSTS);
-    String slaveCompType = request.getParameters().get(DECOM_SLAVE_COMPONENT);
+    Set<String> excludedHosts = getHostList(actionExecutionContext.getParameters(),
+                                            DECOM_EXCLUDED_HOSTS);
+    Set<String> includedHosts = getHostList(actionExecutionContext.getParameters(),
+                                            DECOM_INCLUDED_HOSTS);
+    String slaveCompType = actionExecutionContext.getParameters().get(DECOM_SLAVE_COMPONENT);
 
     Set<String> cloneSet = new HashSet<String>(excludedHosts);
     cloneSet.retainAll(includedHosts);
     if (cloneSet.size() > 0) {
-      throw new AmbariException("Same host cannot be specified for inclusion as well as exclusion. Hosts: "
-          + cloneSet.toString());
+      throw new AmbariException("Same host cannot be specified for inclusion " +
+        "as well as exclusion. Hosts: " + cloneSet.toString());
     }
 
     Service service = cluster.getService(serviceName);
     if (service == null) {
-      throw new AmbariException("Specified service " + serviceName + " is not a valid/deployed service.");
+      throw new AmbariException("Specified service " + serviceName +
+        " is not a valid/deployed service.");
     }
 
-    String masterCompType = request.getComponentName();
+    String masterCompType = componentName;
     Map<String, ServiceComponent> svcComponents = service.getServiceComponents();
     if (!svcComponents.containsKey(masterCompType)) {
-      throw new AmbariException("Specified component " + masterCompType + " does not belong to service "
-          + serviceName + ".");
+      throw new AmbariException("Specified component " + masterCompType +
+        " does not belong to service " + serviceName + ".");
     }
 
     ServiceComponent masterComponent = svcComponents.get(masterCompType);
     if (!masterComponent.isMasterComponent()) {
-      throw new AmbariException("Specified component " + masterCompType + " is not a MASTER for service "
-          + serviceName + ".");
+      throw new AmbariException("Specified component " + masterCompType +
+        " is not a MASTER for service " + serviceName + ".");
     }
 
     if (!masterToSlaveMappingForDecom.containsKey(masterCompType)) {
@@ -542,7 +534,7 @@ public class AmbariCustomCommandExecutionHelper {
       throw new AmbariException("Component " + slaveCompType + " is not supported for decommissioning.");
     }
 
-    String isDrainOnlyRequest = request.getParameters().get(HBASE_MARK_DRAINING_ONLY);
+    String isDrainOnlyRequest = actionExecutionContext.getParameters().get(HBASE_MARK_DRAINING_ONLY);
     if (isDrainOnlyRequest != null && !slaveCompType.equals(Role.HBASE_REGIONSERVER.name())) {
       throw new AmbariException(HBASE_MARK_DRAINING_ONLY + " is not a valid parameter for " + masterCompType);
     }
@@ -557,7 +549,7 @@ public class AmbariCustomCommandExecutionHelper {
       }
     }
 
-    String alignMtnStateStr = request.getParameters().get(ALIGN_MAINTENANCE_STATE);
+    String alignMtnStateStr = actionExecutionContext.getParameters().get(ALIGN_MAINTENANCE_STATE);
     boolean alignMtnState = "true".equals(alignMtnStateStr);
     // Set/reset decommissioned flag on all components
     List<String> listOfExcludedHosts = new ArrayList<String>();
@@ -597,12 +589,18 @@ public class AmbariCustomCommandExecutionHelper {
       }
     }
 
-    StringBuilder commandDetail = getReadableDecommissionCommandDetail(request, includedHosts, listOfExcludedHosts);
+    StringBuilder commandDetail = getReadableDecommissionCommandDetail
+      (actionExecutionContext, includedHosts, listOfExcludedHosts);
 
     for (String hostName : masterSchs.keySet()) {
-      ExecuteActionRequest commandRequest = new ExecuteActionRequest(
-          request.getClusterName(), request.getCommandName(), request.getActionName(), request.getServiceName(),
-          masterComponent.getName(), Collections.singletonList(hostName), null);
+      RequestResourceFilter commandFilter = new RequestResourceFilter(serviceName,
+        masterComponent.getName(), Collections.singletonList(hostName));
+      List<RequestResourceFilter> resourceFilters = new ArrayList<RequestResourceFilter>();
+      resourceFilters.add(commandFilter);
+
+      ActionExecutionContext commandContext = new ActionExecutionContext(
+        clusterName, actionExecutionContext.getActionName(), resourceFilters
+      );
 
       String clusterHostInfoJson = StageUtils.getGson().toJson(
           StageUtils.getClusterHostInfo(clusters.getHostsForCluster(cluster.getClusterName()), cluster));
@@ -622,16 +620,17 @@ public class AmbariCustomCommandExecutionHelper {
 
       if (!serviceName.equals(Service.Type.HBASE.name()) || hostName.equals(primaryCandidate)) {
         commandParams.put(UPDATE_EXCLUDE_FILE_ONLY, "false");
-        addCustomCommandAction(commandRequest, stage, hostLevelParams, commandParams, commandDetail.toString());
+        addCustomCommandAction(commandContext, commandFilter, stage,
+          hostLevelParams, commandParams, commandDetail.toString());
       }
     }
   }
 
-  private StringBuilder getReadableDecommissionCommandDetail(ExecuteActionRequest request,
-                                                             Set<String> includedHosts,
-                                                             List<String> listOfExcludedHosts) {
+  private StringBuilder getReadableDecommissionCommandDetail(
+      ActionExecutionContext actionExecutionContext, Set<String> includedHosts,
+      List<String> listOfExcludedHosts) {
     StringBuilder commandDetail = new StringBuilder();
-    commandDetail.append(request.getCommandName());
+    commandDetail.append(actionExecutionContext.getActionName());
     if (listOfExcludedHosts.size() > 0) {
       commandDetail.append(", Excluded: ").append(StringUtils.join(listOfExcludedHosts, ','));
     }
@@ -642,156 +641,83 @@ public class AmbariCustomCommandExecutionHelper {
   }
 
   /**
-   * Creates and populates an EXECUTION_COMMAND for host
+   * Validate custom command and throw exception is invalid request.
+   * @param actionRequest
+   * @throws AmbariException
    */
-  public void createHostAction(Cluster cluster,
-                               Stage stage, ServiceComponentHost scHost,
-                               Map<String, Map<String, String>> configurations,
-                               Map<String, Map<String, String>> configTags,
-                               RoleCommand roleCommand,
-                               Map<String, String> commandParams,
-                               ServiceComponentHostEvent event)
-      throws AmbariException {
-
-    stage.addHostRoleExecutionCommand(scHost.getHostName(), Role.valueOf(scHost
-        .getServiceComponentName()), roleCommand,
-        event, scHost.getClusterName(),
-        scHost.getServiceName());
-    String serviceName = scHost.getServiceName();
-    String componentName = event.getServiceComponentName();
-    String hostname = scHost.getHostName();
-    String osType = clusters.getHost(hostname).getOsType();
-    StackId stackId = cluster.getDesiredStackVersion();
-    ServiceInfo serviceInfo = ambariMetaInfo.getServiceInfo(stackId.getStackName(),
-        stackId.getStackVersion(), serviceName);
-    ComponentInfo componentInfo = ambariMetaInfo.getComponent(
-        stackId.getStackName(), stackId.getStackVersion(),
-        serviceName, componentName);
-    StackInfo stackInfo = ambariMetaInfo.getStackInfo(stackId.getStackName(),
-        stackId.getStackVersion());
-
-    ExecutionCommand execCmd = stage.getExecutionCommandWrapper(scHost.getHostName(),
-        scHost.getServiceComponentName()).getExecutionCommand();
+  public void validateAction(ExecuteActionRequest actionRequest) throws AmbariException {
 
-    Host host = clusters.getHost(scHost.getHostName());
+    List<RequestResourceFilter> resourceFilters = actionRequest.getResourceFilters();
 
-    // Hack - Remove passwords from configs
-    if (event.getServiceComponentName().equals(Role.HIVE_CLIENT.toString())) {
-      configHelper.applyCustomConfig(configurations, Configuration.HIVE_CONFIG_TAG,
-          Configuration.HIVE_METASTORE_PASSWORD_PROPERTY, "", true);
+    if (resourceFilters == null || resourceFilters.isEmpty()) {
+      throw new AmbariException("Command execution cannot proceed without a " +
+        "resource filter.");
     }
 
-    String jobtrackerHost = amc.getJobTrackerHost(cluster);
-    if (!scHost.getHostName().equals(jobtrackerHost)) {
-      if (configTags.get(Configuration.GLOBAL_CONFIG_TAG) != null) {
-        configHelper.applyCustomConfig(
-            configurations, Configuration.GLOBAL_CONFIG_TAG,
-            Configuration.RCA_ENABLED_PROPERTY, "false", false);
+    for (RequestResourceFilter resourceFilter : resourceFilters) {
+      if (resourceFilter.getServiceName() == null
+        || resourceFilter.getServiceName().isEmpty()
+        || actionRequest.getCommandName() == null
+        || actionRequest.getCommandName().isEmpty()) {
+        throw new AmbariException("Invalid resource filter : " + "cluster = "
+          + actionRequest.getClusterName() + ", service = "
+          + resourceFilter.getServiceName() + ", command = "
+          + actionRequest.getCommandName());
       }
-    }
 
-    execCmd.setConfigurations(configurations);
-    execCmd.setConfigurationTags(configTags);
-    if (commandParams == null) { // if not defined
-      commandParams = new TreeMap<String, String>();
-    }
-    commandParams.put(SCHEMA_VERSION, serviceInfo.getSchemaVersion());
-
-
-    // Get command script info for custom command/custom action
-    /*
-     * TODO: Custom actions are not supported yet, that's why we just pass
-     * component main commandScript to agent. This script is only used for
-     * default commads like INSTALL/STOP/START/CONFIGURE
-     */
-    String commandTimeout = configs.getDefaultAgentTaskTimeout();
-    CommandScriptDefinition script = componentInfo.getCommandScript();
-    if (serviceInfo.getSchemaVersion().equals(AmbariMetaInfo.SCHEMA_VERSION_2)) {
-      if (script != null) {
-        commandParams.put(SCRIPT, script.getScript());
-        commandParams.put(SCRIPT_TYPE, script.getScriptType().toString());
-        if (script.getTimeout() > 0) {
-          commandTimeout = String.valueOf(script.getTimeout());
-        }
-      } else {
-        String message = String.format("Component %s of service %s has no " +
-            "command script defined", componentName, serviceName);
-        throw new AmbariException(message);
+      if (!isServiceCheckCommand(actionRequest.getCommandName(), resourceFilter.getServiceName())
+        && !isValidCustomCommand(actionRequest, resourceFilter)) {
+        throw new AmbariException(
+          "Unsupported action " + actionRequest.getCommandName() +
+            " for Service: " + resourceFilter.getServiceName()
+            + " and Component: " + resourceFilter.getComponentName());
       }
     }
-    commandParams.put(COMMAND_TIMEOUT, commandTimeout);
-    commandParams.put(SERVICE_PACKAGE_FOLDER,
-        serviceInfo.getServicePackageFolder());
-    commandParams.put(HOOKS_FOLDER, stackInfo.getStackHooksFolder());
-
-    execCmd.setCommandParams(commandParams);
+  }
 
-    String repoInfo = getRepoInfo(cluster, host);
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Sending repo information to agent"
-          + ", hostname=" + scHost.getHostName()
-          + ", clusterName=" + cluster.getClusterName()
-          + ", stackInfo=" + stackId.getStackId()
-          + ", repoInfo=" + repoInfo);
-    }
-
-    Map<String, String> hostParams = new TreeMap<String, String>();
-    hostParams.put(REPO_INFO, repoInfo);
-    hostParams.put(JDK_LOCATION, amc.getJdkResourceUrl());
-    hostParams.put(JAVA_HOME, amc.getJavaHome());
-    hostParams.put(JDK_NAME, amc.getJDKName());
-    hostParams.put(JCE_NAME, amc.getJCEName());
-    hostParams.put(STACK_NAME, stackId.getStackName());
-    hostParams.put(STACK_VERSION, stackId.getStackVersion());
-    hostParams.put(DB_NAME, amc.getServerDB());
-    hostParams.put(MYSQL_JDBC_URL, amc.getMysqljdbcUrl());
-    hostParams.put(ORACLE_JDBC_URL, amc.getOjdbcUrl());
-    hostParams.putAll(amc.getRcaParameters());
-
-    // Write down os specific info for the service
-    ServiceOsSpecific anyOs = null;
-    if (serviceInfo.getOsSpecifics().containsKey(AmbariMetaInfo.ANY_OS)) {
-      anyOs = serviceInfo.getOsSpecifics().get(AmbariMetaInfo.ANY_OS);
-    }
-    ServiceOsSpecific hostOs = null;
-    if (serviceInfo.getOsSpecifics().containsKey(osType)) {
-      hostOs = serviceInfo.getOsSpecifics().get(osType);
-      // Choose repo that is relevant for host
-      ServiceOsSpecific.Repo serviceRepo = hostOs.getRepo();
-      if (serviceRepo != null) {
-        String serviceRepoInfo = gson.toJson(serviceRepo);
-        hostParams.put(SERVICE_REPO_INFO, serviceRepoInfo);
+  /**
+   * Other than Service_Check and Decommission all other commands are pass-through
+   * @param actionExecutionContext received request to execute a command
+   * @param stage the initial stage for task creation
+   * @param hostLevelParams specific parameters for the hosts
+   * @throws AmbariException
+   */
+  public void addExecutionCommandsToStage(ActionExecutionContext actionExecutionContext,
+                                          Stage stage, Map<String, String> hostLevelParams)
+                                          throws AmbariException {
+
+    List<RequestResourceFilter> resourceFilters = actionExecutionContext.getResourceFilters();
+
+    for (RequestResourceFilter resourceFilter : resourceFilters) {
+      LOG.debug("Received a command execution request"
+        + ", clusterName=" + actionExecutionContext.getClusterName()
+        + ", serviceName=" + resourceFilter.getServiceName()
+        + ", request=" + actionExecutionContext.toString());
+
+      if (actionExecutionContext.getActionName().contains(SERVICE_CHECK_COMMAND_NAME)) {
+        findHostAndAddServiceCheckAction(actionExecutionContext,
+          resourceFilter, stage, hostLevelParams);
+      } else if (actionExecutionContext.getActionName().equals(DECOMMISSION_COMMAND_NAME)) {
+        addDecommissionAction(actionExecutionContext, resourceFilter, stage, hostLevelParams);
+      } else if (isValidCustomCommand(actionExecutionContext, resourceFilter)) {
+        String commandDetail = getReadableCustomCommandDetail(actionExecutionContext, resourceFilter);
+        addCustomCommandAction(actionExecutionContext, resourceFilter, stage,
+          hostLevelParams, null, commandDetail);
+      } else {
+        throw new AmbariException("Unsupported action " +
+          actionExecutionContext.getActionName());
       }
     }
-    // Build package list that is relevant for host
-    List<ServiceOsSpecific.Package> packages =
-        new ArrayList<ServiceOsSpecific.Package>();
-    if (anyOs != null) {
-      packages.addAll(anyOs.getPackages());
-    }
-
-    if (hostOs != null) {
-      packages.addAll(hostOs.getPackages());
-    }
-    String packageList = gson.toJson(packages);
-    hostParams.put(PACKAGE_LIST, packageList);
-
-    if (configs.getServerDBName().equalsIgnoreCase(Configuration
-        .ORACLE_DB_NAME)) {
-      hostParams.put(DB_DRIVER_FILENAME, configs.getOjdbcJarName());
-    } else if (configs.getServerDBName().equalsIgnoreCase(Configuration
-        .MYSQL_DB_NAME)) {
-      hostParams.put(DB_DRIVER_FILENAME, configs.getMySQLJarName());
-    }
-    execCmd.setHostLevelParams(hostParams);
-
-    Map<String, String> roleParams = new TreeMap<String, String>();
-    execCmd.setRoleParams(roleParams);
-    
-    execCmd.setPassiveInfo(MaintenanceStateHelper.getMaintenanceHostCompoments(clusters, cluster));
   }
 
-  private String getRepoInfo(Cluster cluster, Host host) throws AmbariException {
+  /**
+   * Get repository info given a cluster and host.
+   * @param cluster
+   * @param host
+   * @return
+   * @throws AmbariException
+   */
+  public String getRepoInfo(Cluster cluster, Host host) throws AmbariException {
     StackId stackId = cluster.getDesiredStackVersion();
 
     Map<String, List<RepositoryInfo>> repos = ambariMetaInfo.getRepository(