You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by dm...@apache.org on 2014/07/10 16:57:30 UTC

[2/2] git commit: AMBARI-6423. Reimplementation of Maintenance mode support (dlysnichenko)

AMBARI-6423. Reimplementation of Maintenance mode support (dlysnichenko)


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

Branch: refs/heads/trunk
Commit: 30a41aca30242dc6845b3315b1d26469164d2e68
Parents: 4b3ab24
Author: Lisnichenko Dmitro <dl...@hortonworks.com>
Authored: Thu Jul 10 17:55:59 2014 +0300
Committer: Lisnichenko Dmitro <dl...@hortonworks.com>
Committed: Thu Jul 10 17:55:59 2014 +0300

----------------------------------------------------------------------
 .../actionmanager/ActionDBAccessorImpl.java     |   5 +-
 .../ambari/server/agent/HeartbeatMonitor.java   |   2 -
 .../controller/AmbariActionExecutionHelper.java |  58 ++--
 .../AmbariCustomCommandExecutionHelper.java     | 118 +++++---
 .../controller/AmbariManagementController.java  |   1 +
 .../AmbariManagementControllerImpl.java         | 105 ++++++-
 .../controller/MaintenanceStateHelper.java      | 172 ++++++++++-
 .../internal/ComponentResourceProvider.java     | 138 +++++----
 .../internal/RequestOperationLevel.java         |  39 +++
 .../internal/RequestResourceProvider.java       |  36 +--
 .../internal/ServiceResourceProvider.java       |  48 ++--
 .../resources/BaseResourceDefinitionTest.java   |  14 +-
 .../AmbariManagementControllerTest.java         |  85 ++++--
 .../controller/MaintenanceStateHelperTest.java  | 282 ++++++++++++++++---
 .../AbstractControllerResourceProviderTest.java |   9 +-
 .../internal/AbstractResourceProviderTest.java  |  16 +-
 .../internal/ComponentResourceProviderTest.java |  31 +-
 .../internal/JMXHostProviderTest.java           |  11 +-
 .../internal/RequestOperationLevelTest.java     |  61 +++-
 .../internal/RequestResourceProviderTest.java   |  32 +--
 .../internal/ServiceResourceProviderTest.java   |  71 ++++-
 21 files changed, 999 insertions(+), 335 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
index 375794d..a6c59a7 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/actionmanager/ActionDBAccessorImpl.java
@@ -235,8 +235,9 @@ public class ActionDBAccessorImpl implements ActionDBAccessor {
 
         HostEntity hostEntity = hostDAO.findByName(hostRoleCommandEntity.getHostName());
         if (hostEntity == null) {
-          LOG.error("Host {} doesn't exists in database" + hostRoleCommandEntity.getHostName());
-          throw new RuntimeException("Host '" + hostRoleCommandEntity.getHostName() + "' doesn't exists in database");
+          String msg = String.format("Host %s doesn't exist in database", hostRoleCommandEntity.getHostName());
+          LOG.error(msg);
+          throw new RuntimeException(msg);
         }
         hostRoleCommandEntity.setHost(hostEntity);
         hostRoleCommandDAO.create(hostRoleCommandEntity);

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
index 959ee5a..cdf178c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartbeatMonitor.java
@@ -78,7 +78,6 @@ public class HeartbeatMonitor implements Runnable {
   private final AmbariMetaInfo ambariMetaInfo;
   private final AmbariManagementController ambariManagementController;
   private final Configuration configuration;
-  private final MaintenanceStateHelper maintenanceStateHelper;
 
   public HeartbeatMonitor(Clusters clusters, ActionQueue aq, ActionManager am,
                           int threadWakeupInterval, Injector injector) {
@@ -91,7 +90,6 @@ public class HeartbeatMonitor implements Runnable {
     this.ambariManagementController = injector.getInstance(
             AmbariManagementController.class);
     this.configuration = injector.getInstance(Configuration.class);
-    this.maintenanceStateHelper = injector.getInstance(MaintenanceStateHelper.class);
   }
 
   public void shutdown() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/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 c66d2e2..8ef40f6 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
@@ -209,30 +209,33 @@ public class AmbariActionExecutionHelper {
    * @param hostLevelParams host level params to send with the command
    * @throws AmbariException
    */
-  public void addExecutionCommandsToStage(ActionExecutionContext
-    actionContext, Stage stage, Map<String, String> hostLevelParams)
+  public void addExecutionCommandsToStage(
+          final ActionExecutionContext actionContext,
+          Stage stage, Map<String, String> hostLevelParams)
       throws AmbariException {
 
     String actionName = actionContext.getActionName();
     String clusterName = actionContext.getClusterName();
-    Cluster cluster = null;
+    final Cluster cluster;
     if (null != clusterName)
       cluster = clusters.getCluster(clusterName);
-    
-    ComponentInfo componentInfo = null;
+    else 
+      cluster = null;
 
+    ComponentInfo componentInfo = null;
     List<RequestResourceFilter> resourceFilters = actionContext.getResourceFilters();
-
-    RequestResourceFilter resourceFilter = new RequestResourceFilter();
+    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<String>();
 
-    String serviceName = actionContext.getExpectedServiceName();
-    String componentName = actionContext.getExpectedComponentName();
+    final String serviceName = actionContext.getExpectedServiceName();
+    final String componentName = actionContext.getExpectedComponentName();
     
     if (null != cluster) {
       StackId stackId = cluster.getCurrentStackVersion();
@@ -256,15 +259,32 @@ public class AmbariActionExecutionHelper {
         // All hosts are valid target host
         candidateHosts.addAll(clusters.getHostsForCluster(cluster.getClusterName()).keySet());
       }
+
+      // 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);
+                }
+              }
+      );
+      LOG.debug("Ignoring action for hosts due to maintenance state." +
+            "Ignored hosts =" + ignoredHosts + ", component="
+            + componentName + ", service=" + serviceName
+            + ", cluster=" + cluster.getClusterName() + ", " +
+            "actionName=" + 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() + ", ")
-//        + ", cluster=" + cluster.getClusterName() + ", "
-        + "actionName=" + actionContext.getActionName());
+              + componentName + ", service=" + serviceName
+              + ((null == cluster) ? "" : ", cluster=" + cluster.getClusterName() + ", ")
+              + "actionName=" + actionContext.getActionName());
     }
 
     // Compare specified hosts to available hosts
@@ -302,11 +322,6 @@ public class AmbariActionExecutionHelper {
       }
     }
 
-    Set<Map<String, String>> maintenanceSCHs = new HashSet<Map<String, String>>();
-        
-    if (null != cluster)
-      maintenanceSCHs = maintenanceStateHelper.getMaintenanceHostComponents(clusters, cluster);
-
     //create tasks for each host
     for (String hostName : targetHosts) {
       stage.addHostRoleExecutionCommand(hostName,
@@ -359,6 +374,13 @@ public class AmbariActionExecutionHelper {
           StageUtils.getClusterHostInfo(clusters.getHostsForCluster(clusterName), cluster));
 
       // cluster passive map
+      Set<Map<String, String>> maintenanceSCHs;
+      if (null != cluster) {
+        maintenanceSCHs = maintenanceStateHelper.
+                getMaintenanceHostComponents(clusters, cluster);
+      } else {
+        maintenanceSCHs = new HashSet<Map<String, String>>();
+      }
       execCmd.setPassiveInfo(maintenanceSCHs);
     }
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/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 403d6a2..1e07919 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
@@ -45,7 +45,6 @@ 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.RequestOperationLevel;
 import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.state.Cluster;
@@ -200,24 +199,45 @@ public class AmbariCustomCommandExecutionHelper {
     return sb.toString();
   }
 
-  private void addCustomCommandAction(ActionExecutionContext actionExecutionContext,
-                                      RequestResourceFilter resourceFilter,
+  private void addCustomCommandAction(final ActionExecutionContext actionExecutionContext,
+                                      final RequestResourceFilter resourceFilter,
                                       Stage stage, Map<String, String> hostLevelParams,
                                       Map<String, String> additionalCommandParams,
                                       String commandDetail)
                                       throws AmbariException {
+    final String serviceName = resourceFilter.getServiceName();
+    final String componentName = resourceFilter.getComponentName();
+    final String commandName = actionExecutionContext.getActionName();
 
-    List<String> hosts = resourceFilter.getHostNames();
-    if (hosts.isEmpty()) {
-      throw new AmbariException("Invalid request : No hosts specified.");
+    String clusterName = stage.getClusterName();
+    final Cluster cluster = clusters.getCluster(clusterName);
+
+    Set<String> candidateHosts = new HashSet<String>(resourceFilter.getHostNames());
+    // 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, actionExecutionContext.getOperationLevel(),
+                        resourceFilter, serviceName, componentName, hostname);
+              }
+            }
+    );
+    if (! ignoredHosts.isEmpty()) {
+      String message = String.format("Some hosts (%s) have been ignored " +
+                      "because components on them are in Maintenance state.",
+              ignoredHosts);
+      LOG.debug(message);
+    }
+
+    if (candidateHosts.isEmpty()) {
+      String message = "Invalid request : No hosts specified.";
+      throw new AmbariException(message);
     }
 
