ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nc...@apache.org
Subject [01/50] [abbrv] ambari git commit: AMBARI-14614 - Hosts in Maintenance Mode Are Included in Client Service Checks During Upgrade (jonathanhurley)
Date Fri, 15 Jan 2016 17:33:25 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-dev-patch-upgrade e001ed1b3 -> ee623b7ff


AMBARI-14614 - Hosts in Maintenance Mode Are Included in Client Service Checks During Upgrade
(jonathanhurley)


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

Branch: refs/heads/branch-dev-patch-upgrade
Commit: 54f0e270fdccd71271650684b04c57f2c079b229
Parents: 0afdd9b
Author: Jonathan Hurley <jhurley@hortonworks.com>
Authored: Mon Jan 11 15:03:03 2016 -0500
Committer: Nate Cole <ncole@hortonworks.com>
Committed: Thu Jan 14 11:43:24 2016 -0500

----------------------------------------------------------------------
 .../controller/ActionExecutionContext.java      | 26 +++++---
 .../AmbariCustomCommandExecutionHelper.java     | 66 ++++++++++++--------
 .../controller/AmbariManagementController.java  |  9 ++-
 .../controller/MaintenanceStateHelper.java      | 22 +++++--
 .../internal/UpgradeResourceProvider.java       |  8 +--
 .../AmbariCustomCommandExecutionHelperTest.java | 49 ++++++++++++++-
 6 files changed, 135 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/54f0e270/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 923fd92..3681eda 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
