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-10851 - Alert Definitions That Ignore Host Cannot Be Put Into Maintenance Mode (jonathanhurley)
Date Thu, 30 Apr 2015 13:38:28 GMT
Repository: ambari
Updated Branches:
  refs/heads/trunk 8727232cd -> 9eaacd3db


AMBARI-10851 - Alert Definitions That Ignore Host Cannot Be Put Into Maintenance Mode (jonathanhurley)


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

Branch: refs/heads/trunk
Commit: 9eaacd3dbf9edd51f044b2a1f7948791e1edf8ec
Parents: 8727232
Author: Jonathan Hurley <jhurley@hortonworks.com>
Authored: Wed Apr 29 16:14:17 2015 -0400
Committer: Jonathan Hurley <jhurley@hortonworks.com>
Committed: Thu Apr 30 09:38:15 2015 -0400

----------------------------------------------------------------------
 .../alerts/AlertMaintenanceModeListener.java    | 185 ++++++---------
 .../AlertMaintenanceModeListenerTest.java       | 232 +++++++++++++++++++
 2 files changed, 297 insertions(+), 120 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9eaacd3d/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertMaintenanceModeListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertMaintenanceModeListener.java
b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertMaintenanceModeListener.java
index 200a471..e0e1d4b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertMaintenanceModeListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertMaintenanceModeListener.java
@@ -19,10 +19,7 @@ package org.apache.ambari.server.events.listeners.alerts;
 
 import java.util.List;
 
-import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.EagerSingleton;
-import org.apache.ambari.server.controller.MaintenanceStateHelper;
-import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
 import org.apache.ambari.server.events.MaintenanceModeEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.dao.AlertsDAO;
@@ -30,8 +27,7 @@ import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
 import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
-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.ServiceComponentHost;
@@ -41,7 +37,6 @@ import org.slf4j.LoggerFactory;
 import com.google.common.eventbus.AllowConcurrentEvents;
 import com.google.common.eventbus.Subscribe;
 import com.google.inject.Inject;