-    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 = managementController.getAmbariMetaInfo();
     ServiceInfo serviceInfo = ambariMetaInfo.getServiceInfo
@@ -227,7 +247,7 @@ public class AmbariCustomCommandExecutionHelper {
 
     long nowTimestamp = System.currentTimeMillis();
 
-    for (String hostName : hosts) {
+    for (String hostName : candidateHosts) {
 
       Host host = clusters.getHost(hostName);
 
@@ -318,62 +338,72 @@ public class AmbariCustomCommandExecutionHelper {
     }
   }
 
-  private void findHostAndAddServiceCheckAction(ActionExecutionContext
-      actionExecutionContext, RequestResourceFilter resourceFilter,
-      Stage stage, Map<String, String> hostLevelParams)
-      throws AmbariException {
+  private void findHostAndAddServiceCheckAction(
+          final ActionExecutionContext actionExecutionContext,
+          final RequestResourceFilter resourceFilter,
+          Stage stage, Map<String, String> hostLevelParams)
+          throws AmbariException {
 
     String clusterName = actionExecutionContext.getClusterName();
-    String componentName = actionMetadata.getClient(resourceFilter.getServiceName());
-    String serviceName = resourceFilter.getServiceName();
+    final Cluster cluster = clusters.getCluster(clusterName);
+    final String componentName = actionMetadata.getClient(resourceFilter.getServiceName());
+    final String serviceName = resourceFilter.getServiceName();
     String smokeTestRole = actionExecutionContext.getActionName();
     long nowTimestamp = System.currentTimeMillis();
     Map<String, String> actionParameters = actionExecutionContext.getParameters();
-
-    String hostName;
+    final Set<String> candidateHosts;
     if (componentName != null) {
       Map<String, ServiceComponentHost> components =
-        clusters.getCluster(clusterName).getService(serviceName)
+        cluster.getService(serviceName)
           .getServiceComponent(componentName).getServiceComponentHosts();
-
       if (components.isEmpty()) {
         throw new AmbariException("Hosts not found, component="
             + 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);
-        }
+      List<String> candidateHostsList = resourceFilter.getHostNames();
+      if (candidateHostsList != null && !candidateHostsList.isEmpty()) {
+        candidateHosts = new HashSet<String>(candidateHostsList);
       } else {
-        hostName = managementController.getHealthyHost(components.keySet());
+        candidateHosts = components.keySet();
       }
-
-    } else {
-      Map<String, ServiceComponent> components = clusters
-        .getCluster(clusterName).getService(serviceName).getServiceComponents();
-
+    } else { // TODO: this code branch looks unreliable(taking random component)
+      Map<String, ServiceComponent> components =
+              cluster.getService(serviceName).getServiceComponents();
       if (components.isEmpty()) {
         throw new AmbariException("Components not found, service = "
             + serviceName + ", cluster = " + clusterName);
       }
-
-      ServiceComponent serviceComponent = components.values().iterator()
-          .next();
-
+      ServiceComponent serviceComponent = components.values().iterator().next();
       if (serviceComponent.getServiceComponentHosts().isEmpty()) {
         throw new AmbariException("Hosts not found, component="
             + serviceComponent.getName() + ", service = "
             + serviceName + ", cluster = " + clusterName);
       }
-
-      hostName = serviceComponent.getServiceComponentHosts().keySet().iterator().next();
+      candidateHosts = serviceComponent.getServiceComponentHosts().keySet();
+    }
+
+    // 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, actionExecutionContext.getOperationLevel(),
+                        resourceFilter, serviceName, componentName, hostname);
+              }
+            }
+    );
+    String hostName = managementController.getHealthyHost(candidateHosts);
+    if (hostName == null) {
+      String msg = String.format("Unable to find a healthy host " +
+              "amongst the provided set of " +
+              "hosts: %s. You may also see this message if " +
+              "all healthy hosts are not appropriate for service check " +
+              "due to maintenance state (these hosts are %s). ",
+              candidateHosts, ignoredHosts);
+      LOG.info(msg);
     }
 
     addServiceCheckAction(stage, hostName, smokeTestRole, nowTimestamp,

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
index abd1238..d1e85df 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java
@@ -301,6 +301,7 @@ public interface AmbariManagementController {
 
   /**
    * Create the action defined by the attributes in the given request object.
+   * Used only for custom commands/actions.
    *
    * @param actionRequest the request object which defines the action to be created
    * @param requestProperties the request properties

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index 5fa95fb..2d4b7e1 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -38,6 +38,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.DuplicateResourceException;
@@ -83,6 +84,7 @@ import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.internal.RequestOperationLevel;
 import org.apache.ambari.server.controller.internal.RequestStageContainer;
 import org.apache.ambari.server.controller.internal.URLStreamProvider;
+import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.customactions.ActionDefinition;
 import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
@@ -1166,21 +1168,29 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
              Map<String, Map<State, List<ServiceComponentHost>>> changedScHosts,
              boolean runSmokeTest) throws AmbariException {
 
+    // We choose the most general (high-level) op level here. As a result,
+    // service checks will be only launched for services/components that
+    // are not in a Maintenance state.
+    Resource.Type opLvl = Resource.Type.Cluster;
+
     Set<String> smokeTestServices = new HashSet<String>();
 
+    // Adding smoke checks for changed services
     if (changedServices != null) {
       for (Entry<State, List<Service>> entry : changedServices.entrySet()) {
         if (State.STARTED != entry.getKey()) {
           continue;
         }
         for (Service s : entry.getValue()) {
-          if (runSmokeTest && (State.INSTALLED == s.getDesiredState())) {
+          if (runSmokeTest && (State.INSTALLED == s.getDesiredState() &&
+                  maintenanceStateHelper.isOperationAllowed(opLvl, s))) {
             smokeTestServices.add(s.getName());
           }
         }
       }
     }
 
+    // Adding smoke checks for changed host components
     Map<String, Map<String, Integer>> changedComponentCount =
       new HashMap<String, Map<String, Integer>>();
     for (Map<State, List<ServiceComponentHost>> stateScHostMap :
@@ -1194,6 +1204,9 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           if (State.INSTALLED != sch.getState()) {
             continue;
           }
+          if (! maintenanceStateHelper.isOperationAllowed(opLvl, sch)) {
+            continue;
+          }
           if (!changedComponentCount.containsKey(sch.getServiceName())) {
             changedComponentCount.put(sch.getServiceName(),
               new HashMap<String, Integer>());
@@ -1212,26 +1225,32 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       }
     }
 
+    // Add service checks for any changed master component hosts or if
+    // more then one component has been changed for a service
     for (Entry<String, Map<String, Integer>> entry :
       changedComponentCount.entrySet()) {
       String serviceName = entry.getKey();
+      Service s = cluster.getService(serviceName);
       // smoke test service if more than one component is started
-      if (runSmokeTest && (entry.getValue().size() > 1)) {
+      if (runSmokeTest && (entry.getValue().size() > 1) &&
+              maintenanceStateHelper.isOperationAllowed(opLvl, s)) {
         smokeTestServices.add(serviceName);
         continue;
       }
       for (String componentName :
         changedComponentCount.get(serviceName).keySet()) {
-        ServiceComponent sc = cluster.getService(serviceName)
-          .getServiceComponent(componentName);
+        ServiceComponent sc = cluster.getService(serviceName).
+          getServiceComponent(componentName);
         StackId stackId = sc.getDesiredStackVersion();
         ComponentInfo compInfo = ambariMetaInfo.getComponentCategory(
           stackId.getStackName(), stackId.getStackVersion(), serviceName,
           componentName);
-        if (runSmokeTest && compInfo.isMaster()) {
+        if (runSmokeTest && compInfo.isMaster() &&
+                // op lvl handling for service component
+                // is the same as for service
+                maintenanceStateHelper.isOperationAllowed(opLvl, s)) {
           smokeTestServices.add(serviceName);
         }
-
         // FIXME if master check if we need to run a smoke test for the master
       }
     }
@@ -1907,6 +1926,19 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     Map<ServiceComponentHost, State> directTransitionScHosts = new HashMap<ServiceComponentHost, State>();
     Set<String> maintenanceClusters = new HashSet<String>();
 
+    // Determine operation level
+    Resource.Type reqOpLvl;
+    if (requestProperties.containsKey(RequestOperationLevel.OPERATION_LEVEL_ID)) {
+      RequestOperationLevel operationLevel = new RequestOperationLevel(requestProperties);
+      reqOpLvl = operationLevel.getLevel();
+    } else {
+      String message = "Can not determine request operation level. " +
+              "Operation level property should " +
+              "be specified for this request.";
+      LOG.warn(message);
+      reqOpLvl = Resource.Type.Cluster;
+    }
+
     for (ServiceComponentHostRequest request : requests) {
       validateServiceComponentHostRequest(request);
 
@@ -1971,6 +2003,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         }
       }
 
+      // Setting Maintenance state for host component
       if (null != request.getMaintenanceState()) {
         MaintenanceStateHelper psh = injector.getInstance(MaintenanceStateHelper.class);
 
@@ -2030,6 +2063,18 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         continue;
       }
 
+      if (! maintenanceStateHelper.isOperationAllowed(reqOpLvl, sch)) {
+        ignoredScHosts.add(sch);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Ignoring ServiceComponentHost"
+                  + ", clusterName=" + request.getClusterName()
+                  + ", serviceName=" + s.getName()
+                  + ", componentName=" + sc.getName()
+                  + ", hostname=" + sch.getHostName());
+        }
+        continue;
+      }
+
       if (!State.isValidStateTransition(oldSchState, newState)) {
         throw new AmbariException("Invalid transition for"
             + " servicecomponenthost"
@@ -2126,6 +2171,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       changedScHosts, ignoredScHosts, runSmokeTest, false);
   }
 
+
   private void validateServiceComponentHostRequest(ServiceComponentHostRequest request) {
     if (request.getClusterName() == null
         || request.getClusterName().isEmpty()
@@ -2584,6 +2630,14 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
   private String getClientHostForRunningAction(Cluster cluster,
       Service service) throws AmbariException {
+    /*
+     * We assume Cluster level here. That means that we never run service
+     * checks on clients/hosts that are in maintenance state.
+     * That also means that we can not run service check if the only host
+     * that has client component is in maintenance state
+     */
+    Resource.Type opLvl = Resource.Type.Cluster;
+
     StackId stackId = service.getDesiredStackVersion();
     ComponentInfo compInfo =
         ambariMetaInfo.getServiceInfo(stackId.getStackName(),
@@ -2593,15 +2647,15 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
         ServiceComponent serviceComponent =
             service.getServiceComponent(compInfo.getName());
         if (!serviceComponent.getServiceComponentHosts().isEmpty()) {
-          return getHealthyHost(serviceComponent.getServiceComponentHosts().keySet());
+          Set<String> candidateHosts = serviceComponent.getServiceComponentHosts().keySet();
+          filterHostsForAction(candidateHosts, service, cluster, opLvl);
+          return getHealthyHost(candidateHosts);
         }
       } catch (ServiceComponentNotFoundException e) {
         LOG.warn("Could not find required component to run action"
             + ", clusterName=" + cluster.getClusterName()
             + ", serviceName=" + service.getName()
             + ", componentName=" + compInfo.getName());
-
-
       }
     }
 
@@ -2615,11 +2669,38 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       if (serviceComponent.getServiceComponentHosts().isEmpty()) {
         continue;
       }
-      return getHealthyHost(serviceComponent.getServiceComponentHosts().keySet());
+      Set<String> candidateHosts = serviceComponent.getServiceComponentHosts().keySet();
+      filterHostsForAction(candidateHosts, service, cluster, opLvl);
+      return getHealthyHost(candidateHosts);
     }
     return null;
   }
 
