Pārlūkot izejas kodu

AMBARI-5234. Add new Maintenance States to support different operation levels. (swagle)

Siddharth Wagle 11 gadi atpakaļ
vecāks
revīzija
1d1ac32253

+ 3 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariActionExecutionHelper.java

@@ -74,6 +74,8 @@ public class AmbariActionExecutionHelper {
   private ActionManager actionManager;
   @Inject
   private AmbariMetaInfo ambariMetaInfo;
+  @Inject
+  private MaintenanceStateHelper maintenanceStateHelper;
 
   /**
    * Validates the request to execute an action.
@@ -294,7 +296,7 @@ public class AmbariActionExecutionHelper {
     }
 
     Set<Map<String, String>> maintenanceSCHs =
-      MaintenanceStateHelper.getMaintenanceHostComponents(clusters, cluster);
+      maintenanceStateHelper.getMaintenanceHostComponents(clusters, cluster);
 
     //create tasks for each host
     for (String hostName : targetHosts) {

+ 3 - 1
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelper.java

@@ -112,6 +112,8 @@ public class AmbariCustomCommandExecutionHelper {
   private AmbariMetaInfo ambariMetaInfo;
   @Inject
   private ConfigHelper configHelper;
+  @Inject
+  private MaintenanceStateHelper maintenanceStateHelper;
 
   protected static final String SERVICE_CHECK_COMMAND_NAME = "SERVICE_CHECK";
   protected static final String DECOMMISSION_COMMAND_NAME = "DECOMMISSION";
@@ -306,7 +308,7 @@ public class AmbariCustomCommandExecutionHelper {
       // if the target is NAGIOS (for example: restart command), make passive info always available
       if (execCmd.getRole().equals(Role.NAGIOS_SERVER.name())) {
         execCmd.setPassiveInfo(
-          MaintenanceStateHelper.getMaintenanceHostComponents(clusters, cluster));
+          maintenanceStateHelper.getMaintenanceHostComponents(clusters, cluster));
       }
       
     }

+ 6 - 6
ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java

@@ -1314,7 +1314,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     // Send passive host info to the Nagios host role
     if (execCmd.getRole().equals(Role.NAGIOS_SERVER.name())) {
       execCmd.setPassiveInfo(
-        MaintenanceStateHelper.getMaintenanceHostComponents(clusters, cluster));
+        maintenanceStateHelper.getMaintenanceHostComponents(clusters, cluster));
     }
   }
 
@@ -1777,7 +1777,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
           if (sc.isClientComponent()) {
             throw new IllegalArgumentException("Invalid arguments, cannot set " +
               "maintenance state on a client component");
-          } else if (newMaint.equals(MaintenanceState.IMPLIED)) {
+          } else if (newMaint.equals(MaintenanceState.IMPLIED_FROM_HOST)
+              || newMaint.equals(MaintenanceState.IMPLIED_FROM_SERVICE)) {
             throw new IllegalArgumentException("Invalid arguments, can only set " +
               "maintenance state to one of " + EnumSet.of(MaintenanceState.OFF, MaintenanceState.ON));
           } else {
@@ -1909,8 +1910,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
     
     if (maintenanceClusters.size() > 0) {
       try {
-        MaintenanceStateHelper.createRequests(this, requestProperties,
-            maintenanceClusters);
+        maintenanceStateHelper.createRequests(this, requestProperties, maintenanceClusters);
       } catch (Exception e) {
         LOG.warn("Could not send maintenance status to Nagios (" + e.getMessage() + ")");
       }
@@ -1918,8 +1918,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
 
     Cluster cluster = clusters.getCluster(clusterNames.iterator().next());
 
-    return createAndPersistStages(cluster, requestProperties, null, null, null, changedScHosts, ignoredScHosts, runSmokeTest,
-        false);
+    return createAndPersistStages(cluster, requestProperties, null, null, null,
+      changedScHosts, ignoredScHosts, runSmokeTest, false);
   }
 
   private void validateServiceComponentHostRequest(ServiceComponentHostRequest request) {

+ 82 - 16
ambari-server/src/main/java/org/apache/ambari/server/controller/MaintenanceStateHelper.java

@@ -17,17 +17,17 @@
  */
 package org.apache.ambari.server.controller;
 
-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 com.google.inject.Singleton;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.HostNotFoundException;
-import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.controller.internal.RequestResourceFilter;
+import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Host;
@@ -37,14 +37,18 @@ import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Used to help manage maintenance state checks.
  */
+@Singleton
 public class MaintenanceStateHelper {
   private static final String NAGIOS_SERVICE = "NAGIOS";
   private static final String NAGIOS_COMPONENT = "NAGIOS_SERVER";
   private static final String NAGIOS_ACTION_NAME = "nagios_update_ignore";
+  private static final Logger LOG = LoggerFactory.getLogger(MaintenanceStateHelper.class);
   
   @Inject
   private Clusters clusters;
@@ -97,16 +101,30 @@ public class MaintenanceStateHelper {
    * @param sch the host component
    * @return the effective maintenance state
    */
-  private static MaintenanceState getEffectiveState(long clusterId, Service service,
-      Host host, ServiceComponentHost sch) {
-    if (MaintenanceState.ON == sch.getMaintenanceState())
+  private MaintenanceState getEffectiveState(long clusterId,
+      Service service, Host host, ServiceComponentHost sch) {
+
+    MaintenanceState schState = sch.getMaintenanceState();
+    if (MaintenanceState.ON == schState) {
       return MaintenanceState.ON;
+    }
 
-    if (MaintenanceState.OFF != service.getMaintenanceState() ||
-        MaintenanceState.OFF != host.getMaintenanceState(clusterId))
-      return MaintenanceState.IMPLIED;
+    MaintenanceState serviceState = service.getMaintenanceState();
+    MaintenanceState hostState = host.getMaintenanceState(clusterId);
+
+    if (MaintenanceState.OFF != serviceState && MaintenanceState.OFF != hostState) {
+      return MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST;
+    }
+
+    if (MaintenanceState.OFF != serviceState) {
+      return MaintenanceState.IMPLIED_FROM_SERVICE;
+    }
+
+    if (MaintenanceState.OFF != hostState) {
+      return MaintenanceState.IMPLIED_FROM_HOST;
+    }
     
-    return sch.getMaintenanceState();
+    return schState;
   }
 
   /**
@@ -114,9 +132,11 @@ public class MaintenanceStateHelper {
    * @param cluster the specific cluster to check
    * @return a property map of all host components that are in a
    * maintenance state (either {@link MaintenanceState#ON} or
-   * {@link MaintenanceState#IMPLIED})
+   * {@link MaintenanceState#IMPLIED_FROM_HOST} or
+   * {@link MaintenanceState#IMPLIED_FROM_SERVICE} or
+   * {@link MaintenanceState#IMPLIED_FROM_SERVICE_AND_HOST})
    */
-  public static 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>>();
 
@@ -153,7 +173,7 @@ public class MaintenanceStateHelper {
    * @return the response
    * @throws AmbariException
    */
-  public static RequestStatusResponse createRequests(AmbariManagementController amc,
+  public RequestStatusResponse createRequests(AmbariManagementController amc,
       Map<String, String> requestProperties, Set<String> clusterNames) throws AmbariException {
     
     Map<String, String> params = new HashMap<String, String>();
@@ -169,10 +189,56 @@ public class MaintenanceStateHelper {
         clusterName, null, NAGIOS_ACTION_NAME,
         Collections.singletonList(resourceFilter), params);
       
-      if (null == response)
+      if (null == response) {
         response = amc.createAction(actionRequest, requestProperties);
+      }
     }    
     return response;
-  }  
-  
+  }
+
+  /**
+   * Determine based on the requesting Resource level and the state of the
+   * operand whether to allow operations on it.
+   *
+   * @param sourceType Request Source: {CLUSTER, SERVICE, HOSTCOMPONENT, HOST}
+   * @param sch HostComponent which is the operand of the operation
+   * @return
+   * @throws AmbariException
+   */
+  public boolean isOperationAllowed(Resource.Type sourceType,
+                                    ServiceComponentHost sch) throws AmbariException {
+    MaintenanceState maintenanceState = sch.getMaintenanceState();
+
+    if (sourceType.equals(Resource.Type.Cluster)) {
+
+      if (maintenanceState.equals(MaintenanceState.OFF)) {
+        return true;
+      }
+
+    } else if (sourceType.equals(Resource.Type.Service)) {
+
+      if (maintenanceState.equals(MaintenanceState.IMPLIED_FROM_SERVICE)
+          || maintenanceState.equals(MaintenanceState.OFF)) {
+        return true;
+      }
+
+    } else if (sourceType.equals(Resource.Type.Host)) {
+
+      if (maintenanceState.equals(MaintenanceState.IMPLIED_FROM_HOST)
+          || maintenanceState.equals(MaintenanceState.OFF)) {
+        return true;
+      }
+
+    } else if (sourceType.equals(Resource.Type.HostComponent)) {
+
+      return true;
+
+    } else {
+      LOG.warn("Unsupported Resource type, type = " + sourceType);
+    }
+
+    return false;
+  }
+
+
 }

+ 7 - 3
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java

@@ -27,6 +27,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.inject.Inject;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.DuplicateResourceException;
@@ -117,6 +118,9 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
       new HashSet<String>(Arrays.asList(new String[]{
           HOST_NAME_PROPERTY_ID}));
 
+  @Inject
+  private MaintenanceStateHelper maintenanceStateHelper;
+
   // ----- Constructors ----------------------------------------------------
 
   /**
@@ -572,7 +576,8 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
         MaintenanceState newState = MaintenanceState.valueOf(request.getMaintenanceState());
         MaintenanceState oldState = h.getMaintenanceState(c.getClusterId());
         if (!newState.equals(oldState)) {
-          if (newState.equals(MaintenanceState.IMPLIED)) {
+          if (newState.equals(MaintenanceState.IMPLIED_FROM_HOST)
+              || newState.equals(MaintenanceState.IMPLIED_FROM_SERVICE)) {
             throw new IllegalArgumentException("Invalid arguments, can only set " +
               "maintenance state to one of " + EnumSet.of(MaintenanceState.OFF, MaintenanceState.ON));
           } else {
@@ -624,8 +629,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider {
     
     if (maintenanceClusters.size() > 0) {
       try {
-        MaintenanceStateHelper.createRequests(controller, requestProperties,
-            maintenanceClusters);
+        maintenanceStateHelper.createRequests(controller, requestProperties, maintenanceClusters);
       } catch (Exception e) {
         LOG.warn("Could not send maintenance status to Nagios (" + e.getMessage() + ")");
       }

+ 9 - 5
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java

@@ -29,6 +29,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.inject.Inject;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ClusterNotFoundException;
 import org.apache.ambari.server.DuplicateResourceException;
@@ -107,6 +108,8 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
 
   private static final ServiceState DEFAULT_SERVICE_STATE = new DefaultServiceState();
 
+  @Inject
+  private MaintenanceStateHelper maintenanceStateHelper;
 
   // ----- Constructors ----------------------------------------------------
 
@@ -615,7 +618,8 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
       if (null != request.getMaintenanceState()) {
         MaintenanceState newMaint = MaintenanceState.valueOf(request.getMaintenanceState());
         if (newMaint  != s.getMaintenanceState()) {
-          if (newMaint.equals(MaintenanceState.IMPLIED)) {
+          if (newMaint.equals(MaintenanceState.IMPLIED_FROM_HOST)
+              || newMaint.equals(MaintenanceState.IMPLIED_FROM_SERVICE)) {
             throw new IllegalArgumentException("Invalid arguments, can only set " +
               "maintenance state to one of " + EnumSet.of(MaintenanceState.OFF, MaintenanceState.ON));
           } else {
@@ -741,7 +745,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
           }
           Host host = clusters.getHost(sch.getHostName());
 
-          if (schMaint == MaintenanceState.IMPLIED
+          if (schMaint == MaintenanceState.IMPLIED_FROM_HOST
              && host != null
              && host.getMaintenanceState(cluster.getClusterId()) != MaintenanceState.OFF) {
 
@@ -816,8 +820,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
     
     if (maintenanceClusters.size() > 0) {
       try {
-        MaintenanceStateHelper.createRequests(controller, requestProperties,
-            maintenanceClusters);
+        maintenanceStateHelper.createRequests(controller, requestProperties, maintenanceClusters);
       } catch (Exception e) {
         LOG.warn("Could not send maintenance state to Nagios (" + e.getMessage() + ")");
       }
@@ -825,7 +828,8 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
 
     Cluster cluster = clusters.getCluster(clusterNames.iterator().next());
 
-    return controller.addStages(requestStages, cluster, requestProperties, null, changedServices, changedComps, changedScHosts,
+    return controller.addStages(requestStages, cluster, requestProperties,
+      null, changedServices, changedComps, changedScHosts,
         ignoredScHosts, runSmokeTest, reconfigureClients);
   }
 

+ 11 - 3
ambari-server/src/main/java/org/apache/ambari/server/state/MaintenanceState.java

@@ -18,7 +18,7 @@
 package org.apache.ambari.server.state;
 
 /**
- * Indicates when a Service or Host participates in automated opererations, and
+ * Indicates when a Service or Host participates in automated operations, and
  * if alerts are enabled.
  */
 public enum MaintenanceState {
@@ -31,7 +31,15 @@ public enum MaintenanceState {
    */
   ON,
   /**
-   * Target is in maintenance, implied by a parent target.
+   * Target is in maintenance, implied by parent service.
    */
-  IMPLIED
+  IMPLIED_FROM_SERVICE,
+  /**
+   * Target is in maintenance, implied by parent host.
+   */
+  IMPLIED_FROM_HOST,
+  /**
+   * Target is in maintenance, implied by parent service and host.
+   */
+  IMPLIED_FROM_SERVICE_AND_HOST
 }

+ 1 - 1
ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java

@@ -1295,7 +1295,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
   
   @Override
   public void updateActualConfigs(Map<String, Map<String, String>> configTags) {
-    Map<Long, ConfigGroup> configGroupMap = null;
+    Map<Long, ConfigGroup> configGroupMap;
     String clusterName = getClusterName();
     try {
       Cluster cluster = clusters.getCluster(clusterName);

+ 6 - 4
ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariManagementControllerTest.java

@@ -9677,7 +9677,7 @@ public class AmbariManagementControllerTest {
     // check the host components implied state vs desired state
     for (ServiceComponent sc : service.getServiceComponents().values()) {
       for (ServiceComponentHost sch : sc.getServiceComponentHosts().values()) {
-        Assert.assertEquals(MaintenanceState.IMPLIED,
+        Assert.assertEquals(MaintenanceState.IMPLIED_FROM_SERVICE,
             controller.getEffectiveMaintenanceState(sch));
         Assert.assertEquals(MaintenanceState.OFF, sch.getMaintenanceState());
       }
@@ -9712,7 +9712,7 @@ public class AmbariManagementControllerTest {
       for (ServiceComponentHost sch : sc.getServiceComponentHosts().values()) {
         MaintenanceState implied = controller.getEffectiveMaintenanceState(sch);
         if (sch.getHostName().equals(host1)) {
-          Assert.assertEquals(MaintenanceState.IMPLIED, implied);
+          Assert.assertEquals(MaintenanceState.IMPLIED_FROM_HOST, implied);
         } else {
           Assert.assertEquals(MaintenanceState.OFF, implied);
         }
@@ -9783,7 +9783,8 @@ public class AmbariManagementControllerTest {
     
     // make SCH active
     targetSch.setMaintenanceState(MaintenanceState.OFF);
-    Assert.assertEquals(MaintenanceState.IMPLIED, controller.getEffectiveMaintenanceState(targetSch));
+    Assert.assertEquals(MaintenanceState.IMPLIED_FROM_SERVICE,
+      controller.getEffectiveMaintenanceState(targetSch));
     
     // update the service
     service.setMaintenanceState(MaintenanceState.OFF);
@@ -9792,7 +9793,8 @@ public class AmbariManagementControllerTest {
     host = hosts.get(host2);
     // update host
     host.setMaintenanceState(cluster.getClusterId(), MaintenanceState.ON);
-    Assert.assertEquals(MaintenanceState.IMPLIED, controller.getEffectiveMaintenanceState(targetSch));
+    Assert.assertEquals(MaintenanceState.IMPLIED_FROM_HOST,
+      controller.getEffectiveMaintenanceState(targetSch));
     
     targetSch.setMaintenanceState(MaintenanceState.ON);
     Assert.assertEquals(MaintenanceState.ON, controller.getEffectiveMaintenanceState(targetSch));

+ 154 - 12
ambari-server/src/test/java/org/apache/ambari/server/controller/MaintenanceStateHelperTest.java

@@ -19,16 +19,23 @@ 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.controller.internal.RequestResourceFilter;
+import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Host;
@@ -68,6 +75,9 @@ public class MaintenanceStateHelperTest {
     Capture<ExecuteActionRequest> earCapture = new Capture<ExecuteActionRequest>();
     Capture<Map<String, String>> rpCapture = new Capture<Map<String, String>>();
     expect(amc.createAction(capture(earCapture), capture(rpCapture))).andReturn(null);
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper = createMockBuilder
+      (MaintenanceStateHelper.class).withConstructor(injector).createMock();
     
     Clusters clusters = createMock(Clusters.class);
     Cluster cluster = createMock(Cluster.class);
@@ -83,12 +93,11 @@ public class MaintenanceStateHelperTest {
     expect(sch.getServiceComponentName()).andReturn("NAMENODE").anyTimes();
     expect(sch.getHostName()).andReturn("h1");
     
-    replay(amc, clusters, cluster, sch);
+    replay(amc, clusters, cluster, sch, maintenanceStateHelper);
     
     Map<String, String> map = new HashMap<String, String>();
     map.put("context", "abc");
-    MaintenanceStateHelper.createRequests(amc, map,
-        Collections.singleton(sch.getClusterName()));
+    maintenanceStateHelper.createRequests(amc, map, Collections.singleton(sch.getClusterName()));
     
     ExecuteActionRequest ear = earCapture.getValue();
     map = rpCapture.getValue();
@@ -103,12 +112,15 @@ public class MaintenanceStateHelperTest {
     Assert.assertEquals("c1", ear.getClusterName());
     Assert.assertTrue(map.containsKey("context"));  
   }
-  
+
   private void testHost(MaintenanceState state) throws Exception {
     AmbariManagementController amc = createMock(AmbariManagementController.class);
     Capture<ExecuteActionRequest> earCapture = new Capture<ExecuteActionRequest>();
     Capture<Map<String, String>> rpCapture = new Capture<Map<String, String>>();
     expect(amc.createAction(capture(earCapture), capture(rpCapture))).andReturn(null);
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper = createMockBuilder
+      (MaintenanceStateHelper.class).withConstructor(injector).createMock();
 
     Clusters clusters = createMock(Clusters.class);
     Cluster cluster = createMock(Cluster.class);
@@ -140,12 +152,11 @@ public class MaintenanceStateHelperTest {
     expect(host.getHostName()).andReturn("h1").anyTimes();
     expect(host.getMaintenanceState(1L)).andReturn(state);
     
-    replay(amc, clusters, cluster, service, sch1, host);
+    replay(amc, clusters, cluster, service, sch1, host, maintenanceStateHelper);
     
     Map<String, String> map = new HashMap<String, String>();
     map.put("context", "abc");
-    MaintenanceStateHelper.createRequests(amc, map,
-        Collections.singleton(cluster.getClusterName()));
+    maintenanceStateHelper.createRequests(amc, map, Collections.singleton(cluster.getClusterName()));
     
     ExecuteActionRequest ear = earCapture.getValue();
     rpCapture.getValue();
@@ -160,12 +171,14 @@ public class MaintenanceStateHelperTest {
     Assert.assertTrue(map.containsKey("context"));    
   }
   
-  
   private void testService(MaintenanceState state) throws Exception {
     AmbariManagementController amc = createMock(AmbariManagementController.class);
     Capture<ExecuteActionRequest> earCapture = new Capture<ExecuteActionRequest>();
     Capture<Map<String, String>> rpCapture = new Capture<Map<String, String>>();
     expect(amc.createAction(capture(earCapture), capture(rpCapture))).andReturn(null);
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper = createMockBuilder
+      (MaintenanceStateHelper.class).withConstructor(injector).createMock();
     
     Clusters clusters = createMock(Clusters.class);
     Cluster cluster = createMock(Cluster.class);
@@ -198,12 +211,11 @@ public class MaintenanceStateHelperTest {
     expect(service.getMaintenanceState()).andReturn(state);
     expect(service.getName()).andReturn("HDFS");
     
-    replay(amc, clusters, cluster, service, sc1, sc2, sch1);
+    replay(amc, clusters, cluster, service, sc1, sc2, sch1, maintenanceStateHelper);
     
     Map<String, String> map = new HashMap<String, String>();
     map.put("context", "abc");
-    MaintenanceStateHelper.createRequests(amc, map,
-        Collections.singleton("c1"));
+    maintenanceStateHelper.createRequests(amc, map, Collections.singleton("c1"));
     
     ExecuteActionRequest ear = earCapture.getValue();
     map = rpCapture.getValue();
@@ -217,5 +229,135 @@ public class MaintenanceStateHelperTest {
     Assert.assertEquals("c1", ear.getClusterName());
     Assert.assertTrue(map.containsKey("context"));
   }
-  
+
+  @Test
+  public void testHostComponentImpliedState() throws Exception {
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper =
+      createMockBuilder(MaintenanceStateHelper.class)
+        .withConstructor(injector)
+        .createNiceMock();
+
+    Clusters clusters = createMock(Clusters.class);
+    Cluster cluster = createMock(Cluster.class);
+    ServiceComponentHost sch = createMock(ServiceComponentHost.class);
+    Service service = createNiceMock(Service.class);
+    final Host host = createNiceMock(Host.class);
+
+    expect(sch.getClusterName()).andReturn("c1").anyTimes();
+    expect(clusters.getCluster("c1")).andReturn(cluster).anyTimes();
+    expect(cluster.getClusterName()).andReturn("c1").anyTimes();
+    expect(cluster.getClusterId()).andReturn(1L).anyTimes();
+    expect(clusters.getHostsForCluster("c1")).andReturn(
+      new HashMap<String, Host>() {{
+        put("h1", host);
+      }}
+    ).anyTimes();
+    expect(sch.getHostName()).andReturn("h1").anyTimes();
+    expect(sch.getServiceName()).andReturn("HDFS").anyTimes();
+    expect(cluster.getService("HDFS")).andReturn(service).anyTimes();
+
+    expect(sch.getMaintenanceState())
+      .andReturn(MaintenanceState.ON).times(1)
+      .andReturn(MaintenanceState.OFF).anyTimes();
+    expect(service.getMaintenanceState()).andReturn(MaintenanceState.ON);
+    expect(host.getMaintenanceState(1L)).andReturn(MaintenanceState.ON);
+    expect(service.getMaintenanceState()).andReturn(MaintenanceState.ON);
+    expect(host.getMaintenanceState(1L)).andReturn(MaintenanceState.OFF);
+    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);
+
+    replay(maintenanceStateHelper, clusters, cluster, sch, host, service);
+
+    MaintenanceState state = maintenanceStateHelper.getEffectiveState(sch);
+    Assert.assertEquals(MaintenanceState.ON, state);
+
+    state = maintenanceStateHelper.getEffectiveState(sch);
+    Assert.assertEquals(MaintenanceState.IMPLIED_FROM_SERVICE_AND_HOST, state);
+
+    state = maintenanceStateHelper.getEffectiveState(sch);
+    Assert.assertEquals(MaintenanceState.IMPLIED_FROM_SERVICE, state);
+
+    state = maintenanceStateHelper.getEffectiveState(sch);
+    Assert.assertEquals(MaintenanceState.IMPLIED_FROM_HOST, state);
+
+    verify(maintenanceStateHelper, clusters, cluster, sch, host, service);
+  }
+
+  @Test
+  public void testHostComponentOperationsAllowance() throws Exception {
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper =
+      createMockBuilder(MaintenanceStateHelper.class)
+        .withConstructor(injector)
+        .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);
+
+    // 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);
+
+    // 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);
+
+    // 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);
+
+
+    replay(maintenanceStateHelper, sch);
+
+    // Cluster
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, sch));
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, sch));
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, sch));
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, sch));
+
+    // Service
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Service, sch));
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Service, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Service, sch));
+    Assert.assertEquals(false , maintenanceStateHelper.isOperationAllowed(Resource.Type.Service, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Service, sch));
+
+    // Host
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Host, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Host, sch));
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Host, sch));
+    Assert.assertEquals(false, maintenanceStateHelper.isOperationAllowed(Resource.Type.Host, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.Host, sch));
+
+    // HostComponent
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.HostComponent, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.HostComponent, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.HostComponent, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.HostComponent, sch));
+    Assert.assertEquals(true, maintenanceStateHelper.isOperationAllowed(Resource.Type.HostComponent, sch));
+
+    verify(maintenanceStateHelper, sch);
+  }
 }