@@ -39,7 +39,7 @@ public class ActionExecutionContext {
   private Short timeout;
   private String expectedServiceName;
   private String expectedComponentName;
-  private boolean ignoreMaintenance = false;
+  private boolean hostsInMaintenanceModeExcluded = true;
   private boolean allowRetry = false;
 
   /**
@@ -178,25 +178,33 @@ public class ActionExecutionContext {
       ", parameters=" + parameters +
       ", targetType=" + targetType +
       ", timeout=" + timeout +
-      ", ignoreMaintenance=" + ignoreMaintenance +
+      ", isMaintenanceModeHostExcluded=" + hostsInMaintenanceModeExcluded +
       ", allowRetry=" + allowRetry +
       ", autoSkipFailures=" + autoSkipFailures +
       '}';
   }
 
   /**
-   * @return {@code true} if the action context should schedule even if maintenance mode
is
-   * enabled
+   * Gets whether hosts in maintenance mode should be excluded from the command.
+   *
+   * @return {@code true} to exclude any hosts in maintenance mode from the
+   *         command, {@code false} to include hosts which are in maintenance
+   *         mode.
    */
-  public boolean isMaintenanceModeIgnored() {
-    return ignoreMaintenance;
+  public boolean isMaintenanceModeHostExcluded() {
+    return hostsInMaintenanceModeExcluded;
   }
 
   /**
-   * @param ignore  {@code true} to ignore maintenace mode
+   * Sets whether hosts in maintenance mode should be excluded from the command.
+   *
+   * @param excluded
+   *          {@code true} to exclude any hosts in maintenance mode from the
+   *          command, {@code false} to include hosts which are in maintenance
+   *          mode.
    */
-  public void setMaintenanceModeIgnored(boolean ignore) {
-    ignoreMaintenance = ignore;
+  public void setMaintenanceModeHostExcluded(boolean excluded) {
+    hostsInMaintenanceModeExcluded = excluded;
   }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/54f0e270/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 1eb9ee5..b62f4d1 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
@@ -113,8 +113,9 @@ import com.google.inject.Singleton;
  */
 @Singleton
 public class AmbariCustomCommandExecutionHelper {
-  private final static Logger LOG =
-      LoggerFactory.getLogger(AmbariCustomCommandExecutionHelper.class);
+  private final static Logger LOG = LoggerFactory.getLogger(
+      AmbariCustomCommandExecutionHelper.class);
+
   // TODO: Remove the hard-coded mapping when stack definition indicates which slave types
can be decommissioned
   public static final Map<String, String> masterToSlaveMappingForDecom = new HashMap<String,
String>();
 
@@ -135,22 +136,31 @@ public class AmbariCustomCommandExecutionHelper {
 
   @Inject
   private ActionMetadata actionMetadata;
+
   @Inject
   private Clusters clusters;
+
   @Inject
   private AmbariManagementController managementController;
+
   @Inject
   private Gson gson;
+
   @Inject
   private Configuration configs;
+
   @Inject
   private AmbariMetaInfo ambariMetaInfo;
+
   @Inject
   private ConfigHelper configHelper;
+
   @Inject
   private MaintenanceStateHelper maintenanceStateHelper;
+
   @Inject
   private OsFamily os_family;
+
   @Inject
   private ClusterVersionDAO clusterVersionDAO;
 
@@ -450,12 +460,13 @@ public class AmbariCustomCommandExecutionHelper {
     long nowTimestamp = System.currentTimeMillis();
     Map<String, String> actionParameters = actionExecutionContext.getParameters();
     final Set<String> candidateHosts;
+    final Map<String, ServiceComponentHost> serviceHostComponents;
 
     if (componentName != null) {
-      Map<String, ServiceComponentHost> components =
-        cluster.getService(serviceName)
-          .getServiceComponent(componentName).getServiceComponentHosts();
-      if (components.isEmpty()) {
+      serviceHostComponents = cluster.getService(serviceName).getServiceComponent(
+          componentName).getServiceComponentHosts();
+
+      if (serviceHostComponents.isEmpty()) {
         throw new AmbariException("Hosts not found, component="
             + componentName + ", service = " + serviceName
             + ", cluster = " + clusterName);
@@ -465,39 +476,43 @@ public class AmbariCustomCommandExecutionHelper {
       if (candidateHostsList != null && !candidateHostsList.isEmpty()) {
         candidateHosts = new HashSet<String>(candidateHostsList);
       } else {
-        candidateHosts = components.keySet();
+        candidateHosts = serviceHostComponents.keySet();
       }
-    } else { // TODO: this code branch looks unreliable(taking random component)
-      Map<String, ServiceComponent> components =
+    } else {
+      // TODO: this code branch looks unreliable(taking random component)
+      Map<String, ServiceComponent> serviceComponents =
               cluster.getService(serviceName).getServiceComponents();
 
-      if (components.isEmpty()) {
+      if (serviceComponents.isEmpty()) {
         throw new AmbariException("Components not found, service = "
             + serviceName + ", cluster = " + clusterName);
       }
 
-      ServiceComponent serviceComponent = components.values().iterator().next();
+      ServiceComponent serviceComponent = serviceComponents.values().iterator().next();
       if (serviceComponent.getServiceComponentHosts().isEmpty()) {
         throw new AmbariException("Hosts not found, component="
             + serviceComponent.getName() + ", service = "
             + serviceName + ", cluster = " + clusterName);
       }
-      candidateHosts = serviceComponent.getServiceComponentHosts().keySet();
+
+      serviceHostComponents = serviceComponent.getServiceComponentHosts();
+      candidateHosts = serviceHostComponents.keySet();
     }
 
-    // filter out hosts that are in maintenance mode
-    Set<String> ignoredHosts = new HashSet<String>();
-    if (!actionExecutionContext.isMaintenanceModeIgnored()) {
-      ignoredHosts.addAll(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);
-          }
+    // filter out hosts that are in maintenance mode - they should never be
+    // included in service checks
+    Set<String> hostsInMaintenanceMode = new HashSet<String>();
+    if (actionExecutionContext.isMaintenanceModeHostExcluded()) {
+      Iterator<String> iterator = candidateHosts.iterator();
+      while (iterator.hasNext()) {
+        String candidateHostName = iterator.next();
+        ServiceComponentHost serviceComponentHost = serviceHostComponents.get(candidateHostName);
+        Host host = serviceComponentHost.getHost();
+        if (host.getMaintenanceState(cluster.getClusterId()) == MaintenanceState.ON) {
+          hostsInMaintenanceMode.add(candidateHostName);
+          iterator.remove();
         }
-      ));
+      }
     }
 
     // pick a random healthy host from the remaining set, throwing an exception
@@ -506,7 +521,8 @@ public class AmbariCustomCommandExecutionHelper {
     if (hostName == null) {
       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,
','));
+          serviceName, StringUtils.join(candidateHosts, ','),
+          StringUtils.join(hostsInMaintenanceMode, ','));
 
       throw new AmbariException(message);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/54f0e270/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 cbc5a95..69c6e82 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
@@ -40,6 +40,7 @@ import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Config;
 import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.HostState;
 import org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
@@ -634,8 +635,14 @@ public interface AmbariManagementController {
   String getMysqljdbcUrl();
 
   /**
-   * Return a healthy host if found otherwise any random host
+   * Chooses a healthy host from the list of candidate hosts randomly. If there
+   * are no healthy hosts, then this method will return {@code null}.
+   * <p/>
+   * The host's {@link HostState} is used to determine if a host is healthy.
+   *
+   * @return a random healthy host, or {@code null}.
    * @throws AmbariException
+   * @see {@link HostState#HEALTHY}
    */
   String getHealthyHost(Set<String> hostList) throws AmbariException;
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/54f0e270/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 4c946dc..cd49e76 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
@@ -347,10 +347,6 @@ public class MaintenanceStateHelper {
     return result;
   }
 
-  public static interface HostPredicate {
-    public boolean shouldHostBeRemoved(String hostname) throws AmbariException;
-  }
-
   /**
    * Removes from a set all hosts that match a given condition.
    *
@@ -373,4 +369,22 @@ public class MaintenanceStateHelper {
     return removedHosts;
   }
 
+  /**
+   * The {@link HostPredicate} interaface is used as a way to pass a custom
+   * implementation into one of the many
+   * {@link MaintenanceStateHelper#isOperationAllowed(org.apache.ambari.server.controller.spi.Resource.Type,
Service)}
+   * methods.
+   */
+  public static interface HostPredicate {
+    /**
+     * Gets whether the specified host should not be included in a result set.
+     *
+     * @param hostname
+     *          the host (not {@code null}).
+     * @return {@code true} to indicate that the specified host is not a valid
+     *         choice, {@code false} otherwise.
+     * @throws AmbariException
+     */
+    public boolean shouldHostBeRemoved(String hostname) throws AmbariException;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/54f0e270/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 0f9e65e..d0f226f 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
@@ -1194,7 +1194,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
         "ru_execute_tasks", Collections.singletonList(filter), params);
 
     // hosts in maintenance mode are excluded from the upgrade
-    actionContext.setMaintenanceModeIgnored(false);
+    actionContext.setMaintenanceModeHostExcluded(true);
 
     actionContext.setTimeout(Short.valueOf(s_configuration.getDefaultAgentTaskTimeout(false)));
     actionContext.setRetryAllowed(allowRetry);
@@ -1295,7 +1295,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
 
     // hosts in maintenance mode are excluded from the upgrade
-    actionContext.setMaintenanceModeIgnored(false);
+    actionContext.setMaintenanceModeHostExcluded(true);
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
         cluster, context.getEffectiveStackId());
@@ -1356,7 +1356,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
 
     // hosts in maintenance mode are excluded from the upgrade and should not be
     // candidates for service checks
-    actionContext.setMaintenanceModeIgnored(false);
+    actionContext.setMaintenanceModeHostExcluded(true);
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
         cluster, context.getEffectiveStackId());
@@ -1473,7 +1473,7 @@ public class UpgradeResourceProvider extends AbstractControllerResourceProvider
     actionContext.setAutoSkipFailures(context.isComponentFailureAutoSkipped());
 
     // hosts in maintenance mode are excluded from the upgrade
-    actionContext.setMaintenanceModeIgnored(false);
+    actionContext.setMaintenanceModeHostExcluded(true);
 
     ExecuteCommandJson jsons = s_commandExecutionHelper.get().getCommandJson(actionContext,
         cluster, context.getEffectiveStackId());

http://git-wip-us.apache.org/repos/asf/ambari/blob/54f0e270/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 9eed672..1ecadc4 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
@@ -60,14 +60,13 @@ import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.security.core.context.SecurityContextHolder;
 
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
 
 import junit.framework.Assert;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
 
 @RunWith(MockitoJUnitRunner.class)
 public class AmbariCustomCommandExecutionHelperTest {
@@ -340,6 +339,52 @@ public class AmbariCustomCommandExecutionHelperTest {
         "Expected an exception since there are no hosts which can run the ZK service check");
   }
 
+  /**
+   * Tests that client-only services like TEZ are not run on hosts which are in
+   * MM. The client-only service is a special path since a component is
+   * typically not specified in the request.
+   */
+  @Test(expected = AmbariException.class)
+  public void testServiceCheckMaintenanceModeWithMissingComponentName() throws Exception
{
+    SecurityContextHolder.getContext().setAuthentication(
+        TestAuthenticationFactory.createAdministrator());
+
+    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");
+
+    // !!! use a null operation level to have us guess at the component
+    Map<String, String> requestProperties = new HashMap<String, String>() {
+      {
+        put("context", "Service Check ZooKeeper");
+        put("operation_level/level", null);
+        put("operation_level/service_name", "ZOOKEEPER");
+        put("operation_level/cluster_name", "c1");
+      }
+    };
+
+    // create the service check on the host in MM, passing in null for the
+    // component name
+    ExecuteActionRequest actionRequest = new ExecuteActionRequest("c1",
+        "ZOOKEEPER_QUORUM_SERVICE_CHECK", null, Arrays.asList(
+            new RequestResourceFilter("ZOOKEEPER", null, 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
   public void testIsTopologyRefreshRequired() throws Exception {
     SecurityContextHolder.getContext().setAuthentication(TestAuthenticationFactory.createAdministrator());


Mime
View raw message