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-15303 - New Alerts Do Not Honor Existing Maintenance Mode Setting (jonathanhurley)
Date Fri, 04 Mar 2016 19:56:56 GMT
Repository: ambari
Updated Branches:
  refs/heads/trunk 8486be6aa -> 211a48d56


AMBARI-15303 - New Alerts Do Not Honor Existing Maintenance Mode Setting (jonathanhurley)


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

Branch: refs/heads/trunk
Commit: 211a48d56eb6975d002b9c8c12aaab76049d6ee0
Parents: 8486be6
Author: Jonathan Hurley <jhurley@hortonworks.com>
Authored: Fri Mar 4 12:43:42 2016 -0500
Committer: Jonathan Hurley <jhurley@hortonworks.com>
Committed: Fri Mar 4 14:56:49 2016 -0500

----------------------------------------------------------------------
 .../controller/MaintenanceStateHelper.java      |  60 ++++++++
 .../listeners/alerts/AlertReceivedListener.java |  23 ++-
 .../controller/MaintenanceStateHelperTest.java  | 145 +++++++++++++++++++
 .../state/alerts/AlertReceivedListenerTest.java |  47 ++++++
 4 files changed, 274 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/211a48d5/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 cd49e76..dd1652c 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
@@ -24,9 +24,11 @@ import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.HostNotFoundException;
+import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
 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.Alert;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Host;
@@ -34,6 +36,7 @@ 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.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -230,6 +233,63 @@ public class MaintenanceStateHelper {
   }
 
   /**
+   * Gets the effective maintenance state for a given alert. This will determine
+   * whether the alert needs to report that it is in maintenance mode.
+   *
+   * @param clusterId
+   *          the ID of the cluster for the alert.
+   * @param alert
+   *          the alert (not {@code null}).
+   * @return {@link MaintenanceState#OFF} if the host/service/component all
+   *         report they are not in maintenance mode;
+   *         {@link MaintenanceState#ON} otherwise.
+   * @throws AmbariException
+   */
+  public MaintenanceState getEffectiveState(long clusterId, Alert alert) throws AmbariException
{
+    String serviceName = alert.getService();
+    String componentName = alert.getComponent();
+    String hostName = alert.getHostName();
+
+    if (null == serviceName && null == hostName) {
+      LOG.warn("Unable to determine maintenance state for an alert without a service or host");
+      return MaintenanceState.OFF;
+    }
+
+    // always start with the host first; we always have a host unless this is an
+    // aggregate alert (service-level alert)
+    if (StringUtils.isNotBlank(hostName)) {
+      Host host = clusters.getHost(hostName);
+      if (host.getMaintenanceState(clusterId) != MaintenanceState.OFF) {
+        return MaintenanceState.ON;
+      }
+    }
+
+    // the AMBARI service is not a real service; it's never in MM
+    if( StringUtils.equals(Services.AMBARI.name(), serviceName)){
+      return MaintenanceState.OFF;
+    }
+
+    // the host is not in MM, move onto the service
+    Cluster cluster = clusters.getClusterById(clusterId);
+    Service service = cluster.getService(serviceName);
+    if( service.getMaintenanceState() != MaintenanceState.OFF ){
+      return MaintenanceState.ON;
+    }
+
+    if( StringUtils.isNotBlank(componentName)){
+      ServiceComponent serviceComponent = service.getServiceComponent(componentName);
+      ServiceComponentHost serviceComponentHost = serviceComponent.getServiceComponentHost(hostName);
+
+      if (serviceComponentHost.getMaintenanceState() != MaintenanceState.OFF) {
+        return MaintenanceState.ON;
+      }
+    }
+
+    // MM is off at the host, service, and component level; return OFF
+    return MaintenanceState.OFF;
+  }
+
+  /**
    * @param clusters
    *          the collection of clusters
    * @param cluster

http://git-wip-us.apache.org/repos/asf/ambari/blob/211a48d5/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
index 9bbfe37..8dc8e1e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertReceivedListener.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.EagerSingleton;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
 import org.apache.ambari.server.events.AlertEvent;
 import org.apache.ambari.server.events.AlertReceivedEvent;
@@ -81,6 +82,16 @@ public class AlertReceivedListener {
   Provider<Clusters> m_clusters;
 
   /**
+   * Used to calculate the maintenance state of new alerts being created.
+   * Consider the case where you have disabled alerts for a component in MM.
+   * This means that there are no current alerts in the system since disabling
+   * them removes all current instances. New alerts being created for the
+   * component in MM must reflect the correct MM.
+   */
+  @Inject
+  private Provider<MaintenanceStateHelper> m_maintenanceStateHelper;
+
+  /**
    * Receives and publishes {@link AlertEvent} instances.
    */
   private AlertEventPublisher m_alertEventPublisher;
