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:29 UTC

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

Repository: ambari
Updated Branches:
  refs/heads/trunk 4b3ab24fc -> 30a41aca3


http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/MaintenanceStateHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/MaintenanceStateHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/MaintenanceStateHelperTest.java
index 08ccc87..8b9b36a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/MaintenanceStateHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/MaintenanceStateHelperTest.java
@@ -17,23 +17,9 @@
  */
 package org.apache.ambari.server.controller;
 
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.createMockBuilder;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import com.google.inject.Injector;
+import org.apache.ambari.server.AmbariException;
+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;
@@ -43,10 +29,34 @@ import org.apache.ambari.server.state.MaintenanceState;
 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.controller.spi.Resource.Type;
 import org.easymock.Capture;
+import org.easymock.EasyMock;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.easymock.EasyMock.anyInt;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+
 /**
  * Tests the {@link MaintenanceStateHelper} class
  */
@@ -231,6 +241,52 @@ public class MaintenanceStateHelperTest {
   }
 
   @Test
+  public void testisOperationAllowed() throws Exception {
+    // Tests that isOperationAllowed() falls
+    // back to guessing req op level if operation level is not specified
+    // explicitly
+    Injector injector = createStrictMock(Injector.class);
+    Cluster cluster = createMock(Cluster.class);
+    Method isOperationAllowed = MaintenanceStateHelper.class.getDeclaredMethod(
+            "isOperationAllowed", new Class[]{Cluster.class, Type.class,
+            String.class, String.class, String.class});
+    MaintenanceStateHelper maintenanceStateHelper =
+            createMockBuilder(MaintenanceStateHelper.class)
+                    .withConstructor(injector)
+                    .addMockedMethod(isOperationAllowed)
+                    .createNiceMock();
+
+    RequestResourceFilter filter = createMock(RequestResourceFilter.class);
+    RequestOperationLevel level = createMock(RequestOperationLevel.class);
+    expect(level.getLevel()).andReturn(Type.Cluster);
+    expect(maintenanceStateHelper.isOperationAllowed(
+            anyObject(Cluster.class), anyObject(Type.class),
+            anyObject(String.class),
+            anyObject(String.class), anyObject(String.class))).andStubReturn(true);
+    // Case when level is defined
+    replay(cluster, maintenanceStateHelper, level);
+    maintenanceStateHelper.isOperationAllowed(cluster, level, filter, "service", "component", "hostname");
+    verify(maintenanceStateHelper, level);
+
+    maintenanceStateHelper =
+            createMockBuilder(MaintenanceStateHelper.class)
+                    .withConstructor(injector)
+                    .addMockedMethod(isOperationAllowed)
+                    .addMockedMethod("guessOperationLevel")
+                    .createNiceMock();
+
+    expect(maintenanceStateHelper.guessOperationLevel(anyObject(RequestResourceFilter.class))).andReturn(Type.Cluster);
+    expect(maintenanceStateHelper.isOperationAllowed(
+            anyObject(Cluster.class), anyObject(Type.class),
+            anyObject(String.class),
+            anyObject(String.class), anyObject(String.class))).andStubReturn(true);
+    // Case when level is not defined
+    replay(maintenanceStateHelper);
+    maintenanceStateHelper.isOperationAllowed(cluster, null, filter, "service", "component", "hostname");
+    verify(maintenanceStateHelper);
+  }
+
+  @Test
   public void testHostComponentImpliedState() throws Exception {
     Injector injector = createStrictMock(Injector.class);
     MaintenanceStateHelper maintenanceStateHelper =
@@ -263,10 +319,7 @@ public class MaintenanceStateHelperTest {
     expect(service.getMaintenanceState()).andReturn(MaintenanceState.OFF);
     expect(host.getMaintenanceState(1L)).andReturn(MaintenanceState.ON);
 
-    Class<?> maintenanceHelperClass = MaintenanceStateHelper.class;
-    Field f = maintenanceHelperClass.getDeclaredField("clusters");
-    f.setAccessible(true);
-    f.set(maintenanceStateHelper, clusters);
+    injectField(maintenanceStateHelper, clusters);
 
     replay(maintenanceStateHelper, clusters, cluster, sch, host, service);
 
@@ -286,43 +339,104 @@ public class MaintenanceStateHelperTest {
   }
 
   @Test
+  public void testServiceOperationsAllowance() throws Exception {
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper =
+            createMockBuilder(MaintenanceStateHelper.class)
+                    .withConstructor(injector)
+                    .createNiceMock();
+
+    Service service = createMock(Service.class);
+
+    // only called for Cluster level
+    expect(service.getMaintenanceState()).andReturn(MaintenanceState.ON);
+    expect(service.getMaintenanceState()).andReturn(MaintenanceState.OFF);
+
+    replay(maintenanceStateHelper, service);
+
+
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, service));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Service, service));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Host, service));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.HostComponent, service));
+
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, service));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Service, service));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Host, service));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.HostComponent, service));
+
+    verify(maintenanceStateHelper, service);
+  }
+
+  @Test
+  public void testHostOperationsAllowance() throws Exception {
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper =
+            createMockBuilder(MaintenanceStateHelper.class)
+                    .withConstructor(injector)
+                    .createNiceMock();
+
+    Host host = createMock(Host.class);
+
+    // only called for Cluster level
+    expect(host.getMaintenanceState(anyInt())).andReturn(MaintenanceState.ON);
+    expect(host.getMaintenanceState(anyInt())).andReturn(MaintenanceState.OFF);
+
+    replay(maintenanceStateHelper, host);
+
+
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(host, 1, Resource.Type.Cluster));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(host, 1, Resource.Type.Service));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(host, 1, Resource.Type.Host));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(host, 1, Resource.Type.HostComponent));
+
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(host, 1, Resource.Type.Cluster));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(host, 1, Resource.Type.Service));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(host, 1, Resource.Type.Host));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(host, 1, Resource.Type.HostComponent));
+
+    verify(maintenanceStateHelper, host);
+  }
+
+  @Test
   public void testHostComponentOperationsAllowance() throws Exception {
     Injector injector = createStrictMock(Injector.class);
+    Method getEffectiveState = MaintenanceStateHelper.class.getMethod("getEffectiveState", new Class[]{ServiceComponentHost.class});
     MaintenanceStateHelper maintenanceStateHelper =
       createMockBuilder(MaintenanceStateHelper.class)
         .withConstructor(injector)
+        .addMockedMethod(getEffectiveState)
         .createNiceMock();
 
     ServiceComponentHost sch = createMock(ServiceComponentHost.class);
 
     // Cluster
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.ON);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_HOST);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.OFF);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.ON);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_HOST);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.OFF);
 
     // Service
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.ON);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_HOST);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.OFF);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.ON);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_HOST);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.OFF);
 
     // Host
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.ON);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_HOST);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.OFF);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.ON);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_HOST);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.OFF);
 
     // HostComponent
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.ON);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_HOST);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST);
-    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.OFF);
-
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.ON);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_HOST);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST);
+    expect(maintenanceStateHelper.getEffectiveState(anyObject(ServiceComponentHost.class))).andReturn(MaintenanceState.OFF);
 
     replay(maintenanceStateHelper, sch);
 
