ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jonathanhur...@apache.org
Subject ambari git commit: AMBARI-14191 - Hosts In Maintenance Mode Should Be Excluded From Service Check Candidates During Upgrades (jonathanhurley)
Date Fri, 04 Dec 2015 04:52:46 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.2 0c4282b65 -> 4518c9c08


AMBARI-14191 - Hosts In Maintenance Mode Should Be Excluded From Service Check Candidates
During Upgrades (jonathanhurley)


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

Branch: refs/heads/branch-2.2
Commit: 4518c9c08b5700d5f67ac63d79d63b5ca0e040aa
Parents: 0c4282b
Author: Jonathan Hurley <jhurley@hortonworks.com>
Authored: Thu Dec 3 14:19:36 2015 -0500
Committer: Jonathan Hurley <jhurley@hortonworks.com>
Committed: Thu Dec 3 23:50:21 2015 -0500

----------------------------------------------------------------------
 .../controller/ActionExecutionContext.java      |   4 +-
 .../AmbariCustomCommandExecutionHelper.java     |  63 ++--
 .../internal/UpgradeResourceProvider.java       |  62 ++--
 .../AmbariCustomCommandExecutionHelperTest.java | 328 +++++++++++--------
 4 files changed, 264 insertions(+), 193 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/4518c9c0/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
