You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mp...@apache.org on 2015/06/13 17:46:48 UTC

[2/2] ambari git commit: AMBARI-11841. Alerts received in single heartbeat should be processed in batch. (mpapirkovskyy)

AMBARI-11841. Alerts received in single heartbeat should be processed in batch. (mpapirkovskyy)


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

Branch: refs/heads/branch-2.1
Commit: a8863851e81ee281ed26b7f06ca1c4f8e6a94d98
Parents: fade596
Author: Myroslav Papirkovskyy <mp...@hortonworks.com>
Authored: Wed Jun 10 19:25:32 2015 +0300
Committer: Myroslav Papirkovskyy <mp...@hortonworks.com>
Committed: Sat Jun 13 18:44:28 2015 +0300

----------------------------------------------------------------------
 .../ambari/server/agent/HeartBeatHandler.java   |  17 +-
 .../apache/ambari/server/events/AlertEvent.java |  20 ++
 .../server/events/AlertReceivedEvent.java       |   9 +-
 .../listeners/alerts/AlertReceivedListener.java | 208 +++++++++++++------
 .../orm/entities/AlertDefinitionEntity.java     | 105 ++++------
 .../server/state/cluster/ClustersImpl.java      |   5 +-
 .../apache/ambari/server/orm/OrmTestHelper.java |   9 +
 .../state/alerts/InitialAlertEventTest.java     |   1 +
 .../state/cluster/AlertDataManagerTest.java     |   9 +-
 9 files changed, 232 insertions(+), 151 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