@@ -356,4 +470,90 @@ public class MaintenanceStateHelperTest {
 
     verify(maintenanceStateHelper, sch);
   }
+
+  @Test
+  public void testGuessOperationLevel() {
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper =
+            createMockBuilder(MaintenanceStateHelper.class)
+                    .withConstructor(injector)
+                    .createNiceMock();
+    replay(maintenanceStateHelper);
+
+    Assert.assertEquals(Resource.Type.Cluster, maintenanceStateHelper.guessOperationLevel(null));
+
+    RequestResourceFilter resourceFilter = new RequestResourceFilter(null, null, null);
+    Assert.assertEquals(Resource.Type.Cluster, maintenanceStateHelper.guessOperationLevel(resourceFilter));
+
+    resourceFilter = new RequestResourceFilter("HDFS", null, null);
+    Assert.assertEquals(Resource.Type.Service, maintenanceStateHelper.guessOperationLevel(resourceFilter));
+
+    resourceFilter = new RequestResourceFilter("HDFS", "NAMENODE", null);
+    Assert.assertEquals(Resource.Type.Service, maintenanceStateHelper.guessOperationLevel(resourceFilter));
+
+    ArrayList<String> hosts = new ArrayList<String>();
+    hosts.add("host1");
+    hosts.add("host2");
+    resourceFilter = new RequestResourceFilter("HDFS", null, hosts);
+    Assert.assertEquals(Resource.Type.Cluster, maintenanceStateHelper.guessOperationLevel(resourceFilter));
+
+    resourceFilter = new RequestResourceFilter(null, null, hosts);
+    Assert.assertEquals(Resource.Type.Host, maintenanceStateHelper.guessOperationLevel(resourceFilter));
+
+    resourceFilter = new RequestResourceFilter("HDFS", "NAMENODE", hosts);
+    Assert.assertEquals(Resource.Type.HostComponent, maintenanceStateHelper.guessOperationLevel(resourceFilter));
+
+  }
+
+  @Test
+  public void testCutOffHosts() throws AmbariException {
+    MaintenanceStateHelper.HostPredicate predicate = createMock(MaintenanceStateHelper.HostPredicate.class);
+    expect(predicate.shouldHostBeRemoved(eq("host1"))).andReturn(true);
+    expect(predicate.shouldHostBeRemoved(eq("host2"))).andReturn(false);
+    expect(predicate.shouldHostBeRemoved(eq("host3"))).andReturn(true);
+    expect(predicate.shouldHostBeRemoved(eq("host4"))).andReturn(false);
+    Set<String> candidates = new HashSet<String>();
+    candidates.add("host1");
+    candidates.add("host2");
+    candidates.add("host3");
+    candidates.add("host4");
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper =
+            createMockBuilder(MaintenanceStateHelper.class)
+                    .withConstructor(injector)
+                    .createNiceMock();
+    replay(predicate, maintenanceStateHelper);
+
+    Set<String> ignored = maintenanceStateHelper.filterHostsInMaintenanceState(candidates, predicate);
+
+    verify(predicate, maintenanceStateHelper);
+
+    Assert.assertEquals(candidates.size(), 2);
+    Assert.assertTrue(candidates.contains("host2"));
+    Assert.assertTrue(candidates.contains("host4"));
+
+    Assert.assertEquals(ignored.size(), 2);
+    Assert.assertTrue(ignored.contains("host1"));
+    Assert.assertTrue(ignored.contains("host3"));
+  }
+
+  private static void injectField(MaintenanceStateHelper maintenanceStateHelper, Clusters clusters)
+          throws NoSuchFieldException, IllegalAccessException {
+    Class<?> maintenanceHelperClass = MaintenanceStateHelper.class;
+    Field f = maintenanceHelperClass.getDeclaredField("clusters");
+    f.setAccessible(true);
+    f.set(maintenanceStateHelper, clusters);
+  }
+
+  public static MaintenanceStateHelper getMaintenanceStateHelperInstance(
+    Clusters clusters) throws NoSuchFieldException, IllegalAccessException {
+    Injector injector = createNiceMock(Injector.class);
+    injector.injectMembers(anyObject(MaintenanceStateHelper.class));
+    EasyMock.expectLastCall().once();
+    replay(injector);
+
+    MaintenanceStateHelper maintenanceStateHelper = new MaintenanceStateHelper(injector);
+    injectField(maintenanceStateHelper, clusters);
+    return maintenanceStateHelper;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProviderTest.java
index 588932a..8453aad 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProviderTest.java
@@ -20,6 +20,7 @@ package org.apache.ambari.server.controller.internal;
 
 import junit.framework.Assert;
 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.spi.Predicate;
 import org.apache.ambari.server.controller.spi.Resource;
@@ -33,6 +34,7 @@ import java.util.Map;
 import java.util.Set;
 
 import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
 
@@ -56,13 +58,14 @@ public class AbstractControllerResourceProviderTest {
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
     
     ResourceProviderFactory factory = createMock(ResourceProviderFactory.class);
-    
-    ResourceProvider serviceResourceProvider = new ServiceResourceProvider(propertyIds, keyPropertyIds, managementController);
+
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
+    ResourceProvider serviceResourceProvider = new ServiceResourceProvider(propertyIds, keyPropertyIds, managementController, maintenanceStateHelper);
     expect(factory.getServiceResourceProvider(propertyIds, keyPropertyIds, managementController)).andReturn(serviceResourceProvider);
     
     AbstractControllerResourceProvider.init(factory);
     
-    replay(managementController, factory);
+    replay(managementController, factory, maintenanceStateHelper);
 
     AbstractResourceProvider provider =
         (AbstractResourceProvider) AbstractControllerResourceProvider.getResourceProvider(

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
index b3f40a5..0a56586 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AbstractResourceProviderTest.java
@@ -19,6 +19,8 @@
 package org.apache.ambari.server.controller.internal;
 
 import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.replay;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -32,6 +34,7 @@ import org.apache.ambari.server.controller.ClusterRequest;
 import org.apache.ambari.server.controller.ConfigurationRequest;
 import org.apache.ambari.server.controller.GroupRequest;
 import org.apache.ambari.server.controller.HostRequest;
+import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.MemberRequest;
 import org.apache.ambari.server.controller.RequestStatusResponse;
 import org.apache.ambari.server.controller.ServiceComponentHostRequest;
@@ -73,11 +76,12 @@ public class AbstractResourceProviderTest {
     Map<Resource.Type, String> keyPropertyIds = new HashMap<Resource.Type, String>();
 
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
-
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
+    replay(maintenanceStateHelper);
     AbstractResourceProvider provider = new ServiceResourceProvider(
             propertyIds,
             keyPropertyIds,
-            managementController);
+            managementController, maintenanceStateHelper);
 
     Set<String> unsupported = provider.checkPropertyIds(Collections.singleton("foo"));
     Assert.assertTrue(unsupported.isEmpty());
@@ -111,11 +115,13 @@ public class AbstractResourceProviderTest {
     Map<Resource.Type, String> keyPropertyIds = new HashMap<Resource.Type, String>();
 
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
+    replay(maintenanceStateHelper);
 
     AbstractResourceProvider provider = new ServiceResourceProvider(
             propertyIds,
             keyPropertyIds,
-            managementController);
+            managementController, maintenanceStateHelper);
 
     Set<String> supportedPropertyIds = provider.getPropertyIds();
     Assert.assertTrue(supportedPropertyIds.containsAll(propertyIds));
@@ -126,11 +132,13 @@ public class AbstractResourceProviderTest {
     Set<String> propertyIds = new HashSet<String>();
     Map<Resource.Type, String> keyPropertyIds = new HashMap<Resource.Type, String>();
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
+    replay(maintenanceStateHelper);
 
     AbstractResourceProvider provider = new ServiceResourceProvider(
             propertyIds,
             keyPropertyIds,
-            managementController);
+            managementController, maintenanceStateHelper);
 
     RequestStatus status = provider.getRequestStatus(null);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java
index c3e5a95..e068520 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ComponentResourceProviderTest.java
@@ -20,6 +20,8 @@ package org.apache.ambari.server.controller.internal;
 
 import static org.easymock.EasyMock.anyBoolean;
 import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMockBuilder;
+import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.createNiceMock;
@@ -32,6 +34,7 @@ import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -85,6 +88,7 @@ public class ComponentResourceProviderTest {
   public void testCreateResources() throws Exception {
     Resource.Type type = Resource.Type.Component;
 
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
     Clusters clusters = createNiceMock(Clusters.class);
     Cluster cluster = createNiceMock(Cluster.class);
@@ -118,7 +122,7 @@ public class ComponentResourceProviderTest {
 
     ResourceProvider provider = new ComponentResourceProvider(PropertyHelper.getPropertyIds(type),
         PropertyHelper.getKeyPropertyIds(type),
-        managementController);
+        managementController, maintenanceStateHelper);
 
     // add the property map to a set for the request.  add more maps for multiple creates
     Set<Map<String, Object>> propertySet = new LinkedHashSet<Map<String, Object>>();
@@ -147,6 +151,7 @@ public class ComponentResourceProviderTest {
   public void testGetResources() throws Exception {
     Resource.Type type = Resource.Type.Component;
 
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
     Clusters clusters = createNiceMock(Clusters.class);
     Cluster cluster = createNiceMock(Cluster.class);
@@ -196,7 +201,7 @@ public class ComponentResourceProviderTest {
     ResourceProvider provider = new ComponentResourceProvider(
         PropertyHelper.getPropertyIds(type),
         PropertyHelper.getKeyPropertyIds(type),
-        managementController);
+        managementController, maintenanceStateHelper);
 
     Set<String> propertyIds = new HashSet<String>();
 
@@ -242,6 +247,7 @@ public class ComponentResourceProviderTest {
   public void testUpdateResources() throws Exception {
     Resource.Type type = Resource.Type.Component;
 
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
     Clusters clusters = createNiceMock(Clusters.class);
     Cluster cluster = createNiceMock(Cluster.class);
@@ -296,6 +302,7 @@ public class ComponentResourceProviderTest {
     expect(serviceComponent2.getServiceComponentHosts()).andReturn(serviceComponentHosts).anyTimes();
     expect(serviceComponent3.getServiceComponentHosts()).andReturn(serviceComponentHosts).anyTimes();
 
+    expect(maintenanceStateHelper.isOperationAllowed(anyObject(Resource.Type.class), anyObject(Service.class))).andReturn(true).anyTimes();
 
     Capture<Map<String, String>> requestPropertiesCapture = new Capture<Map<String, String>>();
     Capture<Map<State, List<Service>>> changedServicesCapture = new Capture<Map<State, List<Service>>>();
@@ -317,12 +324,12 @@ public class ComponentResourceProviderTest {
     // replay
     replay(managementController, clusters, cluster, ambariMetaInfo, service,
         serviceComponent1, serviceComponent2, serviceComponent3, serviceComponentHost,
-        requestStatusResponse, stackId);
+        requestStatusResponse, stackId, maintenanceStateHelper);
 
     ResourceProvider provider = new ComponentResourceProvider(
         PropertyHelper.getPropertyIds(type),
         PropertyHelper.getKeyPropertyIds(type),
-        managementController);
+        managementController, maintenanceStateHelper);
 
     Map<String, Object> properties = new LinkedHashMap<String, Object>();
 
@@ -340,13 +347,14 @@ public class ComponentResourceProviderTest {
     // verify
     verify(managementController, clusters, cluster, ambariMetaInfo, service,
         serviceComponent1, serviceComponent2, serviceComponent3, serviceComponentHost,
-        requestStatusResponse, stackId);
+        requestStatusResponse, stackId, maintenanceStateHelper);
   }
 
   @Test
   public void testDeleteResources() throws Exception {
     Resource.Type type = Resource.Type.Component;
 
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
 
     // replay
@@ -355,7 +363,7 @@ public class ComponentResourceProviderTest {
     ResourceProvider provider = new ComponentResourceProvider(
         PropertyHelper.getPropertyIds(type),
         PropertyHelper.getKeyPropertyIds(type),
-        managementController);
+        managementController, maintenanceStateHelper);
 
     AbstractResourceProviderTest.TestObserver observer = new AbstractResourceProviderTest.TestObserver();
 
@@ -489,13 +497,20 @@ public class ComponentResourceProviderTest {
     verify(clusters, cluster, service, component1,  component2, response1, response2, ambariMetaInfo, stackId, managementController);
   }
 
-  public static ComponentResourceProvider getComponentResourceProvider(AmbariManagementController managementController) {
+  public static ComponentResourceProvider getComponentResourceProvider(AmbariManagementController managementController)
+          throws AmbariException {
     Resource.Type type = Resource.Type.Component;
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
+    expect(maintenanceStateHelper.isOperationAllowed(anyObject(Resource.Type.class),
+            anyObject(Service.class))).andReturn(true).anyTimes();
+    expect(maintenanceStateHelper.isOperationAllowed(anyObject(Resource.Type.class),
+            anyObject(ServiceComponentHost.class))).andReturn(true).anyTimes();
+    replay(maintenanceStateHelper);
 
     return new ComponentResourceProvider(
         PropertyHelper.getPropertyIds(type),
         PropertyHelper.getKeyPropertyIds(type),
-        managementController);
+        managementController, maintenanceStateHelper);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/JMXHostProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/JMXHostProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/JMXHostProviderTest.java
index bff767e..6e8cb9f 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/JMXHostProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/JMXHostProviderTest.java
@@ -28,6 +28,7 @@ import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.ClusterRequest;
 import org.apache.ambari.server.controller.ConfigurationRequest;
+import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.ServiceComponentHostRequest;
 import org.apache.ambari.server.controller.ServiceComponentRequest;
 import org.apache.ambari.server.controller.ServiceRequest;
@@ -54,6 +55,9 @@ import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
 
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.replay;
+
 public class JMXHostProviderTest {
   private Injector injector;
   private Clusters clusters;
@@ -381,9 +385,14 @@ public class JMXHostProviderTest {
       .Cluster), PropertyHelper.getKeyPropertyIds(Resource.Type.Cluster),
       controller);
 
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
+    {
+      replay(maintenanceStateHelper);
+    }
+
     ResourceProvider serviceResourceProvider = new ServiceResourceProvider(PropertyHelper
       .getPropertyIds(Resource.Type.Service),
-      PropertyHelper.getKeyPropertyIds(Resource.Type.Service), controller);
+      PropertyHelper.getKeyPropertyIds(Resource.Type.Service), controller, maintenanceStateHelper);
 
     ResourceProvider hostCompResourceProvider = new
       HostComponentResourceProvider(PropertyHelper.getPropertyIds(Resource

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestOperationLevelTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestOperationLevelTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestOperationLevelTest.java
index d832015..bd4ad90 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestOperationLevelTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestOperationLevelTest.java
@@ -18,9 +18,14 @@
 
 package org.apache.ambari.server.controller.internal;
 
-import junit.framework.TestCase;
+import org.junit.Assert;
 import org.junit.Test;
-import static junit.framework.TestCase.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.fail;
 
 public class RequestOperationLevelTest {
 
@@ -28,6 +33,58 @@ public class RequestOperationLevelTest {
   private final String hostComponent = "HostComponent";
 
   @Test
+  public void test_ConstructionFromRequestProperties() throws Exception {
+    String c1 = "c1";
+    String host_component = "HOST_COMPONENT";
+    String service_id = "HDFS";
+    String hostcomponent_id = "Namenode";
+    String host_id = "host1";
+
+    Map<String, String> requestInfoProperties = new HashMap<String, String>();
+    requestInfoProperties.put(RequestResourceProvider.COMMAND_ID, "RESTART");
+
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_LEVEL_ID,
+            host_component);
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_CLUSTER_ID, c1);
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_SERVICE_ID,
+            service_id);
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_HOSTCOMPONENT_ID,
+            hostcomponent_id);
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_HOST_ID,
+            host_id);
+
+    // Check normal creation
+    RequestOperationLevel opLevel = new RequestOperationLevel(requestInfoProperties);
+    assertEquals(opLevel.getLevel().toString(), "HostComponent");
+    assertEquals(opLevel.getClusterName(), c1);
+    assertEquals(opLevel.getServiceName(), service_id);
+    assertEquals(opLevel.getHostComponentName(), hostcomponent_id);
+    assertEquals(opLevel.getHostName(), host_id);
+
+
+    // Check exception wrong operation level is specified
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_LEVEL_ID,
+            "wrong_value");
+    try {
+      new RequestOperationLevel(requestInfoProperties);
+      Assert.fail("Should throw an exception");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_LEVEL_ID,
+            host_component);
+
+    // Check exception when cluster name is not specified
+    requestInfoProperties.remove(RequestOperationLevel.OPERATION_CLUSTER_ID);
+    try {
+      new RequestOperationLevel(requestInfoProperties);
+      Assert.fail("Should throw an exception");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+  }
+
+  @Test
   public void testGetInternalLevelName() throws Exception {
     String internal = RequestOperationLevel.getInternalLevelName(host_component);
     assertEquals(internal, hostComponent);

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
index f4bfef2..5c0d538 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/RequestResourceProviderTest.java
@@ -1011,14 +1011,14 @@ public class RequestResourceProviderTest {
     Map<String, String> requestInfoProperties = new HashMap<String, String>();
     requestInfoProperties.put(RequestResourceProvider.COMMAND_ID, "RESTART");
 
-    requestInfoProperties.put(RequestResourceProvider.OPERATION_LEVEL_ID,
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_LEVEL_ID,
             host_component);
-    requestInfoProperties.put(RequestResourceProvider.OPERATION_CLUSTER_ID, c1);
-    requestInfoProperties.put(RequestResourceProvider.OPERATION_SERVICE_ID,
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_CLUSTER_ID, c1);
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_SERVICE_ID,
             service_id);
-    requestInfoProperties.put(RequestResourceProvider.OPERATION_HOSTCOMPONENT_ID,
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_HOSTCOMPONENT_ID,
             hostcomponent_id);
-    requestInfoProperties.put(RequestResourceProvider.OPERATION_HOST_ID,
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_HOST_ID,
             host_id);
 
     Request request = PropertyHelper.getCreateRequest(propertySet, requestInfoProperties);
@@ -1028,27 +1028,7 @@ public class RequestResourceProviderTest {
             PropertyHelper.getKeyPropertyIds(type),
             managementController);
 
-    // Check exception wrong operation level is specified
-    requestInfoProperties.put(RequestResourceProvider.OPERATION_LEVEL_ID,
-            "wrong_value");
-    try {
-      provider.createResources(request);
-      Assert.fail("Should throw an exception");
-    } catch (UnsupportedOperationException e) {
-      // expected
-    }
-    requestInfoProperties.put(RequestResourceProvider.OPERATION_LEVEL_ID,
-            host_component);
-
-    // Check exception when cluster name is not specified
-    requestInfoProperties.remove(RequestResourceProvider.OPERATION_CLUSTER_ID);
-    try {
-      provider.createResources(request);
-      Assert.fail("Should throw an exception");
-    } catch (UnsupportedOperationException e) {
-      // expected
-    }
-    requestInfoProperties.put(RequestResourceProvider.OPERATION_CLUSTER_ID, c1);
+    requestInfoProperties.put(RequestOperationLevel.OPERATION_CLUSTER_ID, c1);
 
     // create request in a normal way (positive scenario)
     provider.createResources(request);

http://git-wip-us.apache.org/repos/asf/ambari/blob/30a41aca/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java
index 4f6c0c0..b46736d 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java
@@ -28,6 +28,7 @@ import static org.easymock.EasyMock.isNull;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 
+import java.lang.reflect.Field;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -41,6 +42,7 @@ import java.util.Set;
 import org.apache.ambari.server.AmbariException;
 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.ServiceComponentHostRequest;
 import org.apache.ambari.server.controller.ServiceComponentHostResponse;
@@ -251,6 +253,7 @@ public class ServiceResourceProviderTest {
 
   @Test
   public void testUpdateResources() throws Exception{
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
     Clusters clusters = createNiceMock(Clusters.class);
     Cluster cluster = createNiceMock(Cluster.class);
@@ -289,12 +292,13 @@ public class ServiceResourceProviderTest {
     )).andReturn(requestStages);
     requestStages.persist();
     expect(requestStages.getRequestStatusResponse()).andReturn(requestStatusResponse);
+    expect(maintenanceStateHelper.isOperationAllowed(anyObject(Resource.Type.class), anyObject(Service.class))).andReturn(true).anyTimes();
 
     // replay
-    replay(managementController, clusters, cluster,
+    replay(managementController, clusters, cluster, maintenanceStateHelper,
         service0, serviceFactory, ambariMetaInfo, requestStages, requestStatusResponse);
 
-    ResourceProvider provider = getServiceProvider(managementController);
+    ServiceResourceProvider provider = getServiceProvider(managementController, maintenanceStateHelper);
 
     // add the property map to a set for the request.
     Map<String, Object> properties = new LinkedHashMap<String, Object>();
@@ -310,12 +314,13 @@ public class ServiceResourceProviderTest {
     provider.updateResources(request, predicate);
 
     // verify
-    verify(managementController, clusters, cluster,
+    verify(managementController, clusters, cluster, maintenanceStateHelper,
         service0, serviceFactory, ambariMetaInfo, requestStages, requestStatusResponse);
   }
 
   @Test
   public void testReconfigureClientsFlag() throws Exception {
+    MaintenanceStateHelper maintenanceStateHelper = createNiceMock(MaintenanceStateHelper.class);
     AmbariManagementController managementController1 = createMock(AmbariManagementController.class);
     AmbariManagementController managementController2 = createMock
         (AmbariManagementController.class);
@@ -381,13 +386,15 @@ public class ServiceResourceProviderTest {
     requestStages2.persist();
     expect(requestStages2.getRequestStatusResponse()).andReturn(response2);
 
+    expect(maintenanceStateHelper.isOperationAllowed(anyObject(Resource.Type.class), anyObject(Service.class))).andReturn(true).anyTimes();
+
     // replay
     replay(managementController1, response1, managementController2, requestStages1, requestStages2, response2,
-        clusters, cluster, service0, serviceResponse0, ambariMetaInfo);
+        clusters, cluster, service0, serviceResponse0, ambariMetaInfo, maintenanceStateHelper);
 
-    ResourceProvider provider1 = getServiceProvider(managementController1);
+    ServiceResourceProvider provider1 = getServiceProvider(managementController1, maintenanceStateHelper);
 
-    ResourceProvider provider2 = getServiceProvider(managementController2);
+    ServiceResourceProvider provider2 = getServiceProvider(managementController2, maintenanceStateHelper);
 
     // add the property map to a set for the request.
     Map<String, Object> properties = new LinkedHashMap<String, Object>();
@@ -416,7 +423,7 @@ public class ServiceResourceProviderTest {
 
     // verify
     verify(managementController1, response1, managementController2, requestStages1, requestStages2, response2,
-        clusters, cluster, service0, serviceResponse0, ambariMetaInfo);
+        clusters, cluster, service0, serviceResponse0, ambariMetaInfo, maintenanceStateHelper);
   }
 
   @Test
@@ -559,11 +566,11 @@ public class ServiceResourceProviderTest {
     Map<Resource.Type, String> keyPropertyIds = new HashMap<Resource.Type, String>();
 
     AmbariManagementController managementController = createMock(AmbariManagementController.class);
-    
-    
+
+    MaintenanceStateHelper maintenanceStateHelperMock = createNiceMock(MaintenanceStateHelper.class);
     AbstractResourceProvider provider = new ServiceResourceProvider(propertyIds,
         keyPropertyIds,
-        managementController);
+        managementController, maintenanceStateHelperMock);
 
     Set<String> unsupported = provider.checkPropertyIds(Collections.singleton("foo"));
     Assert.assertTrue(unsupported.isEmpty());
@@ -1243,12 +1250,28 @@ public class ServiceResourceProviderTest {
     verify(managementController, clusters, cluster);
   }
 
-  
-  public static ServiceResourceProvider getServiceProvider(AmbariManagementController managementController) {
+
+  /**
+   * This factory method creates default MaintenanceStateHelper mock.
+   * It's useful in most cases (when we don't care about Maintenance State)
+   */
+  public static ServiceResourceProvider getServiceProvider(AmbariManagementController managementController) throws  AmbariException {
+    MaintenanceStateHelper maintenanceStateHelperMock = createNiceMock(MaintenanceStateHelper.class);
+    expect(maintenanceStateHelperMock.isOperationAllowed(anyObject(Resource.Type.class), anyObject(Service.class))).andReturn(true).anyTimes();
+    expect(maintenanceStateHelperMock.isOperationAllowed(anyObject(Resource.Type.class), anyObject(ServiceComponentHost.class))).andReturn(true).anyTimes();
+    replay(maintenanceStateHelperMock);
+    return getServiceProvider(managementController, maintenanceStateHelperMock);
+  }
+
+  /**
+   * This factory method allows to define custom MaintenanceStateHelper mock.
+   */
+  public static ServiceResourceProvider getServiceProvider(AmbariManagementController managementController,
+                                                           MaintenanceStateHelper maintenanceStateHelper) {
     Resource.Type type = Resource.Type.Service;
     return new ServiceResourceProvider(PropertyHelper.getPropertyIds(type),
             PropertyHelper.getKeyPropertyIds(type),
-            managementController);
+            managementController, maintenanceStateHelper);
   }
 
   public static void createServices(AmbariManagementController controller, Set<ServiceRequest> requests) throws AmbariException {
@@ -1267,13 +1290,33 @@ public class ServiceResourceProviderTest {
                                                      Map<String, String> requestProperties, boolean runSmokeTest,
                                                      boolean reconfigureClients) throws AmbariException
   {
-    ServiceResourceProvider provider = getServiceProvider(controller);
+    return updateServices(controller, requests, requestProperties, runSmokeTest, reconfigureClients, null);
+  }
+
+  /**
+   * Allows to set maintenanceStateHelper. For use when there is anything to test
+   * with maintenance mode.
+   */
+  public static RequestStatusResponse updateServices(AmbariManagementController controller,
+                                                     Set<ServiceRequest> requests,
+                                                     Map<String, String> requestProperties, boolean runSmokeTest,
+                                                     boolean reconfigureClients,
+                                                     MaintenanceStateHelper maintenanceStateHelper) throws AmbariException
+  {
+    ServiceResourceProvider provider;
+    if (maintenanceStateHelper != null) {
+      provider = getServiceProvider(controller, maintenanceStateHelper);
+    } else {
+      provider = getServiceProvider(controller);
+    }
 
     RequestStageContainer request = provider.updateServices(null, requests, requestProperties, runSmokeTest, reconfigureClients);
     request.persist();
     return request.getRequestStatusResponse();
   }
 
+
+
   public static RequestStatusResponse deleteServices(AmbariManagementController controller, Set<ServiceRequest> requests)
       throws AmbariException {
     ServiceResourceProvider provider = getServiceProvider(controller);


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

Posted by dm...@apache.org.
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);
     
   }