-import com.google.inject.Provider;
 import com.google.inject.Singleton;
 
 /**
@@ -63,18 +58,6 @@ public class AlertMaintenanceModeListener {
   private AlertsDAO m_alertsDao = null;
 
   /**
-   * Used to assist in determining implied maintenance state.
-   */
-  @Inject
-  private Provider<MaintenanceStateHelper> m_maintenanceHelper;
-
-  /**
-   * Used to lookup MM states.
-   */
-  @Inject
-  private Provider<Clusters> m_clusters;
-
-  /**
    * Constructor.
    *
    * @param publisher
@@ -98,123 +81,85 @@ public class AlertMaintenanceModeListener {
   public void onEvent(MaintenanceModeEvent event) {
     List<AlertCurrentEntity> currentAlerts = m_alertsDao.findCurrent();
 
+    MaintenanceState newMaintenanceState = MaintenanceState.OFF;
+    if (event.getMaintenanceState() != MaintenanceState.OFF) {
+      newMaintenanceState = MaintenanceState.ON;
+    }
+
     for( AlertCurrentEntity currentAlert : currentAlerts ){
-      MaintenanceState currentState = currentAlert.getMaintenanceState();
       AlertHistoryEntity history = currentAlert.getAlertHistory();
-      AlertDefinitionEntity definition = history.getAlertDefinition();
 
-      long clusterId = history.getClusterId();
-      String hostName = history.getHostName();
-      String serviceName = history.getServiceName();
-      String componentName = history.getComponentName();
+      String alertHostName = history.getHostName();
+      String alertServiceName = history.getServiceName();
+      String alertComponentName = history.getComponentName();
 
       try {
-        // although AMBARI is a service, it's not really a service and would
-        // fail in this loop; so handle it specifically
-        if (Services.AMBARI.name().equals(serviceName)) {
-
-          // if this alert is an AMBARI_AGENT alert, then the only maintenance
-          // state that affects it is a host maintenance state
-          if (null == event.getHost()) {
+        Host host = event.getHost();
+        Service service = event.getService();
+        ServiceComponentHost serviceComponentHost = event.getServiceComponentHost();
+
+        // host level maintenance
+        if( null != host ){
+          String hostName = host.getHostName();
+          if( hostName.equals( alertHostName ) ){
+            updateMaintenanceState(currentAlert, newMaintenanceState);
             continue;
           }
-
-          MaintenanceState maintenanceState = MaintenanceState.OFF;
-          if (event.getMaintenanceState() != MaintenanceState.OFF) {
-            maintenanceState = MaintenanceState.ON;
-          }
-
-          currentAlert.setMaintenanceState(maintenanceState);
-          m_alertsDao.merge(currentAlert);
-          continue;
-        }
-
-        Cluster cluster = m_clusters.get().getClusterById(clusterId);
-        if (null == cluster) {
-          LOG.warn("Unable to find cluster with ID {}", clusterId);
-          continue;
-        }
-
-        Service service = cluster.getService(serviceName);
-        if (null == service) {
-          LOG.warn("Unable to find service named {} in cluster {}",
-              serviceName, cluster.getClusterName());
-
-          continue;
-        }
-
-        // if this is a service-level alert, then check explicitely against the
-        // service for the MM state
-        if (null == componentName) {
-          MaintenanceState serviceState = service.getMaintenanceState();
-          if (currentState != serviceState) {
-            currentAlert.setMaintenanceState(serviceState);
-            m_alertsDao.merge(currentAlert);
-          }
-        }
-        // the presence of a component name means that it's a component alert
-        // which require a host
-        else {
-          if (hostName == null) {
-            LOG.warn("The alert {} for component {} must have a host",
-                definition.getDefinitionName(), componentName);
-
+        } else if( null != service ){
+          // service level maintenance
+          String serviceName = service.getName();
+          if( serviceName.equals(alertServiceName)){
+            updateMaintenanceState(currentAlert, newMaintenanceState);
             continue;
           }
-
-          List<ServiceComponentHost> serviceComponentHosts = cluster.getServiceComponentHosts(hostName);
-          if (null == serviceComponentHosts) {
-            LOG.warn(
-                "Unable to find service components on host {} for {} in cluster {}",
-                hostName, serviceName, cluster.getClusterName());
-
+        } else if( null != serviceComponentHost ){
+          // component level maintenance
+          String hostName = serviceComponentHost.getHostName();
+          String serviceName = serviceComponentHost.getServiceName();
+          String componentName = serviceComponentHost.getServiceComponentName();
+
+          // match on all 3 for a service component
+          if (hostName.equals(alertHostName) && serviceName.equals(alertServiceName)
+              && componentName.equals(alertComponentName)) {
+            updateMaintenanceState(currentAlert, newMaintenanceState);
             continue;
           }
+        }
+      } catch (Exception exception) {
+        AlertDefinitionEntity definition = history.getAlertDefinition();
+        LOG.error("Unable to put alert '{}' for host {} into maintenance mode",
+            definition.getDefinitionName(), alertHostName, exception);
+      }
+    }
+  }
 
-          ServiceComponentHost serviceComponentHost = null;
-          for (ServiceComponentHost sch : serviceComponentHosts) {
-            if (componentName.equals(sch.getServiceComponentName())) {
-              serviceComponentHost = sch;
-              break;
-            }
-          }
+  /**
+   * Updates the maintenance state of the specified alert if different than the
+   * supplied maintenance state.
+   *
+   * @param currentAlert
+   *          the alert to update (not {@code null}).
+   * @param maintenanceState
+   *          the maintenance state to change to, either
+   *          {@link MaintenanceState#OFF} or {@link MaintenanceState#ON}.
+   */
+  private void updateMaintenanceState(AlertCurrentEntity currentAlert,
+      MaintenanceState maintenanceState) {
 
-          if (null == serviceComponentHost) {
-            LOG.warn("Unable to find component {} of {} on host {}",
-                componentName, serviceName, hostName);
+    // alerts only care about OFF or ON
+    if (maintenanceState != MaintenanceState.OFF && maintenanceState != MaintenanceState.ON)
{
+      LOG.warn("Unable to set invalid maintenance state of {} on the alert {}", maintenanceState,
+          currentAlert.getAlertHistory().getAlertDefinition().getDefinitionName());
 
-            continue;
-          }
+      return;
+    }
 
-          MaintenanceState effectiveState = m_maintenanceHelper.get().getEffectiveState(
-              serviceComponentHost);
-
-          switch (effectiveState) {
-            case OFF:
-              if (currentState != MaintenanceState.OFF) {
-                currentAlert.setMaintenanceState(MaintenanceState.OFF);
-                m_alertsDao.merge(currentAlert);
-              }
-
-              break;
-            case ON:
-            case IMPLIED_FROM_HOST:
-            case IMPLIED_FROM_SERVICE:
-            case IMPLIED_FROM_SERVICE_AND_HOST:
-              if (currentState == MaintenanceState.OFF) {
-                currentAlert.setMaintenanceState(MaintenanceState.ON);
-                m_alertsDao.merge(currentAlert);
-              }
-
-              break;
-            default:
-              break;
-          }
-        }
-      } catch (AmbariException ambariException) {
-        LOG.error("Unable to put alert '{}' for host {} into maintenance mode",
-            definition.getDefinitionName(), hostName, ambariException);
-      }
+    MaintenanceState currentState = currentAlert.getMaintenanceState();
+    if (currentState == maintenanceState) {
+      return;
     }