+  /**
+   * Utility method that filters out hosts from set based on their maintenance
+   * state status.
+   */
+  private void filterHostsForAction(Set<String> candidateHosts, Service service,
+                                    final Cluster cluster,
+                                    final Resource.Type level)
+                                    throws AmbariException {
+    Set<String> ignoredHosts = maintenanceStateHelper.filterHostsInMaintenanceState(
+            candidateHosts, new MaintenanceStateHelper.HostPredicate() {
+              @Override
+              public boolean shouldHostBeRemoved(final String hostname)
+                      throws AmbariException {
+                Host host = clusters.getHost(hostname);
+                return !maintenanceStateHelper.isOperationAllowed(
+                        host, cluster.getClusterId(), level);
+              }
+            }
+    );
+    LOG.debug("Ignoring hosts when selecting available hosts for action" +
+            " due to maintenance state." +
+            "Ignored hosts =" + ignoredHosts + ", cluster="
+            + cluster.getClusterName() + ", service=" + service.getName());
+  }
+
 
   @Override
   public String getHealthyHost(Set<String> hostList) throws AmbariException {
@@ -2667,7 +2748,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     }
 
     Map<String, String> params = new HashMap<String, String>();
-    Map<String, Set<String>> clusterHostInfo = new HashMap<String, Set<String>>();
+    Map<String, Set<String>> clusterHostInfo;
     String clusterHostInfoJson = "{}";
 
     if (null != cluster) {
@@ -2686,7 +2767,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
       actionExecutionHelper.addExecutionCommandsToStage(actionExecContext, stage, params);
     }
 