index c1998a9..029341c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
@@ -309,22 +309,9 @@ public class HeartBeatHandler {
     }
 
     if (null != heartbeat.getAlerts()) {
-      for (Alert alert : heartbeat.getAlerts()) {
-        if (null == alert.getHostName()) {
-          alert.setHostName(hostname);
-        }
+      AlertEvent event = new AlertReceivedEvent(heartbeat.getAlerts());
+      alertEventPublisher.publish(event);
 
-        try {
-          Cluster cluster = clusterFsm.getCluster(alert.getCluster());
-          AlertEvent event = new AlertReceivedEvent(cluster.getClusterId(),
-              alert);
-          alertEventPublisher.publish(event);
-        } catch (AmbariException ambariException) {
-          LOG.warn(
-              "Unable to process alerts because the cluster {} does not exist",
-              alert.getCluster());
-        }
-      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java
index 767cb6b..4860ffa 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java
@@ -19,6 +19,9 @@ package org.apache.ambari.server.events;
 
 import org.apache.ambari.server.state.Alert;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * The {@link AlertEvent} class is the base for all events related to alerts.
  */
@@ -26,6 +29,7 @@ public abstract class AlertEvent {
 
   protected long m_clusterId;
   protected Alert m_alert;
+  protected List<Alert> m_alerts;
 
   /**
    * Constructor.
@@ -38,6 +42,10 @@ public abstract class AlertEvent {
     m_alert = alert;
   }
 
+  public AlertEvent(List<Alert> m_alerts) {
+    this.m_alerts = m_alerts;
+  }
+
   /**
    * Gets the cluster ID that the alert belongs to.
    *
@@ -55,4 +63,16 @@ public abstract class AlertEvent {
   public Alert getAlert(){
     return m_alert;
   }
+
+  /**
+   * Gets list of alerts this event was created for
+   * @return
+   */
+  public List<Alert> getAlerts() {
+    if (m_alerts != null) {
+      return m_alerts;
+    } else {
+      return Collections.singletonList(m_alert);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java
index 558c9da..23d29bb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java
@@ -19,6 +19,8 @@ package org.apache.ambari.server.events;
 
 import org.apache.ambari.server.state.Alert;
 
+import java.util.List;
+
 /**
  * The {@link AlertReceivedEvent} is fired when an {@link Alert} is received or
  * generated.
@@ -35,6 +37,10 @@ public final class AlertReceivedEvent extends AlertEvent {
     super(clusterId, alert);
   }
 
+  public AlertReceivedEvent(List<Alert> alerts) {
+    super(alerts);
+  }
+
   /**
    * {@inheritDoc}
    */
@@ -42,8 +48,7 @@ public final class AlertReceivedEvent extends AlertEvent {
   public String toString() {
     StringBuilder buffer = new StringBuilder("AlertReceivedEvent{ ");
     buffer.append("cluserId=").append(m_clusterId);
-    buffer.append(", alert=").append(m_alert);
-
+    buffer.append(", alerts=").append(getAlerts());
     buffer.append("}");
     return buffer.toString();
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/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 f28929a..53b0cb5 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
@@ -17,6 +17,11 @@
  */
 package org.apache.ambari.server.events.listeners.alerts;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.inject.persist.Transactional;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.EagerSingleton;
 import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
@@ -60,16 +65,16 @@ public class AlertReceivedListener {
   private static final Logger LOG = LoggerFactory.getLogger(AlertReceivedListener.class);
 
   @Inject
-  private AlertsDAO m_alertsDao;
+  AlertsDAO m_alertsDao;
 
   @Inject
-  private AlertDefinitionDAO m_definitionDao;
+  AlertDefinitionDAO m_definitionDao;
 
   /**
    * Used for looking up whether an alert has a valid service/component/host
    */
   @Inject
-  private Provider<Clusters> m_clusters;
+  Provider<Clusters> m_clusters;
 
   /**
    * Receives and publishes {@link AlertEvent} instances.
@@ -101,102 +106,175 @@ public class AlertReceivedListener {
       LOG.debug(event.toString());
     }
 
-    Alert alert = event.getAlert();
+    //play around too many commits
+    List<Alert> alerts = event.getAlerts();
 
-    // jobs that were running when a service/component/host was changed
-    // which invalidate the alert should not be reported
-    if (!isValid(alert)) {
-      return;
-    }
+    Map<Alert, AlertCurrentEntity> toCreate = new HashMap<Alert, AlertCurrentEntity>();
+    Map<Alert, AlertCurrentEntity> toMerge = new HashMap<Alert, AlertCurrentEntity>();
+    Map<Alert, AlertCurrentEntity> toCreateHistoryAndMerge = new HashMap<Alert, AlertCurrentEntity>();
+    Map<Alert, AlertState> oldStates = new HashMap<Alert, AlertState>();
 
-    long clusterId = event.getClusterId();
+    for (Alert alert : alerts) {
+      // jobs that were running when a service/component/host was changed
+      // which invalidate the alert should not be reported
+      if (!isValid(alert)) {
+        continue;
+      }
 
-    AlertDefinitionEntity definition = m_definitionDao.findByName(clusterId,
+      Long clusterId = getClusterIdByName(alert.getCluster());
+      if (clusterId == null) {
+        LOG.warn("Null cluster id is not supported for alerts as of now"); //based on listener implementation
+        continue;
+      }
+
+      AlertDefinitionEntity definition = m_definitionDao.findByName(clusterId,
         alert.getName());
 
-    if (null == definition) {
-      LOG.warn(
+      if (null == definition) {
+        LOG.warn(
           "Received an alert for {} which is a definition that does not exist anymore",
           alert.getName());
 
-      return;
-    }
+        continue;
+      }
 
-    // it's possible that a definition which is disabled will still have a
-    // running alert returned; this will ensure we don't record it
-    if (!definition.getEnabled()) {
-      LOG.debug(
+      // it's possible that a definition which is disabled will still have a
+      // running alert returned; this will ensure we don't record it
+      if (!definition.getEnabled()) {
+        LOG.debug(
           "Received an alert for {} which is disabled. No more alerts should be received for this definition.",
           alert.getName());
 
-      return;
-    }
+        continue;
+      }
 
-    AlertCurrentEntity current;
+      AlertCurrentEntity current;
 
-    if (StringUtils.isBlank(alert.getHostName()) || definition.isHostIgnored()) {
-      current = m_alertsDao.findCurrentByNameNoHost(clusterId, alert.getName());
-    } else {
-      current = m_alertsDao.findCurrentByHostAndName(clusterId, alert.getHostName(),
+      if (StringUtils.isBlank(alert.getHostName()) || definition.isHostIgnored()) {
+        current = m_alertsDao.findCurrentByNameNoHost(clusterId, alert.getName());
+      } else {
+        current = m_alertsDao.findCurrentByHostAndName(clusterId, alert.getHostName(),
           alert.getName());
-    }
+      }
 
-    if (null == current) {
-      AlertHistoryEntity history = createHistory(clusterId, definition, alert);
+      if (null == current) {
+        AlertHistoryEntity history = createHistory(clusterId, definition, alert);
 
-      current = new AlertCurrentEntity();
-      current.setMaintenanceState(MaintenanceState.OFF);
-      current.setAlertHistory(history);
-      current.setLatestTimestamp(alert.getTimestamp());
-      current.setOriginalTimestamp(alert.getTimestamp());
-      m_alertsDao.create(current);
+        current = new AlertCurrentEntity();
+        current.setMaintenanceState(MaintenanceState.OFF);
+        current.setAlertHistory(history);
+        current.setLatestTimestamp(alert.getTimestamp());
+        current.setOriginalTimestamp(alert.getTimestamp());
 
-      // broadcast the initial alert being received
-      InitialAlertEvent initialAlertEvent = new InitialAlertEvent(
-          event.getClusterId(), event.getAlert(), current);
+        toCreate.put(alert, current);
 
-      m_alertEventPublisher.publish(initialAlertEvent);
-    } else if (alert.getState() == current.getAlertHistory().getAlertState()) {
-      current.setLatestTimestamp(alert.getTimestamp());
-      current.setLatestText(alert.getText());
-      m_alertsDao.merge(current);
-    } else {
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(
+      } else if (alert.getState() == current.getAlertHistory().getAlertState()) {
+        current.setLatestTimestamp(alert.getTimestamp());
+        current.setLatestText(alert.getText());
+        toMerge.put(alert, current);
+
+      } else {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug(
             "Alert State Changed: CurrentId {}, CurrentTimestamp {}, HistoryId {}, HistoryState {}",
             current.getAlertId(), current.getLatestTimestamp(),
             current.getAlertHistory().getAlertId(),
             current.getAlertHistory().getAlertState());
-      }
+        }
 
-      AlertHistoryEntity oldHistory = current.getAlertHistory();
-      AlertState oldState = oldHistory.getAlertState();
+        AlertHistoryEntity oldHistory = current.getAlertHistory();
+        AlertState oldState = oldHistory.getAlertState();
 
-      // insert history, update current
-      AlertHistoryEntity history = createHistory(clusterId,
+        // insert history, update current
+        AlertHistoryEntity history = createHistory(clusterId,
           oldHistory.getAlertDefinition(), alert);
 
-      current.setLatestTimestamp(alert.getTimestamp());
-      current.setOriginalTimestamp(alert.getTimestamp());
-      current.setLatestText(alert.getText());
+        current.setLatestTimestamp(alert.getTimestamp());
+        current.setOriginalTimestamp(alert.getTimestamp());
+        current.setLatestText(alert.getText());
 
-      current = m_alertsDao.mergeAlertCurrentWithAlertHistory(current, history);
+        current.setAlertHistory(history);
 
-      if (LOG.isDebugEnabled()) {
-        LOG.debug(
-            "Alert State Merged: CurrentId {}, CurrentTimestamp {}, HistoryId {}, HistoryState {}",
-            current.getAlertId(), current.getLatestTimestamp(),
-            current.getAlertHistory().getAlertId(),
-            current.getAlertHistory().getAlertState());
+        toCreateHistoryAndMerge.put(alert, current);
+        oldStates.put(alert, oldState);
+
+      }
+    }
+
+    saveEntities(toCreate, toMerge, toCreateHistoryAndMerge);
+
+    //broadcast events
+    for (Map.Entry<Alert, AlertCurrentEntity> entry : toCreate.entrySet()) {
+      Alert alert = entry.getKey();
+      AlertCurrentEntity entity = entry.getValue();
+      Long clusterId = getClusterIdByName(alert.getCluster());
+      if (clusterId == null) {
+        //super rare case, cluster was removed after isValid() check
+        LOG.error("Unable to process alert {} for an invalid cluster named {}",
+          alert.getName(), alert.getCluster());
+        continue;
+      }
+
+      InitialAlertEvent initialAlertEvent = new InitialAlertEvent(
+        clusterId, alert, entity);
+
+      m_alertEventPublisher.publish(initialAlertEvent);
+
+    }
+
+    for (Map.Entry<Alert, AlertCurrentEntity> entry : toCreateHistoryAndMerge.entrySet()) {
+      Alert alert = entry.getKey();
+      AlertCurrentEntity entity = entry.getValue();
+      Long clusterId = getClusterIdByName(alert.getCluster());
+      if (clusterId == null) {
+        //super rare case, cluster was removed after isValid() check
+        LOG.error("Unable to process alert {} for an invalid cluster named {}",
+          alert.getName(), alert.getCluster());
+        continue;
       }
 
-      // broadcast the alert changed event for other subscribers
-      AlertStateChangeEvent alertChangedEvent = new AlertStateChangeEvent(
-          event.getClusterId(), event.getAlert(), current,
-          oldState);
+      AlertStateChangeEvent alertChangedEvent = new AlertStateChangeEvent(clusterId, alert, entity,
+        oldStates.get(alert));
 
       m_alertEventPublisher.publish(alertChangedEvent);
     }
+
+  }
+
+  Long getClusterIdByName(String clusterName) {
+    try {
+      return m_clusters.get().getCluster(clusterName).getClusterId();
+    } catch (AmbariException e) {
+      LOG.warn("Cluster lookup failed for clusterName={}", clusterName);
+      return null;
+    }
+  }
+
+  @Transactional
+  void saveEntities(Map<Alert, AlertCurrentEntity> toCreate, Map<Alert, AlertCurrentEntity> toMerge,
+                    Map<Alert, AlertCurrentEntity> toCreateHistoryAndMerge) {
+    for (Map.Entry<Alert, AlertCurrentEntity> entry : toCreate.entrySet()) {
+      AlertCurrentEntity entity = entry.getValue();
+      m_alertsDao.create(entity);
+    }
+
+    for (AlertCurrentEntity entity : toMerge.values()) {
+      m_alertsDao.merge(entity);
+    }
+
+    for (Map.Entry<Alert, AlertCurrentEntity> entry : toCreateHistoryAndMerge.entrySet()) {
+      AlertCurrentEntity entity = entry.getValue();
+      m_alertsDao.create(entity.getAlertHistory());
+      m_alertsDao.merge(entity);
+
+      if (LOG.isDebugEnabled()) {
+        LOG.debug(
+          "Alert State Merged: CurrentId {}, CurrentTimestamp {}, HistoryId {}, HistoryState {}",
+          entity.getAlertId(), entity.getLatestTimestamp(),
+          entity.getAlertHistory().getAlertId(),
+          entity.getAlertHistory().getAlertState());
+      }
+    }
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
index c20fd25..16f62e3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertDefinitionEntity.java
@@ -22,27 +22,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
 
-import javax.persistence.Basic;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EntityManager;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.Lob;
-import javax.persistence.ManyToMany;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.PreRemove;
-import javax.persistence.Table;
-import javax.persistence.TableGenerator;
-import javax.persistence.UniqueConstraint;
+import javax.persistence.*;
 
 import org.apache.ambari.server.state.alert.Scope;
 import org.apache.ambari.server.state.alert.SourceType;
@@ -54,17 +34,22 @@ import org.apache.ambari.server.state.alert.SourceType;
  */
 @Entity
 @Table(name = "alert_definition", uniqueConstraints = @UniqueConstraint(columnNames = {
-    "cluster_id", "definition_name" }))
+  "cluster_id", "definition_name"}))
 @TableGenerator(name = "alert_definition_id_generator", table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value", pkColumnValue = "alert_definition_id_seq", initialValue = 0)
 @NamedQueries({
-    @NamedQuery(name = "AlertDefinitionEntity.findAll", query = "SELECT ad FROM AlertDefinitionEntity ad"),
-    @NamedQuery(name = "AlertDefinitionEntity.findAllInCluster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.clusterId = :clusterId"),
-    @NamedQuery(name = "AlertDefinitionEntity.findAllEnabledInCluster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.clusterId = :clusterId AND ad.enabled = 1"),
-    @NamedQuery(name = "AlertDefinitionEntity.findByName", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.definitionName = :definitionName AND ad.clusterId = :clusterId"),
-    @NamedQuery(name = "AlertDefinitionEntity.findByService", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName = :serviceName AND ad.clusterId = :clusterId"),
-    @NamedQuery(name = "AlertDefinitionEntity.findByServiceAndComponent", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName = :serviceName AND ad.componentName = :componentName AND ad.clusterId = :clusterId"),
-    @NamedQuery(name = "AlertDefinitionEntity.findByServiceMaster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName IN :services AND ad.scope = :scope AND ad.clusterId = :clusterId AND ad.componentName IS NULL"),
-    @NamedQuery(name = "AlertDefinitionEntity.findByIds", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.definitionId IN :definitionIds") })
+  @NamedQuery(name = "AlertDefinitionEntity.findAll", query = "SELECT ad FROM AlertDefinitionEntity ad"),
+  @NamedQuery(name = "AlertDefinitionEntity.findAllInCluster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.clusterId = :clusterId"),
+  @NamedQuery(name = "AlertDefinitionEntity.findAllEnabledInCluster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.clusterId = :clusterId AND ad.enabled = 1"),
+  @NamedQuery(name = "AlertDefinitionEntity.findByName", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.definitionName = :definitionName AND ad.clusterId = :clusterId",
+    hints = {
+      @QueryHint(name = "eclipselink.query-results-cache", value = "true"),
+      @QueryHint(name = "eclipselink.query-results-cache.size", value = "5000")
+    }),
+  @NamedQuery(name = "AlertDefinitionEntity.findByService", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName = :serviceName AND ad.clusterId = :clusterId"),
+  @NamedQuery(name = "AlertDefinitionEntity.findByServiceAndComponent", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName = :serviceName AND ad.componentName = :componentName AND ad.clusterId = :clusterId"),
+  @NamedQuery(name = "AlertDefinitionEntity.findByServiceMaster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName IN :services AND ad.scope = :scope AND ad.clusterId = :clusterId AND ad.componentName IS NULL"),
+  @NamedQuery(name = "AlertDefinitionEntity.findByIds", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.definitionId IN :definitionIds")})
+
 public class AlertDefinitionEntity {
 
   @Id
@@ -124,8 +109,8 @@ public class AlertDefinitionEntity {
   /**
    * Bi-directional many-to-many association to {@link AlertGroupEntity}
    */
-  @ManyToMany(mappedBy = "alertDefinitions", cascade = { CascadeType.PERSIST,
-      CascadeType.MERGE, CascadeType.REFRESH })
+  @ManyToMany(mappedBy = "alertDefinitions", cascade = {CascadeType.PERSIST,
+    CascadeType.MERGE, CascadeType.REFRESH})
   private Set<AlertGroupEntity> alertGroups;
 
   /**
@@ -146,8 +131,7 @@ public class AlertDefinitionEntity {
   /**
    * Sets the unique identifier for this alert definition.
    *
-   * @param definitionId
-   *          the ID (not {@code null}).
+   * @param definitionId the ID (not {@code null}).
    */
   public void setDefinitionId(Long definitionId) {
     this.definitionId = definitionId;
@@ -168,8 +152,7 @@ public class AlertDefinitionEntity {
    * Sets the source of the alert, typically in JSON, that defines the type of
    * the alert and its properties.
    *
-   * @param alertSource
-   *          the alert source (not {@code null}).
+   * @param alertSource the alert source (not {@code null}).
    */
   public void setSource(String alertSource) {
     source = alertSource;
@@ -191,8 +174,7 @@ public class AlertDefinitionEntity {
    * cluster has their own set of alert definitions that are not shared with any
    * other cluster.
    *
-   * @param clusterId
-   *          the ID of the cluster (not {@code null}).
+   * @param clusterId the ID of the cluster (not {@code null}).
    */
   public void setClusterId(Long clusterId) {
     this.clusterId = clusterId;
@@ -230,8 +212,7 @@ public class AlertDefinitionEntity {
    * Sets the component name that this alert is associated with, if any. Some
    * alerts are scoped at the service level and will not have a component name.
    *
-   * @param componentName
-   *          the component name or {@code null} if none.
+   * @param componentName the component name or {@code null} if none.
    */
   public void setComponentName(String componentName) {
     this.componentName = componentName;
@@ -251,8 +232,7 @@ public class AlertDefinitionEntity {
    * Sets the scope of the alert definition. The scope is defined as either
    * being for a {@link Scope#SERVICE} or {@link Scope#HOST}.
    *
-   * @param scope
-   *          the scope to set, or {@code null} for none.
+   * @param scope the scope to set, or {@code null} for none.
    */
   public void setScope(Scope scope) {
     this.scope = scope;
@@ -272,8 +252,7 @@ public class AlertDefinitionEntity {
    * Sets the name of this alert definition. Alert definition names are unique
    * within a cluster.
    *
-   * @param definitionName
-   *          the name of the alert definition (not {@code null}).
+   * @param definitionName the name of the alert definition (not {@code null}).
    */
   public void setDefinitionName(String definitionName) {
     this.definitionName = definitionName;
@@ -285,7 +264,7 @@ public class AlertDefinitionEntity {
    * be triggered and no alert data will be collected.
    *
    * @return {@code true} if this alert definition is enabled, {@code false}
-   *         otherwise.
+   * otherwise.
    */
   public boolean getEnabled() {
     return enabled == Integer.valueOf(0) ? false : true;
@@ -294,9 +273,8 @@ public class AlertDefinitionEntity {
   /**
    * Sets whether this alert definition is enabled.
    *
-   * @param enabled
-   *          {@code true} if this alert definition is enabled, {@code false}
-   *          otherwise.
+   * @param enabled {@code true} if this alert definition is enabled, {@code false}
+   *                otherwise.
    */
   public void setEnabled(boolean enabled) {
     this.enabled = enabled ? Integer.valueOf(1) : Integer.valueOf(0);
@@ -307,8 +285,8 @@ public class AlertDefinitionEntity {
    * alert and combine them all into a single alert entry.
    *
    * @return {@code true} if this alert definition is to ignore hosts and
-   *         combine all alert instances into a single entry, {@code false}
-   *         otherwise.
+   * combine all alert instances into a single entry, {@code false}
+   * otherwise.
    */
   public boolean isHostIgnored() {
     return ignoreHost == Integer.valueOf(0) ? false : true;
@@ -318,10 +296,9 @@ public class AlertDefinitionEntity {
    * Sets whether this alert definition will ignore the hosts reporting the
    * alert and combine them all into a single alert entry.
    *
-   * @param ignoreHost
-   *          {@code true} if this alert definition is to ignore hosts and
-   *          combine all alert instances into a single entry, {@code false}
-   *          otherwise.
+   * @param ignoreHost {@code true} if this alert definition is to ignore hosts and
+   *                   combine all alert instances into a single entry, {@code false}
+   *                   otherwise.
    */
   public void setHostIgnored(boolean ignoreHost) {
     this.ignoreHost = ignoreHost ? Integer.valueOf(1) : Integer.valueOf(0);
@@ -341,8 +318,7 @@ public class AlertDefinitionEntity {
    * Gets the unique hash for the current state of this definition. If a
    * property of this definition changes, a new hash is calculated.
    *
-   * @param hash
-   *          the unique hash to set or {@code null} for none.
+   * @param hash the unique hash to set or {@code null} for none.
    */
   public void setHash(String hash) {
     this.hash = hash;
@@ -360,8 +336,7 @@ public class AlertDefinitionEntity {
   /**
    * Sets the alert trigger interval, in seconds.
    *
-   * @param scheduleInterval
-   *          the interval, in seconds.
+   * @param scheduleInterval the interval, in seconds.
    */
   public void setScheduleInterval(Integer scheduleInterval) {
     this.scheduleInterval = scheduleInterval;
@@ -381,8 +356,7 @@ public class AlertDefinitionEntity {
    * Gets the name of the service that this alert definition is associated with.
    * Every alert definition is associated with exactly one service.
    *
-   * @param serviceName
-   *          the name of the service (not {@code null}).
+   * @param serviceName the name of the service (not {@code null}).
    */
   public void setServiceName(String serviceName) {
     this.serviceName = serviceName;
@@ -414,8 +388,7 @@ public class AlertDefinitionEntity {
   /**
    * Sets the alert groups that this alert definition is associated with.
    *
-   * @param alertGroups
-   *          the groups, or {@code null} for none.
+   * @param alertGroups the groups, or {@code null} for none.
    */
   public void setAlertGroups(Set<AlertGroupEntity> alertGroups) {
     this.alertGroups = alertGroups;
@@ -424,8 +397,7 @@ public class AlertDefinitionEntity {
   /**
    * Sets a human readable label for this alert definition.
    *
-   * @param label
-   *          the label or {@code null} if none.
+   * @param label the label or {@code null} if none.
    */
   public void setLabel(String label) {
     this.label = label;
@@ -452,8 +424,7 @@ public class AlertDefinitionEntity {
   /**
    * Gets the optional description for this alert definition.
    *
-   * @param description
-   *          the description to set or {@code null} for none.
+   * @param description the description to set or {@code null} for none.
    */
   public void setDescription(String description) {
     this.description = description;
@@ -522,7 +493,7 @@ public class AlertDefinitionEntity {
     AlertDefinitionEntity that = (AlertDefinitionEntity) object;
 
     if (definitionId != null ? !definitionId.equals(that.definitionId)
-        : that.definitionId != null) {
+      : that.definitionId != null) {
       return false;
     }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
index 85d5307..000a300 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClustersImpl.java
@@ -256,7 +256,10 @@ public class ClustersImpl implements Clusters {
       throws AmbariException {
     checkLoaded();
 
-    Cluster cluster = clusters.get(clusterName);
+    Cluster cluster = null;
+    if (clusterName != null) {
+      cluster = clusters.get(clusterName);
+    }
     if (null == cluster) {
       throw new ClusterNotFoundException(clusterName);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
index aee0a55..738eb42 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java
@@ -34,6 +34,7 @@ import java.util.UUID;
 
 import javax.persistence.EntityManager;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
@@ -393,6 +394,14 @@ public class OrmTestHelper {
     clusters.mapHostToCluster(hostName, cluster.getClusterName());
   }
 
+  public void addHostComponent(Cluster cluster, String hostName, String serviceName, String componentName) throws AmbariException {
+    Service service = cluster.getService(serviceName);
+    ServiceComponent serviceComponent = service.getServiceComponent(componentName);
+    ServiceComponentHost serviceComponentHost = serviceComponent.addServiceComponentHost(hostName);
+    serviceComponentHost.setDesiredState(State.INSTALLED);
+    serviceComponentHost.persist();
+  }
+
   /**
    * Calls {@link Service#persist()} to mock a service install along with
    * creating a single {@link Host} and {@link ServiceComponentHost}.

http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java
index f3694c9..3ddeb2a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/alerts/InitialAlertEventTest.java
@@ -131,6 +131,7 @@ public class InitialAlertEventTest {
     Alert alert = new Alert(definition.getDefinitionName(), null,
         definition.getServiceName(), definition.getComponentName(), null,
         AlertState.OK);
+    alert.setCluster(m_clusterName);
 
     AlertReceivedEvent event = new AlertReceivedEvent(m_cluster.getClusterId(),
         alert);

http://git-wip-us.apache.org/repos/asf/ambari/blob/a8863851/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java
index 6093dd7..e8ecd09 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java
@@ -87,7 +87,7 @@ public class AlertDataManagerTest {
 
   private static final String ALERT_DEFINITION = "Alert Definition 1";
   private static final String SERVICE = "HDFS";
-  private static final String COMPONENT = "component1";
+  private static final String COMPONENT = "DATANODE";
   private static final String HOST1 = "h1";
   private static final String HOST2 = "h2";
   private static final String ALERT_LABEL = "My Label";
@@ -125,6 +125,7 @@ public class AlertDataManagerTest {
         m_componentFactory, m_schFactory, HOST1);
 
     m_helper.addHost(m_clusters, m_cluster, HOST2);
+    m_helper.addHostComponent(m_cluster, HOST2, SERVICE, COMPONENT);
 
     // create 5 definitions
     for (int i = 0; i < 5; i++) {
@@ -157,11 +158,14 @@ public class AlertDataManagerTest {
     alert1.setLabel(ALERT_LABEL);
     alert1.setText("Component component1 is OK");
     alert1.setTimestamp(1L);
+    alert1.setCluster(m_cluster.getClusterName());
 
     Alert alert2 = new Alert(ALERT_DEFINITION, null, SERVICE, COMPONENT, HOST2,
         AlertState.CRITICAL);
     alert2.setLabel(ALERT_LABEL);
     alert2.setText("Component component2 is not OK");
+    alert2.setCluster(m_cluster.getClusterName());
+
 
     AlertReceivedListener listener = m_injector.getInstance(AlertReceivedListener.class);
 
@@ -203,6 +207,7 @@ public class AlertDataManagerTest {
     alert3.setLabel(ALERT_LABEL);
     alert3.setText("Component component1 is OK");
     alert3.setTimestamp(2L);
+    alert3.setCluster(m_cluster.getClusterName());
 
     AlertReceivedEvent event3 = new AlertReceivedEvent(
         m_cluster.getClusterId(),
@@ -235,6 +240,8 @@ public class AlertDataManagerTest {
     alert4.setLabel(ALERT_LABEL);
     alert4.setText("Component component1 is about to go down");
     alert4.setTimestamp(3L);
+    alert4.setCluster(m_cluster.getClusterName());
+
 
     AlertReceivedEvent event4 = new AlertReceivedEvent(
         m_cluster.getClusterId(),