b/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
index dc88a5f..923fd92 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ActionExecutionContext.java
@@ -188,14 +188,14 @@ public class ActionExecutionContext {
    * @return {@code true} if the action context should schedule even if maintenance mode
is
    * enabled
    */
-  public boolean isIgnoreMaintenance() {
+  public boolean isMaintenanceModeIgnored() {
     return ignoreMaintenance;
   }
 
   /**
    * @param ignore  {@code true} to ignore maintenace mode
    */
-  public void setIgnoreMaintenance(boolean ignore) {
+  public void setMaintenanceModeIgnored(boolean ignore) {
     ignoreMaintenance = ignore;
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4518c9c0/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 c515e46..2d3065c 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
@@ -42,6 +42,7 @@ import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_NAM
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.STACK_VERSION;
 import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.USER_LIST;
 
+import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -243,7 +244,9 @@ public class AmbariCustomCommandExecutionHelper {
     String clusterName = stage.getClusterName();
     final Cluster cluster = clusters.getCluster(clusterName);
 
+    // start with all hosts
     Set<String> candidateHosts = new HashSet<String>(resourceFilter.getHostNames());
+
     // Filter hosts that are in MS
     Set<String> ignoredHosts = maintenanceStateHelper.filterHostsInMaintenanceState(
         candidateHosts, new MaintenanceStateHelper.HostPredicate() {
@@ -258,20 +261,28 @@ public class AmbariCustomCommandExecutionHelper {
     );
 
     // Filter unhealthy hosts
-    Set<String> filteredHosts = filterUnhealthHosts(candidateHosts, actionExecutionContext,
resourceFilter);
+    Set<String> unhealthyHosts = getUnhealthyHosts(candidateHosts, actionExecutionContext,
resourceFilter);
 
+    // log excluded hosts
     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);
-    } else if (!filteredHosts.isEmpty()) {
-      String message = String.format("Some hosts (%s) have been ignored " +
-            "because they are in unknown state",
-         filteredHosts);
-      LOG.warn(message);
+      if( LOG.isDebugEnabled() ){
+        LOG.debug(
+            "While building the {} custom command for {}/{}, the following hosts were excluded:
unhealthy[{}], maintenance[{}]",
+            commandName, serviceName, componentName, StringUtils.join(unhealthyHosts, ','),
+            StringUtils.join(ignoredHosts, ','));
+      }
+    } else if (!unhealthyHosts.isEmpty()) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug(
+            "While building the {} custom command for {}/{}, the following hosts were excluded:
unhealthy[{}], maintenance[{}]",
+            commandName, serviceName, componentName, StringUtils.join(unhealthyHosts, ','),
+            StringUtils.join(ignoredHosts, ','));
+      }
     } else if (candidateHosts.isEmpty()) {
-      String message = "Invalid request : No hosts specified.";
+      String message = MessageFormat.format(
+          "While building the {0} custom command for {1}/{2}, there were no healthy eligible
hosts",
+          commandName, serviceName, componentName);
+
       throw new AmbariException(message);
     }
 
@@ -432,9 +443,11 @@ public class AmbariCustomCommandExecutionHelper {
     if (null == smokeTestRole) {
       smokeTestRole = actionExecutionContext.getActionName();
     }
+
     long nowTimestamp = System.currentTimeMillis();
     Map<String, String> actionParameters = actionExecutionContext.getParameters();
     final Set<String> candidateHosts;
+
     if (componentName != null) {
       Map<String, ServiceComponentHost> components =
         cluster.getService(serviceName)
@@ -444,6 +457,7 @@ public class AmbariCustomCommandExecutionHelper {
             + componentName + ", service = " + serviceName
             + ", cluster = " + clusterName);
       }
+
       List<String> candidateHostsList = resourceFilter.getHostNames();
       if (candidateHostsList != null && !candidateHostsList.isEmpty()) {
         candidateHosts = new HashSet<String>(candidateHostsList);
@@ -453,10 +467,12 @@ public class AmbariCustomCommandExecutionHelper {
     } 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();
       if (serviceComponent.getServiceComponentHosts().isEmpty()) {
         throw new AmbariException("Hosts not found, component="
@@ -466,15 +482,13 @@ public class AmbariCustomCommandExecutionHelper {
       candidateHosts = serviceComponent.getServiceComponentHosts().keySet();
     }
 
-    // Filter hosts that are in MS
+    // filter out hosts that are in maintenance mode
     Set<String> ignoredHosts = new HashSet<String>();
-
-    if (!actionExecutionContext.isIgnoreMaintenance()) {
+    if (!actionExecutionContext.isMaintenanceModeIgnored()) {
       ignoredHosts.addAll(maintenanceStateHelper.filterHostsInMaintenanceState(
         candidateHosts, new MaintenanceStateHelper.HostPredicate() {
           @Override
-          public boolean shouldHostBeRemoved(final String hostname)
-                  throws AmbariException {
+            public boolean shouldHostBeRemoved(final String hostname) throws AmbariException
{
             return !maintenanceStateHelper.isOperationAllowed(
                     cluster, actionExecutionContext.getOperationLevel(),
                     resourceFilter, serviceName, componentName, hostname);
@@ -483,15 +497,15 @@ public class AmbariCustomCommandExecutionHelper {
       ));
     }
 
+    // pick a random healthy host from the remaining set, throwing an exception
+    // if there are none to choose from
     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);
+      String message = MessageFormat.format(
+          "While building a service check command for {0}, there were no healthy eligible
hosts: unhealthy[{1}], maintenance[{2}]",
+          serviceName, StringUtils.join(candidateHosts, ','), StringUtils.join(ignoredHosts,
','));
+
+      throw new AmbariException(message);
     }
 
     addServiceCheckAction(stage, hostName, smokeTestRole, nowTimestamp, serviceName, componentName,
@@ -550,7 +564,6 @@ public class AmbariCustomCommandExecutionHelper {
         StageUtils.getClusterHostInfo(cluster));
 
     Map<String, String> commandParams = new TreeMap<String, String>();
-
     String commandTimeout = configs.getDefaultAgentTaskTimeout(false);
 
 
@@ -1196,7 +1209,7 @@ public class AmbariCustomCommandExecutionHelper {
    * @return Set of excluded hosts
    * @throws AmbariException
    */
-  private Set<String> filterUnhealthHosts(Set<String> hosts,
+  private Set<String> getUnhealthyHosts(Set<String> hosts,
                                           ActionExecutionContext actionExecutionContext,
                                           RequestResourceFilter resourceFilter) throws AmbariException
{
     Set<String> removedHosts = new HashSet<String>();

http://git-wip-us.apache.org/repos/asf/ambari/blob/4518c9c0/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
index 3feaadd..14b64ef 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/UpgradeResourceProvider.java
@@ -17,10 +17,25 @@
  */
 package org.apache.ambari.server.controller.internal;
 
-import com.google.common.collect.Lists;
-import com.google.gson.Gson;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
+import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.VERSION;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
@@ -93,24 +108,10 @@ import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.HOOKS_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.SERVICE_PACKAGE_FOLDER;
-import static org.apache.ambari.server.agent.ExecutionCommand.KeyNames.VERSION;
+import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
 
 /**
  * Manages the ability to start and get status of upgrades.
@@ -1185,7 +1186,9 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     ActionExecutionContext actionContext = new ActionExecutionContext(cluster.getClusterName(),
         "ru_execute_tasks", Collections.singletonList(filter), params);
 
-    actionContext.setIgnoreMaintenance(true);
+    // hosts in maintenance mode are excluded from the upgrade
+    actionContext.setMaintenanceModeIgnored(false);
+
     actionContext.setTimeout(Short.valueOf(s_configuration.getDefaultAgentTaskTimeout(false)));
     actionContext.setRetryAllowed(allowRetry);
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
@@ -1281,10 +1284,12 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     ActionExecutionContext actionContext = new ActionExecutionContext(cluster.getClusterName(),
         function, filters, commandParams);
     actionContext.setTimeout(Short.valueOf(s_configuration.getDefaultAgentTaskTimeout(false)));
-    actionContext.setIgnoreMaintenance(true);
     actionContext.setRetryAllowed(allowRetry);
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
 
+    // hosts in maintenance mode are excluded from the upgrade
+    actionContext.setMaintenanceModeIgnored(false);
+
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
         cluster, context.getEffectiveStackId());
 
@@ -1339,10 +1344,13 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         "SERVICE_CHECK", filters, commandParams);
 
     actionContext.setTimeout(Short.valueOf(s_configuration.getDefaultAgentTaskTimeout(false)));
-    actionContext.setIgnoreMaintenance(true);
     actionContext.setRetryAllowed(allowRetry);
     actionContext.setAutoSkipFailures(context.isServiceCheckFailureAutoSkipped());
 
+    // hosts in maintenance mode are excluded from the upgrade and should not be
+    // candidates for service checks
+    actionContext.setMaintenanceModeIgnored(false);
+
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
         cluster, context.getEffectiveStackId());
 
@@ -1454,10 +1462,12 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         commandParams);
 
     actionContext.setTimeout(Short.valueOf((short) -1));
-    actionContext.setIgnoreMaintenance(true);
     actionContext.setRetryAllowed(allowRetry);
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
 
+    // hosts in maintenance mode are excluded from the upgrade
+    actionContext.setMaintenanceModeIgnored(false);
+
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
         cluster, context.getEffectiveStackId());
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/4518c9c0/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
index baa394c..d2b738e 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/AmbariCustomCommandExecutionHelperTest.java
@@ -27,8 +27,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import junit.framework.Assert;
-
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.ExecutionCommandWrapper;
@@ -41,11 +39,13 @@ import org.apache.ambari.server.controller.internal.RequestOperationLevel;
 import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.controller.internal.ServiceResourceProviderTest;
 import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.metadata.ActionMetadata;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.HostState;
+import org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.SecurityType;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.topology.TopologyManager;
@@ -64,6 +64,8 @@ import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
 
+import junit.framework.Assert;
+
 @RunWith(MockitoJUnitRunner.class)
 public class AmbariCustomCommandExecutionHelperTest {
   private Injector injector;
@@ -71,13 +73,13 @@ public class AmbariCustomCommandExecutionHelperTest {
   private AmbariMetaInfo ambariMetaInfo;
   private Clusters clusters;
   private TopologyManager topologyManager;
-  
-  
+
+
   private static final String REQUEST_CONTEXT_PROPERTY = "context";
-  
+
   @Captor ArgumentCaptor<Request> requestCapture;
   @Mock ActionManager am;
-  
+
   @Before
   public void setup() throws Exception {
     InMemoryDefaultTestModule module = new InMemoryDefaultTestModule(){
@@ -88,8 +90,8 @@ public class AmbariCustomCommandExecutionHelperTest {
       }
     };
     injector = Guice.createInjector(module);
-    
-    
+
+
     injector.getInstance(GuiceJpaInitializer.class);
     controller = injector.getInstance(AmbariManagementController.class);
     clusters = injector.getInstance(Clusters.class);
@@ -104,49 +106,47 @@ public class AmbariCustomCommandExecutionHelperTest {
 
   @SuppressWarnings("serial")
   @Test
-  public void testRefreshQueueCustomCommand() {
-    try {
-      createClusterFixture("HDP-2.0.6");
-      
-      Map<String, String> requestProperties = new HashMap<String, String>() {
-        {
-          put(REQUEST_CONTEXT_PROPERTY, "Refresh YARN Capacity Scheduler");
-          put("command", "REFRESHQUEUES");
-        }
-      };
-
-      ExecuteActionRequest actionRequest = new ExecuteActionRequest("c1",
-          "REFRESHQUEUES", new HashMap<String, String>() {
-            {
-              put("forceRefreshConfigTags" , "capacity-scheduler");
-            }
-          }, false);
-      actionRequest.getResourceFilters().add(new RequestResourceFilter("YARN", "RESOURCEMANAGER",Collections.singletonList("c6401")));
-      
-      controller.createAction(actionRequest, requestProperties);
-      
-      Mockito.verify(am, Mockito.times(1)).sendActions(requestCapture.capture(), any(ExecuteActionRequest.class));
-
-      Request request = requestCapture.getValue();
-      Assert.assertNotNull(request);
-      Assert.assertNotNull(request.getStages());
-      Assert.assertEquals(1, request.getStages().size());
-      Stage stage = request.getStages().iterator().next();
-      
-      Assert.assertEquals(1, stage.getHosts().size());
-      
-      List<ExecutionCommandWrapper> commands = stage.getExecutionCommands("c6401");
-      Assert.assertEquals(1, commands.size());
-      
-      ExecutionCommand command = commands.get(0).getExecutionCommand();
-      
-      Assert.assertNotNull(command.getForceRefreshConfigTags());
-      Assert.assertEquals(1, command.getForceRefreshConfigTags().size());
-      Assert.assertEquals("capacity-scheduler", command.getForceRefreshConfigTags().iterator().next());
-      
-    } catch (AmbariException e) {
-      Assert.fail(e.getMessage());
-    }
+  public void testRefreshQueueCustomCommand() throws Exception {
+    createClusterFixture("HDP-2.0.6");
+
+    Map<String, String> requestProperties = new HashMap<String, String>() {
+      {
+        put(REQUEST_CONTEXT_PROPERTY, "Refresh YARN Capacity Scheduler");
+        put("command", "REFRESHQUEUES");
+      }
+    };
+
+    ExecuteActionRequest actionRequest = new ExecuteActionRequest("c1", "REFRESHQUEUES",
+        new HashMap<String, String>() {
+          {
+            put("forceRefreshConfigTags", "capacity-scheduler");
+          }
+        }, false);
+    actionRequest.getResourceFilters().add(
+        new RequestResourceFilter("YARN", "RESOURCEMANAGER", Collections.singletonList("c6401")));
+
+    controller.createAction(actionRequest, requestProperties);
+
+    Mockito.verify(am, Mockito.times(1)).sendActions(requestCapture.capture(),
+        any(ExecuteActionRequest.class));
+
+    Request request = requestCapture.getValue();
+    Assert.assertNotNull(request);
+    Assert.assertNotNull(request.getStages());
+    Assert.assertEquals(1, request.getStages().size());
+    Stage stage = request.getStages().iterator().next();
+
+    Assert.assertEquals(1, stage.getHosts().size());
+
+    List<ExecutionCommandWrapper> commands = stage.getExecutionCommands("c6401");
+    Assert.assertEquals(1, commands.size());
+
+    ExecutionCommand command = commands.get(0).getExecutionCommand();
+
+    Assert.assertNotNull(command.getForceRefreshConfigTags());
+    Assert.assertEquals(1, command.getForceRefreshConfigTags().size());
+    Assert.assertEquals("capacity-scheduler",
+        command.getForceRefreshConfigTags().iterator().next());
   }
 
   @Test
@@ -170,7 +170,10 @@ public class AmbariCustomCommandExecutionHelperTest {
           new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR", Collections.singletonList("c6402"))
        ),
        new RequestOperationLevel(Resource.Type.Service, "c1", "GANGLIA", null, null),
-       new HashMap<String, String>(){{}},
+        new HashMap<String, String>() {
+          {
+          }
+        },
        false);
 
     controller.createAction(actionRequest, requestProperties);
@@ -190,92 +193,134 @@ public class AmbariCustomCommandExecutionHelperTest {
   }
 
   @Test
-  public void testHostsFilterUnhealthyHost(){
-    try {
-      createClusterFixture("HDP-2.0.6");
-
-      // Set custom status to host
-      clusters.getHost("c6402").setState(HostState.HEARTBEAT_LOST);
-      Map<String, String> requestProperties = new HashMap<String, String>() {
-        {
-          put("context" , "Restart all components for GANGLIA");
-          put("operation_level/level", "SERVICE");
-          put("operation_level/service_name", "GANGLIA");
-          put("operation_level/cluster_name", "c1");
-        }
-      };
-
-      ExecuteActionRequest actionRequest = new ExecuteActionRequest(
-         "c1", "RESTART", null,
-         Arrays.asList(
-            new RequestResourceFilter("GANGLIA", "GANGLIA_SERVER", Collections.singletonList("c6401")),
-            new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR", Collections.singletonList("c6401")),
-            new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR", Collections.singletonList("c6402"))
-         ),
-         new RequestOperationLevel(Resource.Type.Service, "c1", "GANGLIA", null, null),
-         new HashMap<String, String>(){{}},
-         false);
-
-      controller.createAction(actionRequest, requestProperties);
-
-      Mockito.verify(am, Mockito.times(1)).sendActions(requestCapture.capture(), any(ExecuteActionRequest.class));
-
-      Request request = requestCapture.getValue();
-      Assert.assertNotNull(request);
-      Assert.assertNotNull(request.getStages());
-      Assert.assertEquals(1, request.getStages().size());
-      Stage stage = request.getStages().iterator().next();
-
-      // Check if was generated command for one health host
-      Assert.assertEquals(1, stage.getHostRoleCommands().size());
-    }catch (Exception e) {
-      Assert.fail(e.getMessage());
-    }
+  public void testHostsFilterUnhealthyHost() throws Exception {
+    createClusterFixture("HDP-2.0.6");
+
+    // Set custom status to host
+    clusters.getHost("c6402").setState(HostState.HEARTBEAT_LOST);
+    Map<String, String> requestProperties = new HashMap<String, String>() {
+      {
+        put("context", "Restart all components for GANGLIA");
+        put("operation_level/level", "SERVICE");
+        put("operation_level/service_name", "GANGLIA");
+        put("operation_level/cluster_name", "c1");
+      }
+    };
+
+    ExecuteActionRequest actionRequest = new ExecuteActionRequest("c1", "RESTART", null,
+        Arrays.asList(
+            new RequestResourceFilter("GANGLIA", "GANGLIA_SERVER",
+                Collections.singletonList("c6401")),
+            new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR",
+                Collections.singletonList("c6401")),
+            new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR",
+                Collections.singletonList("c6402"))),
+        new RequestOperationLevel(Resource.Type.Service, "c1", "GANGLIA", null, null),
+        new HashMap<String, String>() {
+          {
+          }
+        }, false);
+
+    controller.createAction(actionRequest, requestProperties);
+
+    Mockito.verify(am, Mockito.times(1)).sendActions(requestCapture.capture(),
+        any(ExecuteActionRequest.class));
+
+    Request request = requestCapture.getValue();
+    Assert.assertNotNull(request);
+    Assert.assertNotNull(request.getStages());
+    Assert.assertEquals(1, request.getStages().size());
+    Stage stage = request.getStages().iterator().next();
+
+    // Check if was generated command for one health host
+    Assert.assertEquals(1, stage.getHostRoleCommands().size());
   }
 
   @Test
-  public void testHostsFilterUnhealthyComponent(){
-    try {
-      createClusterFixture("HDP-2.0.6");
-
-      // Set custom status to host
-      clusters.getCluster("c1").getService("GANGLIA").getServiceComponent("GANGLIA_MONITOR").getServiceComponentHost("c6402")
-         .setState(State.UNKNOWN);
-      Map<String, String> requestProperties = new HashMap<String, String>() {
-        {
-          put("context" , "Restart all components for GANGLIA");
-          put("operation_level/level", "SERVICE");
-          put("operation_level/service_name", "GANGLIA");
-          put("operation_level/cluster_name", "c1");
-        }
-      };
-
-      ExecuteActionRequest actionRequest = new ExecuteActionRequest(
-         "c1", "RESTART", null,
-         Arrays.asList(
-            new RequestResourceFilter("GANGLIA", "GANGLIA_SERVER", Collections.singletonList("c6401")),
-            new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR", Collections.singletonList("c6401")),
-            new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR", Collections.singletonList("c6402"))
-         ),
-         new RequestOperationLevel(Resource.Type.Host, "c1", "GANGLIA", null, null),
-         new HashMap<String, String>(){{}},
-         false);
-
-      controller.createAction(actionRequest, requestProperties);
-
-      Mockito.verify(am, Mockito.times(1)).sendActions(requestCapture.capture(), any(ExecuteActionRequest.class));
-
-      Request request = requestCapture.getValue();
-      Assert.assertNotNull(request);
-      Assert.assertNotNull(request.getStages());
-      Assert.assertEquals(1, request.getStages().size());
-      Stage stage = request.getStages().iterator().next();
-
-      // Check if was generated command for one health host
-      Assert.assertEquals(1, stage.getHostRoleCommands().size());
-    }catch (Exception e) {
-      Assert.fail(e.getMessage());
-    }
+  public void testHostsFilterUnhealthyComponent() throws Exception {
+    createClusterFixture("HDP-2.0.6");
+
+    // Set custom status to host
+    clusters.getCluster("c1").getService("GANGLIA").getServiceComponent(
+        "GANGLIA_MONITOR").getServiceComponentHost("c6402").setState(State.UNKNOWN);
+
+    Map<String, String> requestProperties = new HashMap<String, String>() {
+      {
+        put("context", "Restart all components for GANGLIA");
+        put("operation_level/level", "SERVICE");
+        put("operation_level/service_name", "GANGLIA");
+        put("operation_level/cluster_name", "c1");
+      }
+    };
+
+    ExecuteActionRequest actionRequest = new ExecuteActionRequest("c1", "RESTART", null,
+        Arrays.asList(
+            new RequestResourceFilter("GANGLIA", "GANGLIA_SERVER",
+                Collections.singletonList("c6401")),
+            new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR",
+                Collections.singletonList("c6401")),
+            new RequestResourceFilter("GANGLIA", "GANGLIA_MONITOR",
+                Collections.singletonList("c6402"))),
+        new RequestOperationLevel(Resource.Type.Host, "c1", "GANGLIA", null, null),
+        new HashMap<String, String>() {
+          {
+          }
+        }, false);
+
+    controller.createAction(actionRequest, requestProperties);
+
+    Mockito.verify(am, Mockito.times(1)).sendActions(requestCapture.capture(),
+        any(ExecuteActionRequest.class));
+
+    Request request = requestCapture.getValue();
+    Assert.assertNotNull(request);
+    Assert.assertNotNull(request.getStages());
+    Assert.assertEquals(1, request.getStages().size());
+    Stage stage = request.getStages().iterator().next();
+
+    // Check if was generated command for one health host
+    Assert.assertEquals(1, stage.getHostRoleCommands().size());
+  }
+
+  /**
+   * Tests that trying to run a service check when there are no available hosts
+   * will throw an exception.
+   */
+  @Test(expected = AmbariException.class)
+  public void testNoCandidateHostThrowsException() throws Exception {
+    createClusterFixture("HDP-2.0.6");
+    long clusterId = clusters.getCluster("c1").getClusterId();
+
+    // put host into MM
+    clusters.getHost("c6402").setMaintenanceState(clusterId, MaintenanceState.ON);
+
+    // ensure that service check is added for ZOOKEEPER
+    injector.getInstance(ActionMetadata.class).addServiceCheckAction("ZOOKEEPER");
+
+    Map<String, String> requestProperties = new HashMap<String, String>() {
+      {
+        put("context", "Service Check ZooKeeper");
+        put("operation_level/level", "SERVICE");
+        put("operation_level/service_name", "ZOOKEEPER");
+        put("operation_level/cluster_name", "c1");
+      }
+    };
+
+    // create the service check on the host in MM
+    ExecuteActionRequest actionRequest = new ExecuteActionRequest("c1",
+        "ZOOKEEPER_QUORUM_SERVICE_CHECK",
+        null, Arrays.asList(new RequestResourceFilter("ZOOKEEPER", "ZOOKEEPER_CLIENT",
+            Collections.singletonList("c6402"))),
+
+        new RequestOperationLevel(Resource.Type.Service, "c1", "ZOOKEEPER", null, null),
+        new HashMap<String, String>() {
+          {
+          }
+        }, false);
+
+    controller.createAction(actionRequest, requestProperties);
+    Assert.fail(
+        "Expected an exception since there are no hosts which can run the ZK service check");
   }
 
   @Test
@@ -293,23 +338,26 @@ public class AmbariCustomCommandExecutionHelperTest {
     createCluster("c1", stackVersion);
     addHost("c6401","c1");
     addHost("c6402","c1");
-    
+
     clusters.getCluster("c1");
     createService("c1", "YARN", null);
     createService("c1", "GANGLIA", null);
+    createService("c1", "ZOOKEEPER", null);
 
     createServiceComponent("c1", "YARN","RESOURCEMANAGER", State.INIT);
     createServiceComponent("c1", "YARN", "NODEMANAGER", State.INIT);
     createServiceComponent("c1", "GANGLIA", "GANGLIA_SERVER", State.INIT);
     createServiceComponent("c1", "GANGLIA", "GANGLIA_MONITOR", State.INIT);
-    
+    createServiceComponent("c1", "ZOOKEEPER", "ZOOKEEPER_CLIENT", State.INIT);
+
     createServiceComponentHost("c1","YARN","RESOURCEMANAGER","c6401", null);
     createServiceComponentHost("c1","YARN","NODEMANAGER","c6401", null);
     createServiceComponentHost("c1","GANGLIA","GANGLIA_SERVER","c6401", State.INIT);
     createServiceComponentHost("c1","GANGLIA","GANGLIA_MONITOR","c6401", State.INIT);
-    
+
     createServiceComponentHost("c1","YARN","NODEMANAGER","c6402", null);
     createServiceComponentHost("c1","GANGLIA","GANGLIA_MONITOR","c6402", State.INIT);
+    createServiceComponentHost("c1", "ZOOKEEPER", "ZOOKEEPER_CLIENT", "c6402", State.INIT);
 
   }
   private void addHost(String hostname, String clusterName) throws AmbariException {
@@ -325,7 +373,7 @@ public class AmbariCustomCommandExecutionHelperTest {
     Map<String, String> hostAttributes = new HashMap<String, String>();
     hostAttributes.put("os_family", osFamily);
     hostAttributes.put("os_release_version", osVersion);
-    
+
     host.setHostAttributes(hostAttributes);
   }
 
@@ -334,7 +382,7 @@ public class AmbariCustomCommandExecutionHelperTest {
         SecurityType.NONE, stackVersion, null);
     controller.createCluster(r);
   }
-  
+
   private void createService(String clusterName,
       String serviceName, State desiredState) throws AmbariException {
     String dStateStr = null;


Mime
View raw message