-    RoleGraph rg = null;
+    RoleGraph rg;
     if (null != cluster) {
       RoleCommandOrder rco = getRoleCommandOrder(cluster);
       rg = new RoleGraph(rco);

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java
index 191c647..77c7167 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java
@@ -26,6 +26,7 @@ import java.util.Set;
 import com.google.inject.Singleton;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.HostNotFoundException;
+import org.apache.ambari.server.controller.internal.RequestOperationLevel;
 import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.state.Cluster;
@@ -59,6 +60,95 @@ public class MaintenanceStateHelper {
   }
 
   /**
+   * @param cluster cluster for request
+   * @param levelObj operation level (can be null)
+   * @param reqFilter request resource filter for operation (can't be null)
+   * @param serviceName service name (can be null)
+   * @param componentName component name (can be null)
+   * @param hostname host name (can't be null)
+   * @return true if operation may be performed on a given target (based
+   * on target's maintenance status).
+   */
+  public boolean isOperationAllowed(Cluster cluster,
+                                    RequestOperationLevel levelObj,
+                                    RequestResourceFilter reqFilter,
+                                    String serviceName,
+                                    String componentName,
+                                    String hostname) throws AmbariException{
+    Resource.Type level;
+    if (levelObj == null) {
+      level = guessOperationLevel(reqFilter);
+    } else {
+      level = levelObj.getLevel();
+    }
+    return isOperationAllowed(cluster, level, serviceName,
+            componentName, hostname);
+  }
+
+   /**
+   * @param cluster cluster for request
+   * @param level operation level (can't be null)
+   * @param serviceName service name (can be null)
+   * @param componentName component name (can be null)
+   * @param hostname host name (can't be null)
+   * @return true if operation may be performed on a given target (based
+   * on target's maintenance status).
+   */
+  boolean isOperationAllowed(Cluster cluster,
+                                     Resource.Type level,
+                                     String serviceName,
+                                     String componentName,
+                                     String hostname) throws AmbariException{
+    if (serviceName != null && ! serviceName.isEmpty()) {
+      Service service = cluster.getService(serviceName);
+      if (componentName != null && ! componentName.isEmpty()) {
+        ServiceComponentHost sch = service.
+                getServiceComponent(componentName).
+                getServiceComponentHost(hostname);
+        return isOperationAllowed(level, sch);
+      } else { // Only service name is defined
+        return isOperationAllowed(level, service);
+      }
+    } else { // Service is not defined, using host
+      Host host = clusters.getHost(hostname);
+      return isOperationAllowed(host, cluster.getClusterId(), level);
+    }
+  }
+
+  /**
+   * @param level operation level
+   * @param service the service
+   * @return true if operation may be performed on a given target (based
+   * on target's maintenance status).
+   */
+  public boolean isOperationAllowed(Resource.Type level,
+                                     Service service) throws AmbariException {
+    if (level == Resource.Type.Cluster) {
+      return service.getMaintenanceState() == MaintenanceState.OFF;
+    } else {
+      return true;
+    }
+  }
+
+
+  /**
+   * @param host the service
+   * @param clusterId cluster the host belongs to
+   * @param level operation level for request
+   * @return true if operation may be performed on a given target (based
+   * on target's maintenance status).
+   */
+  public boolean isOperationAllowed(Host host,
+                                    long clusterId,
+                                    Resource.Type level) throws AmbariException {
+    if (level == Resource.Type.Cluster) {
+      return host.getMaintenanceState(clusterId) == MaintenanceState.OFF;
+    } else {
+      return true;
+    }
+  }
+
+  /**
    * Get effective state of HostComponent
    * @param sch the host component
    * @param host the host
@@ -82,11 +172,9 @@ public class MaintenanceStateHelper {
    * @return the maintenance state
    * @throws AmbariException
    */
-  public MaintenanceState getEffectiveState(ServiceComponentHost sch) throws AmbariException {
-    Cluster cluster = clusters.getCluster(sch.getClusterName());
-
+  public MaintenanceState getEffectiveState(ServiceComponentHost sch)
+          throws AmbariException {
     Host host = clusters.getHost(sch.getHostName());
-
     return getEffectiveState(sch, host);
   }
   
@@ -132,7 +220,8 @@ public class MaintenanceStateHelper {
    * {@link MaintenanceState#IMPLIED_FROM_SERVICE} or
    * {@link MaintenanceState#IMPLIED_FROM_SERVICE_AND_HOST})
    */
-  public Set<Map<String, String>> getMaintenanceHostComponents(Clusters clusters, Cluster cluster) throws AmbariException {
+  public Set<Map<String, String>> getMaintenanceHostComponents(Clusters clusters,
+                                       Cluster cluster) throws AmbariException {
     Set<Map<String, String>> set = new HashSet<Map<String, String>>();
 
     Map<String, Host> hosts = clusters.getHostsForCluster(cluster.getClusterName());
@@ -161,7 +250,8 @@ public class MaintenanceStateHelper {
   }
   
   /**
-   * Creates the requests to send to the clusters
+   * Creates the requests to send to the clusters. These requests
+   * update ignored allerts Nagios configuration.
    * @param amc the controller
    * @param requestProperties the request properties
    * @param clusterNames the names of all the clusters to update
@@ -169,7 +259,8 @@ public class MaintenanceStateHelper {
    * @throws AmbariException
    */
   public RequestStatusResponse createRequests(AmbariManagementController amc,
-      Map<String, String> requestProperties, Set<String> clusterNames) throws AmbariException {
+      Map<String, String> requestProperties, Set<String> clusterNames)
+          throws AmbariException {
     
     Map<String, String> params = new HashMap<String, String>();
     
@@ -186,6 +277,9 @@ public class MaintenanceStateHelper {
         null, params);
       
       if (null == response) {
+        // createAction() may throw an exception if Nagios is in MS or
+        // if Nagios is absent in cluster. This exception is usually ignored at
+        // upper levels
         response = amc.createAction(actionRequest, requestProperties);
       }
     }    
@@ -202,8 +296,8 @@ public class MaintenanceStateHelper {
    * @throws AmbariException
    */
   public boolean isOperationAllowed(Resource.Type operationLevel,
-                                    ServiceComponentHost sch) throws AmbariException {
-    MaintenanceState maintenanceState = sch.getMaintenanceState();
+                            ServiceComponentHost sch) throws AmbariException {
+    MaintenanceState maintenanceState = getEffectiveState(sch);
 
     switch (operationLevel.getInternalType()) {
       case Cluster:
@@ -233,4 +327,64 @@ public class MaintenanceStateHelper {
     return false;
   }
 
+
+  /**
+   * Fallback logic for guessing operation level from request resource filter.
+   * It is used when operation level is not defined explicitly.
+   */
+  public Resource.Type guessOperationLevel(RequestResourceFilter filter)  {
+    Resource.Type result;
+    if (filter == null) {
+      // CLUSTER can be assumed to be the default level if no ResourceFilter
+      // is specified, because for any other resource operation
+      // a ResourceFilter is mandatory.
+      result = Resource.Type.Cluster;
+    } else {
+      boolean serviceDefined = filter.getServiceName() != null;
+      boolean componentDefined = filter.getComponentName() != null;
+      boolean hostsDefined =
+              filter.getHostNames() != null && filter.getHostNames().size() > 0;
+
+      if (hostsDefined & componentDefined) {
+        result = Resource.Type.HostComponent;
+      } else if (! serviceDefined & hostsDefined) {
+        result = Resource.Type.Host;
+      } else if (serviceDefined & ! hostsDefined) {
+        // This option also includes resource filters
+        // that target service on few hosts
+        result = Resource.Type.Service;
+      } else { // Absolute fallback
+        // Cluster level should be a good option for any unsure cases
+        // Cluster-level actions only
+        result = Resource.Type.Cluster;
+      }
+    }
+    return result;
+  }
+
+
+  public static interface HostPredicate {
+    public boolean shouldHostBeRemoved(String hostname) throws AmbariException;
+  }
+
+  /**
+   * Removes from a set all hosts that match a given condition.
+   * @param candidateHosts source set that should to be modified
+   * @param condition condition
+   * @return all hosts that have been removed from a candidateHosts
+   */
+  public Set<String> filterHostsInMaintenanceState(
+          Set<String> candidateHosts, HostPredicate condition)
+          throws AmbariException {
+    // Filter hosts that are in MS
+    Set<String> removedHosts = new HashSet<String>();
+    for (String hostname : candidateHosts) {
+      if (condition.shouldHostBeRemoved(hostname)) {
+        removedHosts.add(hostname);
+      }
+    }
+    candidateHosts.removeAll(removedHosts);
+    return removedHosts;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
index c1ddcd3..4c74b64 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ComponentResourceProvider.java
@@ -34,6 +34,7 @@ import org.apache.ambari.server.ParentObjectNotFoundException;
 import org.apache.ambari.server.ServiceNotFoundException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.RequestStatusResponse;
 import org.apache.ambari.server.controller.ServiceComponentRequest;
 import org.apache.ambari.server.controller.ServiceComponentResponse;
@@ -89,6 +90,7 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
           COMPONENT_SERVICE_NAME_PROPERTY_ID,
           COMPONENT_COMPONENT_NAME_PROPERTY_ID}));
 
+  private MaintenanceStateHelper maintenanceStateHelper;
 
   // ----- Constructors ----------------------------------------------------
 
@@ -102,8 +104,10 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
   @AssistedInject
   ComponentResourceProvider(@Assisted Set<String> propertyIds,
                             @Assisted Map<Resource.Type, String> keyPropertyIds,
-                            @Assisted AmbariManagementController managementController) {
+                            @Assisted AmbariManagementController managementController,
+                            MaintenanceStateHelper maintenanceStateHelper) {
     super(propertyIds, keyPropertyIds, managementController);
+    this.maintenanceStateHelper = maintenanceStateHelper;
   }
 
 
@@ -588,55 +592,72 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         new HashMap<String, Map<String,Set<String>>>();
     Set<State> seenNewStates = new HashSet<State>();
 
+    // Determine operation level
+    Resource.Type reqOpLvl;
+    if (requestProperties.containsKey(RequestOperationLevel.OPERATION_LEVEL_ID)) {
+      RequestOperationLevel operationLevel = new RequestOperationLevel(requestProperties);
+      reqOpLvl = operationLevel.getLevel();
+    } else {
+      String message = "Can not determine request operation level. " +
+              "Operation level property should " +
+              "be specified for this request.";
+      LOG.warn(message);
+      reqOpLvl = Resource.Type.Cluster;
+    }
+
     for (ServiceComponentRequest request : requests) {
-      if (request.getClusterName() == null
-          || request.getClusterName().isEmpty()
-          || request.getComponentName() == null
-          || request.getComponentName().isEmpty()) {
+      final String clusterName = request.getClusterName();
+      String componentName = request.getComponentName();
+      if (clusterName == null
+          || clusterName.isEmpty()
+          || componentName == null
+          || componentName.isEmpty()) {
         throw new IllegalArgumentException("Invalid arguments, cluster name"
             + ", service name and component name should be provided to"
             + " update components");
       }
 
+      String serviceName = request.getServiceName();
       LOG.info("Received a updateComponent request"
-          + ", clusterName=" + request.getClusterName()
-          + ", serviceName=" + request.getServiceName()
-          + ", componentName=" + request.getComponentName()
+          + ", clusterName=" + clusterName
+          + ", serviceName=" + serviceName
+          + ", componentName=" + componentName
           + ", request=" + request.toString());
 
-      Cluster cluster = clusters.getCluster(request.getClusterName());
+      Cluster cluster = clusters.getCluster(clusterName);
 
-      if (request.getServiceName() == null
-          || request.getServiceName().isEmpty()) {
+      if (serviceName == null
+          || serviceName.isEmpty()) {
         StackId stackId = cluster.getDesiredStackVersion();
-        String serviceName =
+        String alternativeServiceName =
             ambariMetaInfo.getComponentToService(stackId.getStackName(),
-                stackId.getStackVersion(), request.getComponentName());
+                stackId.getStackVersion(), componentName);
         if (LOG.isDebugEnabled()) {
           LOG.debug("Looking up service name for component"
-              + ", componentName=" + request.getComponentName()
-              + ", serviceName=" + serviceName);
+              + ", componentName=" + componentName
+              + ", serviceName=" + alternativeServiceName);
         }
 
-        if (serviceName == null
-            || serviceName.isEmpty()) {
+        if (alternativeServiceName == null
+            || alternativeServiceName.isEmpty()) {
           throw new AmbariException("Could not find service for component"
-              + ", componentName=" + request.getComponentName()
+              + ", componentName=" + componentName
               + ", clusterName=" + cluster.getClusterName()
               + ", stackInfo=" + stackId.getStackId());
         }
-        request.setServiceName(serviceName);
+        request.setServiceName(alternativeServiceName);
+        serviceName = alternativeServiceName;
       }
 
       if (LOG.isDebugEnabled()) {
         LOG.debug("Received a updateComponent request"
-            + ", clusterName=" + request.getClusterName()
-            + ", serviceName=" + request.getServiceName()
-            + ", componentName=" + request.getComponentName()
-            + ", request=" + request);
+                + ", clusterName=" + clusterName
+                + ", serviceName=" + serviceName
+                + ", componentName=" + componentName
+                + ", request=" + request);
       }
 
-      clusterNames.add(request.getClusterName());
+      clusterNames.add(clusterName);
 
       if (clusterNames.size() > 1) {
         // FIXME throw correct error
@@ -644,27 +665,26 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
             + " supported");
       }
 
-      if (!componentNames.containsKey(request.getClusterName())) {
-        componentNames.put(request.getClusterName(),
+      if (!componentNames.containsKey(clusterName)) {
+        componentNames.put(clusterName,
             new HashMap<String, Set<String>>());
       }
-      if (!componentNames.get(request.getClusterName())
-          .containsKey(request.getServiceName())) {
-        componentNames.get(request.getClusterName()).put(
-            request.getServiceName(), new HashSet<String>());
+      if (!componentNames.get(clusterName)
+          .containsKey(serviceName)) {
+        componentNames.get(clusterName).put(
+                serviceName, new HashSet<String>());
       }
-      if (componentNames.get(request.getClusterName())
-          .get(request.getServiceName()).contains(request.getComponentName())){
+      if (componentNames.get(clusterName)
+          .get(serviceName).contains(componentName)){
         // throw error later for dup
         throw new IllegalArgumentException("Invalid request contains duplicate"
             + " service components");
       }
-      componentNames.get(request.getClusterName())
-          .get(request.getServiceName()).add(request.getComponentName());
+      componentNames.get(clusterName)
+          .get(serviceName).add(componentName);
 
-      Service s = cluster.getService(request.getServiceName());
-      ServiceComponent sc = s.getServiceComponent(
-          request.getComponentName());
+      Service s = cluster.getService(serviceName);
+      ServiceComponent sc = s.getServiceComponent(componentName);
       State newState = null;
       if (request.getDesiredState() != null) {
         newState = State.valueOf(request.getDesiredState());
@@ -674,12 +694,19 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         }
       }
 
+      if (! maintenanceStateHelper.isOperationAllowed(reqOpLvl, s)) {
+        LOG.info("Operations cannot be applied to component " + componentName
+                + " because service " + serviceName +
+                " is in the maintenance state of " + s.getMaintenanceState());
+        continue;
+      }
+
       if (newState == null) {
         if (LOG.isDebugEnabled()) {
           LOG.debug("Nothing to do for new updateServiceComponent request"
-              + ", clusterName=" + request.getClusterName()
-              + ", serviceName=" + request.getServiceName()
-              + ", componentName=" + request.getComponentName()
+              + ", clusterName=" + clusterName
+              + ", serviceName=" + serviceName
+              + ", componentName=" + componentName
               + ", newDesiredState=null");
         }
         continue;
@@ -711,8 +738,8 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         }
         if (LOG.isDebugEnabled()) {
           LOG.debug("Handling update to ServiceComponent"
-              + ", clusterName=" + request.getClusterName()
-              + ", serviceName=" + s.getName()
+              + ", clusterName=" + clusterName
+              + ", serviceName=" + serviceName
               + ", componentName=" + sc.getName()
               + ", currentDesiredState=" + oldScState
               + ", newDesiredState=" + newState);
@@ -725,8 +752,8 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         if (oldSchState == State.DISABLED || oldSchState == State.UNKNOWN) {
           if (LOG.isDebugEnabled()) {
             LOG.debug("Ignoring ServiceComponentHost"
-                + ", clusterName=" + request.getClusterName()
-                + ", serviceName=" + s.getName()
+                + ", clusterName=" + clusterName
+                + ", serviceName=" + serviceName
                 + ", componentName=" + sc.getName()
                 + ", hostname=" + sch.getHostName()
                 + ", currentState=" + oldSchState
@@ -739,8 +766,8 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
           ignoredScHosts.add(sch);
           if (LOG.isDebugEnabled()) {
             LOG.debug("Ignoring ServiceComponentHost"
-                + ", clusterName=" + request.getClusterName()
-                + ", serviceName=" + s.getName()
+                + ", clusterName=" + clusterName
+                + ", serviceName=" + serviceName
                 + ", componentName=" + sc.getName()
                 + ", hostname=" + sch.getHostName()
                 + ", currentState=" + oldSchState
@@ -750,15 +777,14 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         }
 
         // do not update or alter any HC that is not active
-        MaintenanceState schMaint = controller.getEffectiveMaintenanceState(sch);
-        if (MaintenanceState.OFF != schMaint) {
+        if (! maintenanceStateHelper.isOperationAllowed(reqOpLvl, sch)) {
+          ignoredScHosts.add(sch);
           if (LOG.isDebugEnabled()) {
-            LOG.debug("Ignoring ServiceComponentHost"
-                + ", clusterName=" + request.getClusterName()
-                + ", serviceName=" + s.getName()
+            LOG.debug("Ignoring ServiceComponentHost in maintenance state"
+                + ", clusterName=" + clusterName
+                + ", serviceName=" + serviceName
                 + ", componentName=" + sc.getName()
-                + ", hostname=" + sch.getHostName()
-                + ", maintenance=" + schMaint);
+                + ", hostname=" + sch.getHostName());
           }
           continue;
         }
@@ -785,8 +811,8 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
         }
         if (LOG.isDebugEnabled()) {
           LOG.debug("Handling update to ServiceComponentHost"
-              + ", clusterName=" + request.getClusterName()
-              + ", serviceName=" + s.getName()
+              + ", clusterName=" + clusterName
+              + ", serviceName=" + serviceName
               + ", componentName=" + sc.getName()
               + ", hostname=" + sch.getHostName()
               + ", currentState=" + oldSchState
@@ -816,4 +842,4 @@ public class ComponentResourceProvider extends AbstractControllerResourceProvide
   protected RequestStatusResponse deleteComponents() throws AmbariException {
     throw new AmbariException("Delete components not supported");
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestOperationLevel.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestOperationLevel.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestOperationLevel.java
index a74b8a1..c7c0160 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestOperationLevel.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestOperationLevel.java
@@ -19,6 +19,8 @@ package org.apache.ambari.server.controller.internal;
 
 import org.apache.ambari.server.controller.spi.Resource;
 
+import java.util.Map;
+
 /**
  * Operation level is specified along with some requests. It identifies
  * the logical level, at which the operation is executed.
@@ -41,6 +43,13 @@ public class RequestOperationLevel {
   private static final int ALIAS_COLUMN = 0;
   private static final int INTERNAL_NAME_COLUMN = 1;
 
+  // Identifiers of properties as they appear at request properties
+  public static final String OPERATION_LEVEL_ID = "operation_level/level";
+  public static final String OPERATION_CLUSTER_ID = "operation_level/cluster_name";
+  public static final String OPERATION_SERVICE_ID = "operation_level/service_name";
+  public static final String OPERATION_HOSTCOMPONENT_ID = "operation_level/hostcomponent_name";
+  public static final String OPERATION_HOST_ID = "operation_level/host_name";
+
   /**
    * Converts external operation level alias to an internal name
    */
@@ -82,6 +91,36 @@ public class RequestOperationLevel {
   }
 
   /**
+   * Constructs a new entity from
+   * @param requestInfoProperties
+   * @throws IllegalArgumentException
+   */
+  public RequestOperationLevel(Map<String, String> requestInfoProperties)
+          throws IllegalArgumentException {
+    String operationLevelStr = requestInfoProperties.get(
+            RequestOperationLevel.OPERATION_LEVEL_ID);
+    try {
+      String internalOpLevelNameStr = getInternalLevelName(operationLevelStr);
+      this.level = Resource.Type.valueOf(internalOpLevelNameStr);
+    } catch (IllegalArgumentException e) {
+      String message = String.format(
+              "Wrong operation level value: %s", operationLevelStr);
+      throw new IllegalArgumentException(message, e);
+    }
+    if (!requestInfoProperties.containsKey(OPERATION_CLUSTER_ID)) {
+      String message = String.format(
+              "Mandatory key %s for operation level is not specified",
+              OPERATION_CLUSTER_ID);
+      throw new IllegalArgumentException(message);
+    }
+    this.clusterName = requestInfoProperties.get(OPERATION_CLUSTER_ID);
+    this.serviceName = requestInfoProperties.get(OPERATION_SERVICE_ID);
+    this.hostComponentName =
+            requestInfoProperties.get(OPERATION_HOSTCOMPONENT_ID);
+    this.hostName = requestInfoProperties.get(OPERATION_HOST_ID);
+  }
+
+  /**
    * Valid values are Cluster, Service, Host and HostComponent. Component level
    * is identical to Service level, and that's why it is not supported
    * as a standalone level.

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
index 18f9d6b..c7eecec 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RequestResourceProvider.java
@@ -84,14 +84,6 @@ public class RequestResourceProvider extends AbstractControllerResourceProvider
       new HashSet<String>(Arrays.asList(new String[]{
           REQUEST_ID_PROPERTY_ID}));
 
-  /**
-   * Operation level-related parameters
-   */
-  protected static final String OPERATION_LEVEL_ID = "operation_level/level";
-  protected static final String OPERATION_CLUSTER_ID = "operation_level/cluster_name";
-  protected static final String OPERATION_SERVICE_ID = "operation_level/service_name";
-  protected static final String OPERATION_HOSTCOMPONENT_ID = "operation_level/hostcomponent_name";
-  protected static final String OPERATION_HOST_ID = "operation_level/host_name";
 
   // ----- Constructors ----------------------------------------------------
 
@@ -238,32 +230,8 @@ public class RequestResourceProvider extends AbstractControllerResourceProvider
     }
     // Extract operation level property
     RequestOperationLevel operationLevel = null;
-    Object operationLevelObj = requestInfoProperties.get(OPERATION_LEVEL_ID);
-    if (operationLevelObj != null) {
-      Resource.Type level;
-      try {
-        String internalOpLevelNameStr =
-                RequestOperationLevel.getInternalLevelName(
-                        (String)operationLevelObj);
-        level = Resource.Type.valueOf(internalOpLevelNameStr);
-      } catch (IllegalArgumentException e) {
-        String message = String.format(
-                "Wrong operation level value: %s", operationLevelObj);
-        throw new UnsupportedOperationException(message, e);
-      }
-      if (!requestInfoProperties.containsKey(OPERATION_CLUSTER_ID)) {
-        String message = String.format(
-                "Mandatory key %s for operation level is not specified",
-                OPERATION_CLUSTER_ID);
-        throw new UnsupportedOperationException(message);
-      }
-      String clusterName = requestInfoProperties.get(OPERATION_CLUSTER_ID);
-      String serviceName = requestInfoProperties.get(OPERATION_SERVICE_ID);
-      String hostComponentName =
-              requestInfoProperties.get(OPERATION_HOSTCOMPONENT_ID);
-      String hostName = requestInfoProperties.get(OPERATION_HOST_ID);
-      operationLevel = new RequestOperationLevel(level, clusterName,
-              serviceName, hostComponentName, hostName);
+    if (requestInfoProperties.containsKey(RequestOperationLevel.OPERATION_LEVEL_ID)) {
+      operationLevel = new RequestOperationLevel(requestInfoProperties);
     }
 
     Map<String, String> params = new HashMap<String, String>();

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
index d1c18c5..21dcdc8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
@@ -110,7 +110,6 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
 
   private static final ServiceState DEFAULT_SERVICE_STATE = new DefaultServiceState();
 
-  @Inject
   private MaintenanceStateHelper maintenanceStateHelper;
 
   // ----- Constructors ----------------------------------------------------
@@ -125,8 +124,10 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
   @AssistedInject
   public ServiceResourceProvider(@Assisted Set<String> propertyIds,
                           @Assisted Map<Resource.Type, String> keyPropertyIds,
-                          @Assisted AmbariManagementController managementController) {
+                          @Assisted AmbariManagementController managementController,
+                          MaintenanceStateHelper maintenanceStateHelper) {
     super(propertyIds, keyPropertyIds, managementController);
+    this.maintenanceStateHelper = maintenanceStateHelper;
   }
 
   // ----- ResourceProvider ------------------------------------------------
@@ -568,6 +569,18 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
     Map<String, Set<String>> serviceNames = new HashMap<String, Set<String>>();
     Set<State> seenNewStates = new HashSet<State>();
 
+    // Determine operation level
+    Resource.Type reqOpLvl;
+    if (requestProperties.containsKey(RequestOperationLevel.OPERATION_LEVEL_ID)) {
+      RequestOperationLevel operationLevel = new RequestOperationLevel(requestProperties);
+      reqOpLvl = operationLevel.getLevel();
+    } else {
+      String message = "Can not determine request operation level. " +
+              "Operation level property should " +
+              "be specified for this request.";
+      LOG.warn(message);
+      reqOpLvl = Resource.Type.Cluster;
+    }
 
     Clusters       clusters        = controller.getClusters();
     AmbariMetaInfo ambariMetaInfo   = controller.getAmbariMetaInfo();
@@ -616,7 +629,8 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
               + " desired state, desiredState=" + newState);
         }
       }
-      
+
+      // Setting Maintenance state for service
       if (null != request.getMaintenanceState()) {
         MaintenanceState newMaint = MaintenanceState.valueOf(request.getMaintenanceState());
         if (newMaint  != s.getMaintenanceState()) {
@@ -641,14 +655,13 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
         }
         continue;
       }
-      
-      if (requests.size() > 1 && MaintenanceState.OFF != s.getMaintenanceState()) {
+
+      if (! maintenanceStateHelper.isOperationAllowed(reqOpLvl, s)) {
         LOG.info("Operations cannot be applied to service " + s.getName() +
             " in the maintenance state of " + s.getMaintenanceState());
         continue;
       }
       
-
       seenNewStates.add(newState);
 
       if (newState != oldState) {
@@ -732,12 +745,10 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
             continue;
           }
           
-          MaintenanceState schMaint = controller.getEffectiveMaintenanceState(sch);
-          if (MaintenanceState.ON == schMaint ||
-              (requests.size() > 1 && MaintenanceState.OFF != schMaint)) {
+          if (! maintenanceStateHelper.isOperationAllowed(reqOpLvl, sch)) {
             ignoredScHosts.add(sch);
             if (LOG.isDebugEnabled()) {
-              LOG.debug("Ignoring " + schMaint + " ServiceComponentHost"
+              LOG.debug("Ignoring ServiceComponentHost"
                   + ", clusterName=" + request.getClusterName()
                   + ", serviceName=" + s.getName()
                   + ", componentName=" + sc.getName()
@@ -745,24 +756,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
             }
             continue;
           }
-          Host host = clusters.getHost(sch.getHostName());
-
-          if (schMaint == MaintenanceState.IMPLIED_FROM_HOST
-             && host != null
-             && host.getMaintenanceState(cluster.getClusterId()) != MaintenanceState.OFF) {
 
-            // Host is in Passive mode, ignore the SCH
-            ignoredScHosts.add(sch);
-            LOG.info("Ignoring ServiceComponentHost since "
-              + "the host is in passive mode"
-              + ", clusterName=" + request.getClusterName()
-              + ", serviceName=" + s.getName()
-              + ", componentName=" + sc.getName()
-              + ", hostname=" + sch.getHostName());
-            continue;
-          }
-          
-          
           if (sc.isClientComponent() &&
               !newState.isValidClientComponentState()) {
             continue;

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
index 8d518e4..aafe8ec 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/BaseResourceDefinitionTest.java
@@ -19,18 +19,21 @@
 package org.apache.ambari.server.api.resources;
 
 import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.anyObject;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.handlers.BaseManagementHandler;
 import org.apache.ambari.server.api.query.render.DefaultRenderer;
 import org.apache.ambari.server.api.query.render.MinimalRenderer;
 import org.apache.ambari.server.api.util.TreeNode;
 import org.apache.ambari.server.api.util.TreeNodeImpl;
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.ResourceProviderFactory;
 import org.apache.ambari.server.controller.internal.AbstractControllerResourceProvider;
 import org.apache.ambari.server.controller.internal.ResourceImpl;
@@ -38,6 +41,7 @@ import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.state.Service;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -51,7 +55,7 @@ import java.util.Set;
 public class BaseResourceDefinitionTest {
 
   @Test
-  public void testGetPostProcessors() {
+  public void testGetPostProcessors() throws AmbariException {
     BaseResourceDefinition resourceDefinition = getResourceDefinition();
 
     List<ResourceDefinition.PostProcessor> postProcessors = resourceDefinition.getPostProcessors();
@@ -69,12 +73,14 @@ public class BaseResourceDefinitionTest {
     parentNode.setProperty("isCollection", "true");
     
     ResourceProviderFactory factory = createMock(ResourceProviderFactory.class);
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
-    
+    expect(maintenanceStateHelper.isOperationAllowed(anyObject(Resource.Type.class),
+            anyObject(Service.class))).andReturn(true).anyTimes();
     ResourceProvider serviceResourceProvider = new ServiceResourceProvider(PropertyHelper
         .getPropertyIds(Resource.Type.Service),
         PropertyHelper.getKeyPropertyIds(Resource.Type.Service),
-        managementController);
+        managementController, maintenanceStateHelper);
     
     expect(factory.getServiceResourceProvider(anyObject(Set.class),
         anyObject(Map.class),
@@ -82,7 +88,7 @@ public class BaseResourceDefinitionTest {
     
     AbstractControllerResourceProvider.init(factory);
     
-    replay(factory, managementController);
+    replay(factory, managementController, maintenanceStateHelper);
     
     processor.process(null, serviceNode, "http://c6401.ambari.apache.org:8080/api/v1/clusters/c1/services");
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
index 3efceed..5097fd9 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java
@@ -388,6 +388,14 @@ public class AmbariManagementControllerTest {
   private long startService(String clusterName, String serviceName,
                             boolean runSmokeTests, boolean reconfigureClients) throws
       AmbariException {
+    return startService(clusterName, serviceName, runSmokeTests, reconfigureClients, null);
+  }
+
+
+  private long startService(String clusterName, String serviceName,
+                            boolean runSmokeTests, boolean reconfigureClients,
+                            MaintenanceStateHelper maintenanceStateHelper) throws
+      AmbariException {
     ServiceRequest r = new ServiceRequest(clusterName, serviceName,
         State.STARTED.toString());
     Set<ServiceRequest> requests = new HashSet<ServiceRequest>();
@@ -395,7 +403,7 @@ public class AmbariManagementControllerTest {
     Map<String, String> mapRequestProps = new HashMap<String, String>();
     mapRequestProps.put("context", "Called from a test");
     RequestStatusResponse resp = ServiceResourceProviderTest.updateServices(controller, requests,
-        mapRequestProps, runSmokeTests, reconfigureClients);
+        mapRequestProps, runSmokeTests, reconfigureClients, maintenanceStateHelper);
 
     Assert.assertEquals(State.STARTED,
         clusters.getCluster(clusterName).getService(serviceName)
@@ -416,9 +424,22 @@ public class AmbariManagementControllerTest {
     }
   }
 
+
   private long installService(String clusterName, String serviceName,
-                              boolean runSmokeTests, boolean reconfigureClients) throws
-      AmbariException {
+                              boolean runSmokeTests, boolean reconfigureClients)
+          throws AmbariException {
+    return installService(clusterName, serviceName, runSmokeTests, reconfigureClients, null);
+  }
+
+
+  /**
+   * Allows to set maintenanceStateHelper. For use when there is anything to test
+   * with maintenance mode.
+   */
+  private long installService(String clusterName, String serviceName,
+                              boolean runSmokeTests, boolean reconfigureClients,
+                              MaintenanceStateHelper maintenanceStateHelper)
+          throws AmbariException {
     ServiceRequest r = new ServiceRequest(clusterName, serviceName,
         State.INSTALLED.toString());
     Set<ServiceRequest> requests = new HashSet<ServiceRequest>();
@@ -426,7 +447,7 @@ public class AmbariManagementControllerTest {
     Map<String, String> mapRequestProps = new HashMap<String, String>();
     mapRequestProps.put("context", "Called from a test");
     RequestStatusResponse resp = ServiceResourceProviderTest.updateServices(controller, requests,
-        mapRequestProps, runSmokeTests, reconfigureClients);
+        mapRequestProps, runSmokeTests, reconfigureClients, maintenanceStateHelper);
 
     Assert.assertEquals(State.INSTALLED,
         clusters.getCluster(clusterName).getService(serviceName)
@@ -445,6 +466,7 @@ public class AmbariManagementControllerTest {
     }
   }
 
+
   private boolean checkExceptionType(Throwable e, Class<? extends Exception> exceptionClass) {
     return e != null && (exceptionClass.isAssignableFrom(e.getClass()) || checkExceptionType(e.getCause(), exceptionClass));
   }
@@ -6329,7 +6351,7 @@ public class AmbariManagementControllerTest {
     // Test service checks - specific host
     resourceFilters.clear();
     resourceFilter = new RequestResourceFilter("HDFS", null,
-      new ArrayList<String>() {{ add("h2"); }});
+      new ArrayList<String>() {{ add("h1"); }});
     resourceFilters.add(resourceFilter);
     request = new ExecuteActionRequest("c1", Role.HDFS_SERVICE_CHECK.name(),
       null, resourceFilters, null, null);
@@ -6340,7 +6362,7 @@ public class AmbariManagementControllerTest {
     Assert.assertNotNull(storedTasks);
     Assert.assertEquals(Role.HDFS_SERVICE_CHECK.name(),
       storedTasks.get(0).getRole().name());
-    Assert.assertEquals("h2", storedTasks.get(0).getHostName());
+    Assert.assertEquals("h1", storedTasks.get(0).getHostName());
   }
 
 
@@ -9577,12 +9599,15 @@ public class AmbariManagementControllerTest {
     Cluster cluster = clusters.getCluster(clusterName);
     Service service = cluster.getService(serviceName);
     Map<String, Host> hosts = clusters.getHostsForCluster(clusterName);
+
+    MaintenanceStateHelper maintenanceStateHelper =
+            MaintenanceStateHelperTest.getMaintenanceStateHelperInstance(clusters);
     
     // test updating a service
     ServiceRequest sr = new ServiceRequest(clusterName, serviceName, null);
     sr.setMaintenanceState(MaintenanceState.ON.name());
     ServiceResourceProviderTest.updateServices(controller, Collections.singleton(sr),
-        requestProperties, false, false);
+        requestProperties, false, false, maintenanceStateHelper);
     Assert.assertEquals(MaintenanceState.ON, service.getMaintenanceState());
     
     // check the host components implied state vs desired state
@@ -9597,7 +9622,7 @@ public class AmbariManagementControllerTest {
     // reset
     sr.setMaintenanceState(MaintenanceState.OFF.name());
     ServiceResourceProviderTest.updateServices(controller, Collections.singleton(sr),
-        requestProperties, false, false);
+        requestProperties, false, false, maintenanceStateHelper);
     Assert.assertEquals(MaintenanceState.OFF, service.getMaintenanceState());
     
     // check the host components implied state vs desired state
@@ -9717,8 +9742,8 @@ public class AmbariManagementControllerTest {
       }
     }    
 
-    long id1 = installService(clusterName, serviceName, false, false);
-    long id2 = installService(clusterName, nagiosService, false, false);
+    long id1 = installService(clusterName, serviceName, false, false, maintenanceStateHelper);
+    long id2 = installService(clusterName, nagiosService, false, false, maintenanceStateHelper);
 
     List<HostRoleCommand> hdfsCmds = actionDB.getRequestTasks(id1);
     List<HostRoleCommand> nagiosCmds = actionDB.getRequestTasks(id2);
@@ -9790,7 +9815,6 @@ public class AmbariManagementControllerTest {
     createServiceComponent(clusterName, serviceName2, componentName2_2,
         State.INIT);
     
-
     String host1 = "h1";
     String host2 = "h2";
     
@@ -9803,16 +9827,19 @@ public class AmbariManagementControllerTest {
     
     createServiceComponentHost(clusterName, serviceName2, componentName2_1, host1, null);
     createServiceComponentHost(clusterName, serviceName2, componentName2_2, host2, null);
+
+    MaintenanceStateHelper maintenanceStateHelper =
+            MaintenanceStateHelperTest.getMaintenanceStateHelperInstance(clusters);
     
-    installService(clusterName, serviceName1, false, false);
-    installService(clusterName, serviceName2, false, false);
+    installService(clusterName, serviceName1, false, false, maintenanceStateHelper);
+    installService(clusterName, serviceName2, false, false, maintenanceStateHelper);
     
-    startService(clusterName, serviceName1, false, false);
-    startService(clusterName, serviceName2, false, false);
+    startService(clusterName, serviceName1, false, false, maintenanceStateHelper);
+    startService(clusterName, serviceName2, false, false, maintenanceStateHelper);
     
     Map<String, String> requestProperties = new HashMap<String, String>();
     requestProperties.put("context", "Called from a test");
-    
+
     Cluster cluster = clusters.getCluster(clusterName);
     
     for (Service service : cluster.getServices().values()) {
@@ -9825,7 +9852,8 @@ public class AmbariManagementControllerTest {
     Set<ServiceRequest> srs = new HashSet<ServiceRequest>();
     srs.add(new ServiceRequest(clusterName, serviceName1, State.INSTALLED.name()));
     srs.add(new ServiceRequest(clusterName, serviceName2, State.INSTALLED.name()));
-    RequestStatusResponse rsr = ServiceResourceProviderTest.updateServices(controller, srs, requestProperties, false, false);
+    RequestStatusResponse rsr = ServiceResourceProviderTest.updateServices(controller, srs,
+            requestProperties, false, false, maintenanceStateHelper);
     
     for (ShortTaskStatus sts : rsr.getTasks()) {
       String role = sts.getRole();
@@ -9841,13 +9869,14 @@ public class AmbariManagementControllerTest {
     }
     
     service2.setMaintenanceState(MaintenanceState.OFF);
-    ServiceResourceProviderTest.updateServices(controller, srs, requestProperties, false, false);
+    ServiceResourceProviderTest.updateServices(controller, srs, requestProperties,
+            false, false, maintenanceStateHelper);
     for (Service service : cluster.getServices().values()) {
       Assert.assertEquals(State.INSTALLED, service.getDesiredState());
     }
     
-    startService(clusterName, serviceName1, false, false);
-    startService(clusterName, serviceName2, false, false);
+    startService(clusterName, serviceName1, false, false, maintenanceStateHelper);
+    startService(clusterName, serviceName2, false, false, maintenanceStateHelper);
     
     // test host
     Host h1 = clusters.getHost(host1);
@@ -9857,25 +9886,25 @@ public class AmbariManagementControllerTest {
     srs.add(new ServiceRequest(clusterName, serviceName1, State.INSTALLED.name()));
     srs.add(new ServiceRequest(clusterName, serviceName2, State.INSTALLED.name()));
     
-    rsr = ServiceResourceProviderTest.updateServices(controller, srs, requestProperties, false, false);
+    rsr = ServiceResourceProviderTest.updateServices(controller, srs, requestProperties,
+            false, false, maintenanceStateHelper);
     
     for (ShortTaskStatus sts : rsr.getTasks()) {
       Assert.assertFalse(sts.getHostName().equals(host1));
     }
     
     h1.setMaintenanceState(cluster.getClusterId(), MaintenanceState.OFF);
-    startService(clusterName, serviceName2, false, false);
+    startService(clusterName, serviceName2, false, false, maintenanceStateHelper);
     
     service2.setMaintenanceState(MaintenanceState.ON);
-    
+
     ServiceRequest sr = new ServiceRequest(clusterName, serviceName2, State.INSTALLED.name());
     rsr = ServiceResourceProviderTest.updateServices(controller,
-        Collections.singleton(sr), requestProperties, false, false);
-    
-    System.out.println(rsr.getTasks());
+        Collections.singleton(sr), requestProperties, false, false, maintenanceStateHelper);
     
-    Assert.assertTrue("Service is started, command should create tasks",
-        rsr.getTasks().size() > 0);
+    Assert.assertTrue("Service start request defaults to Cluster operation level," +
+                    "command does not create tasks",
+        rsr == null || rsr.getTasks().size() == 0);
     
   }