+
+    currentAlert.setMaintenanceState(maintenanceState);
+    m_alertsDao.merge(currentAlert);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9eaacd3d/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/AlertMaintenanceModeListenerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/AlertMaintenanceModeListenerTest.java
b/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/AlertMaintenanceModeListenerTest.java
new file mode 100644
index 0000000..7757cdf
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/events/listeners/upgrade/AlertMaintenanceModeListenerTest.java
@@ -0,0 +1,232 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.events.listeners.upgrade;
+
+import static org.easymock.EasyMock.createNiceMock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+
+import org.apache.ambari.server.events.MaintenanceModeEvent;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.orm.DBAccessor;
+import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
+import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
+import org.apache.ambari.server.orm.dao.AlertsDAO;
+import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
+import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+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.ServiceComponentHost;
+import org.apache.ambari.server.utils.EventBusSynchronizer;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.Binder;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+
+/**
+ *
+ */
+public class AlertMaintenanceModeListenerTest {
+
+  private static final String HOSTNAME = "c6401.ambari.apache.org";
+  private static final String SERVICE = "HDFS";
+  private static final String COMPONENT = "NAMENODE";
+
+  @Inject
+  private AmbariEventPublisher m_eventPublisher;
+
+  @Inject
+  private AlertsDAO m_alertsDAO;
+
+  private Injector injector;
+
+  /**
+   *
+   */
+  @Before
+  public void setup() throws Exception {
+    injector = Guice.createInjector(Modules.override(new InMemoryDefaultTestModule()).with(
+        new MockModule()));
+
+    // !!! need a synchronous op for testing
+    EventBusSynchronizer.synchronizeAmbariEventPublisher(injector);
+    injector.injectMembers(this);
+  }
+
+  /**
+   * Tests that only the host alert has its maintenance mode changed.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testHostMaintenanceMode() throws Exception {
+    List<AlertCurrentEntity> alerts = getMockAlerts("HOST");
+
+    AlertCurrentEntity hostAlert = alerts.get(0);
+    AlertCurrentEntity serviceAlert = alerts.get(1);
+    AlertCurrentEntity componentAlert = alerts.get(2);
+
+    EasyMock.expect(hostAlert.getMaintenanceState()).andReturn(MaintenanceState.OFF).atLeastOnce();
+    hostAlert.setMaintenanceState(MaintenanceState.ON);
+    EasyMock.expectLastCall().once();
+
+    EasyMock.expect(m_alertsDAO.merge(hostAlert)).andReturn(hostAlert).once();
+
+    Host host = EasyMock.createNiceMock(Host.class);
+    EasyMock.expect(host.getHostName()).andReturn(HOSTNAME).atLeastOnce();
+
+    EasyMock.replay(hostAlert, serviceAlert, componentAlert, host, m_alertsDAO);
+
+    MaintenanceModeEvent hostEvent = new MaintenanceModeEvent(MaintenanceState.ON, host);
+    m_eventPublisher.publish(hostEvent);
+
+    EasyMock.verify(hostAlert, serviceAlert, componentAlert, host, m_alertsDAO);
+  }
+
+  @Test
+  /**
+   * Tests that only the service alert has its maintenance mode changed.
+   *
+   * @throws Exception
+   */
+  public void testServiceMaintenanceMode() throws Exception {
+    List<AlertCurrentEntity> alerts = getMockAlerts("SERVICE");
+
+    AlertCurrentEntity hostAlert = alerts.get(0);
+    AlertCurrentEntity serviceAlert = alerts.get(1);
+    AlertCurrentEntity componentAlert = alerts.get(2);
+
+    EasyMock.expect(serviceAlert.getMaintenanceState()).andReturn(MaintenanceState.OFF).atLeastOnce();
+    serviceAlert.setMaintenanceState(MaintenanceState.ON);
+    EasyMock.expectLastCall().once();
+
+    EasyMock.expect(m_alertsDAO.merge(serviceAlert)).andReturn(serviceAlert).once();
+
+    Service service = EasyMock.createNiceMock(Service.class);
+    EasyMock.expect(service.getName()).andReturn(SERVICE).atLeastOnce();
+
+    EasyMock.replay(hostAlert, serviceAlert, componentAlert, service, m_alertsDAO);
+
+    MaintenanceModeEvent serviceEvent = new MaintenanceModeEvent(MaintenanceState.ON, service);
+    m_eventPublisher.publish(serviceEvent);
+
+    EasyMock.verify(hostAlert, serviceAlert, componentAlert, service, m_alertsDAO);
+  }
+
+  @Test
+  public void testComponentMaintenanceMode() throws Exception {
+    List<AlertCurrentEntity> alerts = getMockAlerts("SCH");
+
+    AlertCurrentEntity hostAlert = alerts.get(0);
+    AlertCurrentEntity serviceAlert = alerts.get(1);
+    AlertCurrentEntity componentAlert = alerts.get(2);
+
+    EasyMock.expect(componentAlert.getMaintenanceState()).andReturn(MaintenanceState.OFF).atLeastOnce();
+    componentAlert.setMaintenanceState(MaintenanceState.ON);
+    EasyMock.expectLastCall().once();
+
+    EasyMock.expect(m_alertsDAO.merge(componentAlert)).andReturn(componentAlert).once();
+
+    ServiceComponentHost serviceComponentHost = EasyMock.createNiceMock(ServiceComponentHost.class);
+    EasyMock.expect(serviceComponentHost.getHostName()).andReturn(HOSTNAME).atLeastOnce();
+    EasyMock.expect(serviceComponentHost.getServiceName()).andReturn(SERVICE).atLeastOnce();
+    EasyMock.expect(serviceComponentHost.getServiceComponentName()).andReturn(COMPONENT).atLeastOnce();
+
+    EasyMock.replay(hostAlert, serviceAlert, componentAlert, serviceComponentHost, m_alertsDAO);
+
+    MaintenanceModeEvent serviceComponentHostEvent = new MaintenanceModeEvent(MaintenanceState.ON,
+        serviceComponentHost);
+
+    m_eventPublisher.publish(serviceComponentHostEvent);
+
+    EasyMock.verify(hostAlert, serviceAlert, componentAlert, serviceComponentHost, m_alertsDAO);
+  }
+
+  private List<AlertCurrentEntity> getMockAlerts(String testType) {
+    AlertCurrentEntity hostAlert = EasyMock.createStrictMock(AlertCurrentEntity.class);
+    AlertCurrentEntity serviceAlert = EasyMock.createStrictMock(AlertCurrentEntity.class);
+    AlertCurrentEntity componentAlert = EasyMock.createStrictMock(AlertCurrentEntity.class);
+
+    AlertHistoryEntity hostHistory = EasyMock.createStrictMock(AlertHistoryEntity.class);
+    AlertHistoryEntity serviceHistory = EasyMock.createStrictMock(AlertHistoryEntity.class);
+    AlertHistoryEntity componentHistory = EasyMock.createStrictMock(AlertHistoryEntity.class);
+
+    EasyMock.expect(hostAlert.getAlertHistory()).andReturn(hostHistory).atLeastOnce();
+    EasyMock.expect(serviceAlert.getAlertHistory()).andReturn(serviceHistory).atLeastOnce();
+    EasyMock.expect(componentAlert.getAlertHistory()).andReturn(componentHistory).atLeastOnce();
+
+    EasyMock.expect(hostHistory.getHostName()).andReturn(HOSTNAME).atLeastOnce();
+    EasyMock.expect(hostHistory.getServiceName()).andReturn(null).atLeastOnce();
+    EasyMock.expect(hostHistory.getComponentName()).andReturn(null).atLeastOnce();
+
+    EasyMock.expect(serviceHistory.getHostName()).andReturn(null).atLeastOnce();
+    EasyMock.expect(serviceHistory.getServiceName()).andReturn(SERVICE).atLeastOnce();
+    EasyMock.expect(serviceHistory.getComponentName()).andReturn(null).atLeastOnce();
+
+    if (testType.equals("SCH")) {
+      EasyMock.expect(componentHistory.getHostName()).andReturn(HOSTNAME).atLeastOnce();
+      EasyMock.expect(componentHistory.getServiceName()).andReturn(SERVICE).atLeastOnce();
+      EasyMock.expect(componentHistory.getComponentName()).andReturn(COMPONENT).atLeastOnce();
+    } else {
+      EasyMock.expect(componentHistory.getHostName()).andReturn(null).atLeastOnce();
+      EasyMock.expect(componentHistory.getServiceName()).andReturn(null).atLeastOnce();
+      EasyMock.expect(componentHistory.getComponentName()).andReturn(COMPONENT).atLeastOnce();
+    }
+
+    List<AlertCurrentEntity> currentAlerts = new ArrayList<AlertCurrentEntity>();
+    currentAlerts.add(hostAlert);
+    currentAlerts.add(serviceAlert);
+    currentAlerts.add(componentAlert);
+
+    EasyMock.expect(m_alertsDAO.findCurrent()).andReturn(currentAlerts).atLeastOnce();
+
+    EasyMock.replay(hostHistory, serviceHistory, componentHistory);
+    return currentAlerts;
+  }
+
+  /**
+  *
+  */
+  private class MockModule implements Module {
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void configure(Binder binder) {
+      Cluster cluster = EasyMock.createNiceMock(Cluster.class);
+      binder.bind(Clusters.class).toInstance(createNiceMock(Clusters.class));
+      binder.bind(DBAccessor.class).toInstance(createNiceMock(DBAccessor.class));
+      binder.bind(Cluster.class).toInstance(cluster);
+      binder.bind(AlertDefinitionDAO.class).toInstance(createNiceMock(AlertDefinitionDAO.class));
+      binder.bind(AlertsDAO.class).toInstance(createNiceMock(AlertsDAO.class));
+      binder.bind(EntityManager.class).toInstance(createNiceMock(EntityManager.class));
+    }
+  }
+}


Mime
View raw message