@@ -164,8 +175,18 @@ public class AlertReceivedListener {
       if (null == current) {
         AlertHistoryEntity history = createHistory(clusterId, definition, alert);
 
+        // this new alert must reflect the correct MM state for the
+        // service/component/host
+        MaintenanceState maintenanceState = MaintenanceState.OFF;
+        try {
+          maintenanceState = m_maintenanceStateHelper.get().getEffectiveState(clusterId,
alert);
+        } catch (Exception exception) {
+          LOG.error("Unable to determine the maintenance mode state for {}, defaulting to
OFF",
+              alert, exception);
+        }
+
         current = new AlertCurrentEntity();
-        current.setMaintenanceState(MaintenanceState.OFF);
+        current.setMaintenanceState(maintenanceState);
         current.setAlertHistory(history);
         current.setLatestTimestamp(alert.getTimestamp());
         current.setOriginalTimestamp(alert.getTimestamp());

http://git-wip-us.apache.org/repos/asf/ambari/blob/211a48d5/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 d9c5039..8cdaa10 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
@@ -39,11 +39,14 @@ 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.controller.spi.Resource.Type;
+import org.apache.ambari.server.state.Alert;
+import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.Host;
 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.easymock.EasyMock;
 import org.junit.Assert;
@@ -154,6 +157,148 @@ public class MaintenanceStateHelperTest {
     verify(maintenanceStateHelper, clusters, cluster, sch, host, service);
   }
 
+  /**
+   * Tests that the host MM state is calculated correctly for an alert.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testGetEffectiveStateForHostAlert() throws Exception {
+    Injector injector = createStrictMock(Injector.class);
+    MaintenanceStateHelper maintenanceStateHelper = createMockBuilder(
+        MaintenanceStateHelper.class).withConstructor(injector).createNiceMock();
+
+    Clusters clusters = createMock(Clusters.class);
+    final Host host = createNiceMock(Host.class);
+
+    long clusterId = 1L;
+    String hostName = "c6401.ambari.apache.org";
+
+    Alert alert = new Alert("foo-alert", null, "HDFS", "DATANODE", hostName,
+        AlertState.CRITICAL);
+
+    expect(host.getMaintenanceState(clusterId)).andReturn(MaintenanceState.ON).once();
+    expect(clusters.getHost(hostName)).andReturn(host).once();
+
+    injectField(maintenanceStateHelper, clusters);
+    replay(maintenanceStateHelper, clusters, host);
+
+    MaintenanceState state = maintenanceStateHelper.getEffectiveState(clusterId, alert);
+    Assert.assertEquals(MaintenanceState.ON, state);
+
+    verify(maintenanceStateHelper, clusters, host);
+  }
+
+  /**
+   * Tests that the service MM state is calculated correctly for an alert.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testGetEffectiveStateForServiceAlert() 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);
+    Service service = createNiceMock(Service.class);
+    final Host host = createNiceMock(Host.class);
+
+    long clusterId = 1L;
+    String hostName = "c6401.ambari.apache.org";
+
+    Alert alert = new Alert("foo-alert", null, "HDFS", null, hostName, AlertState.CRITICAL);
+
+    expect(host.getMaintenanceState(clusterId)).andReturn(MaintenanceState.OFF).once();
+    expect(clusters.getHost(hostName)).andReturn(host).once();
+    expect(clusters.getClusterById(clusterId)).andReturn(cluster).once();
+    expect(cluster.getService("HDFS")).andReturn(service).once();
+    expect(service.getMaintenanceState()).andReturn(MaintenanceState.ON);
+
+    injectField(maintenanceStateHelper, clusters);
+    replay(maintenanceStateHelper, clusters, host, cluster, service);
+
+    MaintenanceState state = maintenanceStateHelper.getEffectiveState(clusterId, alert);
+    Assert.assertEquals(MaintenanceState.ON, state);
+
+    verify(maintenanceStateHelper, clusters, host, cluster, service);
+  }
+
+  /**
+   * Tests that the service MM state is calculated correctly for an alert which
+   * is only for a service (such as an AGGREGATE alert).
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testGetEffectiveStateForServiceOnlyAlert() 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);
+    Service service = createNiceMock(Service.class);
+
+    long clusterId = 1L;
+
+    Alert alert = new Alert("foo-alert", null, "HDFS", null, null, AlertState.CRITICAL);
+
+    expect(clusters.getClusterById(clusterId)).andReturn(cluster).once();
+    expect(cluster.getService("HDFS")).andReturn(service).once();
+    expect(service.getMaintenanceState()).andReturn(MaintenanceState.ON);
+
+    injectField(maintenanceStateHelper, clusters);
+    replay(maintenanceStateHelper, clusters, cluster, service);
+
+    MaintenanceState state = maintenanceStateHelper.getEffectiveState(clusterId, alert);
+    Assert.assertEquals(MaintenanceState.ON, state);
+
+    verify(maintenanceStateHelper, clusters, cluster, service);
+  }
+
+  /**
+   * Tests that the service MM state is calculated correctly for an alert.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testGetEffectiveStateForComponentAlert() 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);
+    Service service = createNiceMock(Service.class);
+    ServiceComponent serviceComponent = createMock(ServiceComponent.class);
+    ServiceComponentHost sch = createMock(ServiceComponentHost.class);
+    final Host host = createNiceMock(Host.class);
+
+    long clusterId = 1L;
+    String hostName = "c6401.ambari.apache.org";
+
+    Alert alert = new Alert("foo-alert", null, "HDFS", "DATANODE", hostName, AlertState.CRITICAL);
+
+    expect(host.getMaintenanceState(clusterId)).andReturn(MaintenanceState.OFF).once();
+    expect(clusters.getHost(hostName)).andReturn(host).once();
+    expect(clusters.getClusterById(clusterId)).andReturn(cluster).once();
+    expect(cluster.getService("HDFS")).andReturn(service).once();
+    expect(service.getMaintenanceState()).andReturn(MaintenanceState.OFF);
+    expect(service.getServiceComponent("DATANODE")).andReturn(serviceComponent).once();
+    expect(serviceComponent.getServiceComponentHost(hostName)).andReturn(sch).once();
+    expect(sch.getMaintenanceState()).andReturn(MaintenanceState.ON).once();
+
+    injectField(maintenanceStateHelper, clusters);
+    replay(maintenanceStateHelper, clusters, host, cluster, service, serviceComponent, sch);
+
+    MaintenanceState state = maintenanceStateHelper.getEffectiveState(clusterId, alert);
+    Assert.assertEquals(MaintenanceState.ON, state);
+
+    verify(maintenanceStateHelper, clusters, host, cluster, service, serviceComponent, sch);
+  }
+
   @Test
   public void testServiceOperationsAllowance() throws Exception {
     Injector injector = createStrictMock(Injector.class);

http://git-wip-us.apache.org/repos/asf/ambari/blob/211a48d5/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
index 6e58876..136a756 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/AlertReceivedListenerTest.java
@@ -35,6 +35,7 @@ import org.apache.ambari.server.state.Alert;
 import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.ServiceComponentFactory;
 import org.apache.ambari.server.state.ServiceComponentHostFactory;
 import org.apache.ambari.server.state.ServiceFactory;
@@ -259,4 +260,50 @@ public class AlertReceivedListenerTest {
     allCurrent = m_dao.findCurrent();
     assertEquals(0, allCurrent.size());
   }
+
+  /**
+   * Tests that a disabled definition doesn't record alert events.
+   */
+  @Test
+  public void testMaintenanceModeSet() throws Exception {
+    String definitionName = ALERT_DEFINITION + "1";
+    String componentName = "DATANODE";
+
+    Alert alert1 = new Alert(definitionName, null, "HDFS", componentName, HOST1,
+        AlertState.CRITICAL);
+
+    alert1.setCluster(m_cluster.getClusterName());
+    alert1.setLabel(ALERT_LABEL);
+    alert1.setText("HDFS " + componentName + " is OK");
+    alert1.setTimestamp(1L);
+
+    // verify that the listener works with a regular alert
+    AlertReceivedListener listener = m_injector.getInstance(AlertReceivedListener.class);
+    AlertReceivedEvent event = new AlertReceivedEvent(m_cluster.getClusterId(), alert1);
+    listener.onAlertEvent(event);
+
+    List<AlertCurrentEntity> allCurrent = m_dao.findCurrent();
+    assertEquals(1, allCurrent.size());
+
+    AlertCurrentEntity current = allCurrent.get(0);
+    assertEquals(MaintenanceState.OFF, current.getMaintenanceState());
+
+    // remove it
+    m_dao.removeCurrentByService(m_cluster.getClusterId(), "HDFS");
+    allCurrent = m_dao.findCurrent();
+    assertEquals(0, allCurrent.size());
+
+    // set maintenance mode on the service
+    m_cluster.getService("HDFS").setMaintenanceState(MaintenanceState.ON);
+
+    // verify that the listener handles the event and creates the current alert
+    // with the correct MM
+    listener.onAlertEvent(event);
+
+    allCurrent = m_dao.findCurrent();
+    assertEquals(1, allCurrent.size());
+
+    current = allCurrent.get(0);
+    assertEquals(MaintenanceState.ON, current.getMaintenanceState());
+  }
 }


Mime
View raw message