You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2014/08/22 22:22:05 UTC

git commit: AMBARI-6994 - Alerts: Populate Alert Definition Table And Agents (jonathanhurley)

Repository: ambari
Updated Branches:
  refs/heads/branch-alerts-dev 2ac6c726e -> 100fb9c0a


AMBARI-6994 - Alerts: Populate Alert Definition Table And Agents (jonathanhurley)


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

Branch: refs/heads/branch-alerts-dev
Commit: 100fb9c0aa215cb8ac1a7a0f56599f79e269c032
Parents: 2ac6c72
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Fri Aug 22 15:11:20 2014 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Fri Aug 22 16:21:58 2014 -0400

----------------------------------------------------------------------
 .../server/api/services/AmbariMetaInfo.java     |  25 +++--
 .../AlertDefinitionResourceProvider.java        |  55 +---------
 .../server/orm/dao/AlertDefinitionDAO.java      |  17 +++-
 .../orm/entities/AlertDefinitionEntity.java     |  20 +++-
 .../server/orm/entities/ClusterEntity.java      |  75 ++++++++++----
 .../apache/ambari/server/state/ServiceImpl.java |  79 ++++++++++----
 .../server/state/alert/AlertDefinition.java     |  10 +-
 .../state/alert/AlertDefinitionFactory.java     |  10 +-
 .../server/state/alert/AlertDefinitionHash.java |  48 +++++++++
 .../server/state/cluster/ClusterImpl.java       | 102 ++++++++++++-------
 .../svccomphost/ServiceComponentHostImpl.java   |  94 ++++++++++++-----
 .../stacks/HDP/2.0.6/services/HBASE/alerts.json |  24 +++++
 .../server/orm/dao/AlertDefinitionDAOTest.java  |  24 +++++
 13 files changed, 413 insertions(+), 170 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
index 7645f73..fb9c376 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AmbariMetaInfo.java
@@ -1090,10 +1090,16 @@ public class AmbariMetaInfo {
   }
 
   /**
-   * @param stackName the stack name
-   * @param stackVersion the stack version
-   * @param serviceName the service name
-   * @return the alert definitions for a stack
+   * Gets the alert definitions for the specified stack and service.
+   *
+   * @param stackName
+   *          the stack name
+   * @param stackVersion
+   *          the stack version
+   * @param serviceName
+   *          the service name
+   * @return the alert definitions for a stack or an empty list if none (never
+   *         {@code null}).
    * @throws AmbariException
    */
   public Set<AlertDefinition> getAlertDefinitions(String stackName, String stackVersion,
@@ -1104,13 +1110,16 @@ public class AmbariMetaInfo {
   }
 
   /**
+   * Gets the alert definitions for the specified stack and service.
+   *
    * @param stackName
    *          the stack name
    * @param stackVersion
    *          the stack version
    * @param serviceName
    *          the service name
-   * @return the alert definitions for a stack
+   * @return the alert definitions for a stack or an empty list if none (never
+   *         {@code null}).
    * @throws AmbariException
    */
   public Set<AlertDefinition> getAlertDefinitions(ServiceInfo service)
@@ -1121,7 +1130,7 @@ public class AmbariMetaInfo {
       LOG.debug("Alerts file for {}/{} not found.", service.getSchemaVersion(),
           service.getName());
 
-      return null;
+      return Collections.emptySet();
     }
 
     return alertDefinitionFactory.getAlertDefinitions(alertsFile,
@@ -1175,9 +1184,7 @@ public class AmbariMetaInfo {
 
         // get all alerts defined on the stack for each cluster service
         Set<AlertDefinition> serviceDefinitions = getAlertDefinitions(stackService);
-        if (null != serviceDefinitions) {
-          stackDefinitions.addAll(serviceDefinitions);
-        }
+        stackDefinitions.addAll(serviceDefinitions);
       }
 
       // if there are no alert definitions defined for the cluster services

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
index ced50ec..c63f063 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
@@ -28,9 +28,6 @@ import java.util.Set;
 import java.util.UUID;
 
 import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.agent.ActionQueue;
-import org.apache.ambari.server.agent.AgentCommand.AgentCommandType;
-import org.apache.ambari.server.agent.AlertDefinitionCommand;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
 import org.apache.ambari.server.controller.spi.NoSuchResourceException;
@@ -46,7 +43,6 @@ import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
-import org.apache.ambari.server.state.alert.AlertDefinition;
 import org.apache.ambari.server.state.alert.AlertDefinitionHash;
 import org.apache.ambari.server.state.alert.Scope;
 import org.apache.ambari.server.state.alert.SourceType;
@@ -91,8 +87,6 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
 
   private static AlertDefinitionHash alertDefinitionHash;
 
-  private static ActionQueue actionQueue;
-
   /**
    * @param instance
    */
@@ -100,7 +94,6 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
   public static void init(Injector injector) {
     alertDefinitionDAO = injector.getInstance(AlertDefinitionDAO.class);
     alertDefinitionHash = injector.getInstance(AlertDefinitionHash.class);
-    actionQueue = injector.getInstance(ActionQueue.class);
   }
 
   AlertDefinitionResourceProvider(Set<String> propertyIds,
@@ -155,7 +148,7 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
     }
 
     // build alert definition commands for all agent hosts affected
-    enqueueAgentCommands(clusterName, invalidatedHosts);
+    alertDefinitionHash.enqueueAgentCommands(clusterName, invalidatedHosts);
   }
 
   @Override
@@ -242,7 +235,7 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
     }
 
     // build alert definition commands for all agent hosts affected
-    enqueueAgentCommands(clusterName, invalidatedHosts);
+    alertDefinitionHash.enqueueAgentCommands(clusterName, invalidatedHosts);
 
     notifyUpdate(Resource.Type.AlertDefinition, request, predicate);
 
@@ -286,7 +279,7 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
     }
 
     // build alert definition commands for all agent hosts affected
-    enqueueAgentCommands(clusterName, invalidatedHosts);
+    alertDefinitionHash.enqueueAgentCommands(clusterName, invalidatedHosts);
 
     notifyDelete(Resource.Type.AlertDefinition, predicate);
     return getRequestStatus(null);
@@ -504,46 +497,4 @@ public class AlertDefinitionResourceProvider extends AbstractControllerResourceP
 
     return resource;
   }
-
-  /**
-   * Enqueue {@link AlertDefinitionCommand}s for every host specified so that
-   * they will receive a payload of alert definitions that they should be
-   * running.
-   * <p/>
-   * This method is typically called after
-   * {@link AlertDefinitionHash#invalidateHosts(AlertDefinitionEntity)} has
-   * caused a cache invalidation of the alert definition hash.
-   *
-   * @param clusterName
-   *          the name of the cluster (not {@code null}).
-   * @param hosts
-   *          the hosts to push {@link AlertDefinitionCommand}s for.
-   */
-  private void enqueueAgentCommands(String clusterName, Set<String> hosts) {
-    if (null == clusterName) {
-      LOG.warn("Unable to create alert definition agent commands because of a null cluster name");
-      return;
-    }
-
-    if (null == hosts || hosts.size() == 0) {
-      return;
-    }
-
-    for (String hostName : hosts) {
-      List<AlertDefinition> definitions = alertDefinitionHash.getAlertDefinitions(
-          clusterName, hostName);
-
-      String hash = alertDefinitionHash.getHash(clusterName, hostName);
-
-      AlertDefinitionCommand command = new AlertDefinitionCommand(clusterName,
-          hostName, hash, definitions);
-
-      // unlike other commands, the alert definitions commands are really
-      // designed to be 1:1 per change; if multiple invalidations happened
-      // before the next heartbeat, there would be several commands that would
-      // force the agents to reschedule their alerts more than once
-      actionQueue.dequeue(hostName, AgentCommandType.ALERT_DEFINITION_COMMAND);
-      actionQueue.enqueue(hostName, command);
-    }
-  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
index 583f4bf..4a8fe12 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAO.java
@@ -268,7 +268,7 @@ public class AlertDefinitionDAO {
    * Creates or updates the specified entity. This method will check
    * {@link AlertDefinitionEntity#getDefinitionId()} in order to determine
    * whether the entity should be created or merged.
-   * 
+   *
    * @param alertDefinition
    *          the definition to create or update (not {@code null}).
    */
@@ -300,4 +300,19 @@ public class AlertDefinitionDAO {
       entityManager.remove(alertDefinition);
     }
   }
+
+  /**
+   * Removes all {@link AlertDefinitionEntity} that are associated with the
+   * specified cluster ID.
+   *
+   * @param clusterId
+   *          the cluster ID.
+   */
+  @Transactional
+  public void removeAll(long clusterId) {
+    List<AlertDefinitionEntity> definitions = findAll(clusterId);
+    for (AlertDefinitionEntity definition : definitions) {
+      remove(definition);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/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 c93702a..299467c 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
@@ -26,11 +26,14 @@ 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;
@@ -71,6 +74,10 @@ public class AlertDefinitionEntity {
   @Column(name = "cluster_id", nullable = false)
   private Long clusterId;
 
+  @ManyToOne(fetch = FetchType.LAZY)
+  @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", insertable = false, updatable = false)
+  private ClusterEntity clusterEntity;
+
   @Column(name = "component_name", length = 255)
   private String componentName;
 
@@ -177,6 +184,15 @@ public class AlertDefinitionEntity {
   }
 
   /**
+   * Gets the cluster that this alert definition is a member of.
+   *
+   * @return
+   */
+  public ClusterEntity getCluster() {
+    return clusterEntity;
+  }
+
+  /**
    * Gets 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.
    *
@@ -360,7 +376,7 @@ public class AlertDefinitionEntity {
 
   /**
    * Sets a human readable label for this alert definition.
-   * 
+   *
    * @param label
    *          the label or {@code null} if none.
    */
@@ -370,7 +386,7 @@ public class AlertDefinitionEntity {
 
   /**
    * Gets the label for this alert definition.
-   * 
+   *
    * @return the label or {@code null} if none.
    */
   public String getLabel() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
index 292a4d3..b0b3746 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java
@@ -18,13 +18,31 @@
 
 package org.apache.ambari.server.orm.entities;
 
-import javax.persistence.*;
-
-import org.apache.ambari.server.state.State;
+import static org.apache.commons.lang.StringUtils.defaultString;
 
 import java.util.Collection;
 
-import static org.apache.commons.lang.StringUtils.defaultString;
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+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.JoinColumns;
+import javax.persistence.ManyToMany;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import org.apache.ambari.server.state.State;
 
 @Table(name = "clusters")
 @NamedQueries({
@@ -58,8 +76,8 @@ public class ClusterEntity {
   @Basic
   @Enumerated(value = EnumType.STRING)
   @Column(name = "provisioning_state", insertable = true, updatable = true)
-  private State provisioningState = State.INIT;   
-  
+  private State provisioningState = State.INIT;
+
   @Basic
   @Column(name = "desired_cluster_state", insertable = true, updatable = true)
   private String desiredClusterState = "";
@@ -96,6 +114,9 @@ public class ClusterEntity {
   @OneToMany(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE)
   private Collection<ServiceConfigEntity> serviceConfigEntities;
 
+  @OneToMany(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY)
+  private Collection<AlertDefinitionEntity> alertDefinitionEntities;
+
   @OneToOne(cascade = CascadeType.ALL)
   @JoinColumns({
       @JoinColumn(name = "resource_id", referencedColumnName = "resource_id", nullable = false)
@@ -141,24 +162,24 @@ public class ClusterEntity {
   public void setDesiredStackVersion(String desiredStackVersion) {
     this.desiredStackVersion = desiredStackVersion;
   }
-  
+
   /**
-   * Gets whether the cluster is still initializing or has finished with its 
+   * Gets whether the cluster is still initializing or has finished with its
    * deployment requests.
-   * 
-   * @return either {@link State#INIT} or {@link State#INSTALLED}, 
+   *
+   * @return either {@link State#INIT} or {@link State#INSTALLED},
    * never {@code null}.
    */
   public State getProvisioningState(){
-    return this.provisioningState;
+    return provisioningState;
   }
-  
+
   /**
-   * Sets whether the cluster is still initializing or has finished with its 
+   * Sets whether the cluster is still initializing or has finished with its
    * deployment requests.
-   * 
-   * @param provisioningState either {@link State#INIT} or 
-   * {@link State#INSTALLED}, never {@code null}. 
+   *
+   * @param provisioningState either {@link State#INIT} or
+   * {@link State#INSTALLED}, never {@code null}.
    */
   public void setProvisioningState(State provisioningState){
     this.provisioningState = provisioningState;
@@ -166,13 +187,21 @@ public class ClusterEntity {
 
   @Override
   public boolean equals(Object o) {
-    if (this == o) return true;
-    if (o == null || getClass() != o.getClass()) return false;
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
 
     ClusterEntity that = (ClusterEntity) o;
 
-    if (!clusterId.equals(that.clusterId)) return false;
-    if (!clusterName.equals(that.clusterName)) return false;
+    if (!clusterId.equals(that.clusterId)) {
+      return false;
+    }
+    if (!clusterName.equals(that.clusterName)) {
+      return false;
+    }
 
     return true;
   }
@@ -219,7 +248,7 @@ public class ClusterEntity {
   public Collection<ClusterConfigMappingEntity> getConfigMappingEntities() {
     return configMappingEntities;
   }
-  
+
   public void setConfigMappingEntities(Collection<ClusterConfigMappingEntity> entities) {
     configMappingEntities = entities;
   }
@@ -248,6 +277,10 @@ public class ClusterEntity {
     this.serviceConfigEntities = serviceConfigEntities;
   }
 
+  public Collection<AlertDefinitionEntity> getAlertDefinitionEntities() {
+    return alertDefinitionEntities;
+  }
+
   /**
    * Get the admin resource entity.
    *

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
index 36aa65f..b2b84fc 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
@@ -18,9 +18,9 @@
 
 package org.apache.ambari.server.state;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -28,14 +28,18 @@ import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ServiceComponentNotFoundException;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.ServiceResponse;
+import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ClusterServiceDAO;
 import org.apache.ambari.server.orm.dao.ServiceDesiredStateDAO;
+import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.orm.entities.ClusterEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
 import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
 import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
 import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity;
+import org.apache.ambari.server.state.alert.AlertDefinition;
+import org.apache.ambari.server.state.alert.AlertDefinitionFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -75,6 +79,20 @@ public class ServiceImpl implements Service {
   @Inject
   private AmbariMetaInfo ambariMetaInfo;
 
+  /**
+   * Used when a service is installed to insert {@link AlertDefinitionEntity}
+   * into the database.
+   */
+  @Inject
+  private AlertDefinitionDAO alertDefinitionDAO;
+
+  /**
+   * Used when a service is installed to read alert definitions from the stack
+   * and coerce them into {@link AlertDefinitionEntity}.
+   */
+  @Inject
+  private AlertDefinitionFactory alertDefinitionFactory;
+
   private void init() {
     // TODO load from DB during restart?
   }
@@ -93,14 +111,14 @@ public class ServiceImpl implements Service {
 
     this.cluster = cluster;
 
-    this.components = new HashMap<String, ServiceComponent>();
+    components = new HashMap<String, ServiceComponent>();
 
     StackId stackId = cluster.getDesiredStackVersion();
     setDesiredStackVersion(stackId);
 
     ServiceInfo sInfo = ambariMetaInfo.getServiceInfo(stackId.getStackName(),
         stackId.getStackVersion(), serviceName);
-    this.isClientOnlyService = sInfo.isClientOnlyService();
+    isClientOnlyService = sInfo.isClientOnlyService();
 
     init();
   }
@@ -114,9 +132,9 @@ public class ServiceImpl implements Service {
     this.cluster = cluster;
 
     //TODO check for null states?
-    this.serviceDesiredStateEntity = serviceEntity.getServiceDesiredStateEntity();
+    serviceDesiredStateEntity = serviceEntity.getServiceDesiredStateEntity();
 
-    this.components = new HashMap<String, ServiceComponent>();
+    components = new HashMap<String, ServiceComponent>();
 
     if (!serviceEntity.getServiceComponentDesiredStateEntities().isEmpty()) {
       for (ServiceComponentDesiredStateEntity serviceComponentDesiredStateEntity
@@ -130,7 +148,7 @@ public class ServiceImpl implements Service {
     StackId stackId = getDesiredStackVersion();
     ServiceInfo sInfo = ambariMetaInfo.getServiceInfo(stackId.getStackName(),
         stackId.getStackVersion(), getName());
-    this.isClientOnlyService = sInfo.isClientOnlyService();
+    isClientOnlyService = sInfo.isClientOnlyService();
 
     persisted = true;
   }
@@ -225,7 +243,7 @@ public class ServiceImpl implements Service {
               + ", serviceName=" + getName()
               + ", serviceComponentName=" + component.getName());
         }
-        this.components.put(component.getName(), component);
+        components.put(component.getName(), component);
       } finally {
         readWriteLock.writeLock().unlock();
       }
@@ -256,7 +274,7 @@ public class ServiceImpl implements Service {
               + ", serviceComponentName=" + serviceComponentName);
         }
         ServiceComponent component = serviceComponentFactory.createNew(this, serviceComponentName);
-        this.components.put(component.getName(), component);
+        components.put(component.getName(), component);
         return component;
       } finally {
         readWriteLock.writeLock().unlock();
@@ -280,7 +298,7 @@ public class ServiceImpl implements Service {
               getName(),
               componentName);
         }
-        return this.components.get(componentName);
+        return components.get(componentName);
       } finally {
         readWriteLock.readLock().unlock();
       }
@@ -297,7 +315,7 @@ public class ServiceImpl implements Service {
     try {
       readWriteLock.readLock().lock();
       try {
-        return this.serviceDesiredStateEntity.getDesiredState();
+        return serviceDesiredStateEntity.getDesiredState();
       } finally {
         readWriteLock.readLock().unlock();
       }
@@ -319,10 +337,10 @@ public class ServiceImpl implements Service {
               + ", clusterName=" + cluster.getClusterName()
               + ", clusterId=" + cluster.getClusterId()
               + ", serviceName=" + getName()
-              + ", oldDesiredState=" + this.getDesiredState()
+              + ", oldDesiredState=" + getDesiredState()
               + ", newDesiredState=" + state);
         }
-        this.serviceDesiredStateEntity.setDesiredState(state);
+        serviceDesiredStateEntity.setDesiredState(state);
         saveIfPersisted();
       } finally {
         readWriteLock.writeLock().unlock();
@@ -384,7 +402,7 @@ public class ServiceImpl implements Service {
             getName(),
             getDesiredStackVersion().getStackId(),
             getDesiredState().toString());
-        
+
         r.setMaintenanceState(getMaintenanceState().name());
         return r;
       } finally {
@@ -472,16 +490,37 @@ public class ServiceImpl implements Service {
 
   @Transactional
   protected void persistEntities() {
-    ClusterEntity clusterEntity = clusterDAO.findById(cluster.getClusterId());
+    long clusterId = cluster.getClusterId();
+    StackId stackId = cluster.getDesiredStackVersion();
+
+    ClusterEntity clusterEntity = clusterDAO.findById(clusterId);
     serviceEntity.setClusterEntity(clusterEntity);
     clusterServiceDAO.create(serviceEntity);
     serviceDesiredStateDAO.create(serviceDesiredStateEntity);
     clusterEntity.getClusterServiceEntities().add(serviceEntity);
     clusterDAO.merge(clusterEntity);
-//    serviceEntity =
-        clusterServiceDAO.merge(serviceEntity);
-//    serviceDesiredStateEntity =
-        serviceDesiredStateDAO.merge(serviceDesiredStateEntity);
+    clusterServiceDAO.merge(serviceEntity);
+    serviceDesiredStateDAO.merge(serviceDesiredStateEntity);
+
+    // populate alert definitions for the new service from the database, but
+    // don't worry about sending down commands to the agents; the host
+    // components are not yet bound to the hosts so we'd have no way of knowing
+    // which hosts are invalidated; do that in another impl
+    try{
+      Set<AlertDefinition> alertDefinitions = ambariMetaInfo.getAlertDefinitions(
+          stackId.getStackName(), stackId.getStackVersion(), getName());
+
+      for (AlertDefinition definition : alertDefinitions) {
+        AlertDefinitionEntity entity = alertDefinitionFactory.coerce(clusterId,
+            definition);
+
+        alertDefinitionDAO.create(entity);
+      }
+    } catch( AmbariException ae ){
+      LOG.error(
+          "Unable to populate alert definitions from the database during installation of {}",
+          getName(), ae);
+    }
   }
 
   @Transactional
@@ -650,7 +689,7 @@ public class ServiceImpl implements Service {
 
     clusterServiceDAO.removeByPK(pk);
   }
-  
+
   @Override
   public void setMaintenanceState(MaintenanceState state) {
     clusterGlobalLock.readLock().lock();
@@ -666,7 +705,7 @@ public class ServiceImpl implements Service {
       clusterGlobalLock.readLock().unlock();
     }
   }
-  
+
   @Override
   public MaintenanceState getMaintenanceState() {
     return serviceDesiredStateEntity.getMaintenanceState();

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinition.java
index 97d1f54..f227c0a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinition.java
@@ -38,7 +38,7 @@ public class AlertDefinition {
   private String componentName = null;
 
   private String name = null;
-  private Scope scope = null;
+  private Scope scope = Scope.ANY;
   private int interval = 1;
   private boolean enabled = true;
   private Source source = null;
@@ -96,6 +96,10 @@ public class AlertDefinition {
   }
 
   public void setScope(Scope definitionScope) {
+    if (null == definitionScope) {
+      definitionScope = Scope.ANY;
+    }
+
     scope = definitionScope;
   }
 
@@ -198,6 +202,10 @@ public class AlertDefinition {
       return false;
     }
 
+    if (null == scope) {
+      scope = Scope.ANY;
+    }
+
     if (scope != other.scope) {
       return false;
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionFactory.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionFactory.java
index 5aa59da..f16f4a6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionFactory.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionFactory.java
@@ -153,7 +153,7 @@ public class AlertDefinitionFactory {
    * {@link AlertDefinition}.
    * <p/>
    * The new entity will have a UUID already set.
-   * 
+   *
    * @param clusterId
    *          the ID of the cluster.
    * @param definition
@@ -193,9 +193,15 @@ public class AlertDefinitionFactory {
     entity.setHash(UUID.randomUUID().toString());
     entity.setLabel(definition.getLabel());
     entity.setScheduleInterval(definition.getInterval());
-    entity.setScope(definition.getScope());
     entity.setServiceName(definition.getServiceName());
 
+    Scope scope = definition.getScope();
+    if (null == scope) {
+      scope = Scope.ANY;
+    }
+
+    entity.setScope(scope);
+
     Source source = definition.getSource();
     entity.setSourceType(source.getType().name());
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
index 3a89dd9..0a1c73a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinitionHash.java
@@ -33,6 +33,9 @@ import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.ActionQueue;
+import org.apache.ambari.server.agent.AgentCommand.AgentCommandType;
+import org.apache.ambari.server.agent.AlertDefinitionCommand;
 import org.apache.ambari.server.controller.RootServiceResponseFactory.Components;
 import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
 import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
@@ -84,6 +87,9 @@ public class AlertDefinitionHash {
   @Inject
   private Clusters m_clusters;
 
+  @Inject
+  private ActionQueue m_actionQueue;
+
   /**
    * !!! TODO: this class needs some thoughts on locking
    */
@@ -474,4 +480,46 @@ public class AlertDefinitionHash {
       return NULL_MD5_HASH;
     }
   }
+
+  /**
+   * Enqueue {@link AlertDefinitionCommand}s for every host specified so that
+   * they will receive a payload of alert definitions that they should be
+   * running.
+   * <p/>
+   * This method is typically called after
+   * {@link #invalidateHosts(AlertDefinitionEntity)} has caused a cache
+   * invalidation of the alert definition hash.
+   * 
+   * @param clusterName
+   *          the name of the cluster (not {@code null}).
+   * @param hosts
+   *          the hosts to push {@link AlertDefinitionCommand}s for.
+   */
+  public void enqueueAgentCommands(String clusterName, Set<String> hosts) {
+    if (null == clusterName) {
+      LOG.warn("Unable to create alert definition agent commands because of a null cluster name");
+      return;
+    }
+
+    if (null == hosts || hosts.size() == 0) {
+      return;
+    }
+
+    for (String hostName : hosts) {
+      List<AlertDefinition> definitions = getAlertDefinitions(clusterName,
+          hostName);
+
+      String hash = getHash(clusterName, hostName);
+
+      AlertDefinitionCommand command = new AlertDefinitionCommand(clusterName,
+          hostName, hash, definitions);
+
+      // unlike other commands, the alert definitions commands are really
+      // designed to be 1:1 per change; if multiple invalidations happened
+      // before the next heartbeat, there would be several commands that would
+      // force the agents to reschedule their alerts more than once
+      m_actionQueue.dequeue(hostName, AgentCommandType.ALERT_DEFINITION_COMMAND);
+      m_actionQueue.enqueue(hostName, command);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
index baf58e7..1a497bf 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java
@@ -36,8 +36,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.persistence.RollbackException;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.ObjectNotFoundException;
 import org.apache.ambari.server.ParentObjectNotFoundException;
@@ -47,9 +45,11 @@ import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.ClusterResponse;
 import org.apache.ambari.server.controller.ConfigurationResponse;
 import org.apache.ambari.server.controller.MaintenanceStateHelper;
+import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
 import org.apache.ambari.server.orm.RequiresSession;
 import org.apache.ambari.server.orm.cache.ConfigGroupHostMapping;
 import org.apache.ambari.server.orm.cache.HostConfigMapping;
+import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ClusterStateDAO;
 import org.apache.ambari.server.orm.dao.ConfigGroupHostMappingDAO;
@@ -66,20 +66,41 @@ import org.apache.ambari.server.orm.entities.PrivilegeEntity;
 import org.apache.ambari.server.orm.entities.RequestScheduleEntity;
 import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
-import org.apache.ambari.server.state.*;
+import org.apache.ambari.server.state.Alert;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.ClusterHealthReport;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Config;
+import org.apache.ambari.server.state.ConfigFactory;
+import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.ConfigVersionHelper;
+import org.apache.ambari.server.state.DesiredConfig;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.state.HostHealthStatus;
+import org.apache.ambari.server.state.MaintenanceState;
+import org.apache.ambari.server.state.PropertyInfo;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
+import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.ServiceComponentHostEvent;
+import org.apache.ambari.server.state.ServiceFactory;
+import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.configgroup.ConfigGroup;
 import org.apache.ambari.server.state.configgroup.ConfigGroupFactory;
 import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
 import org.apache.ambari.server.state.scheduler.RequestExecution;
 import org.apache.ambari.server.state.scheduler.RequestExecutionFactory;
-import org.apache.ambari.server.controller.ServiceConfigVersionResponse;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.Predicate;
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Multimap;
 import com.google.gson.Gson;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -132,7 +153,7 @@ public class ClusterImpl implements Cluster {
   private final ReadWriteLock clusterGlobalLock = new ReentrantReadWriteLock();
 
   private ClusterEntity clusterEntity;
-  
+
   private Set<Alert> clusterAlerts = new HashSet<Alert>();
 
   private final ConfigVersionHelper configVersionHelper;
@@ -164,6 +185,9 @@ public class ClusterImpl implements Cluster {
   @Inject
   private ServiceConfigDAO serviceConfigDAO;
 
+  @Inject
+  private AlertDefinitionDAO alertDefinitionDAO;
+
   private volatile boolean svcHostsLoaded = false;
 
   private volatile Multimap<String, String> serviceConfigTypes;
@@ -174,11 +198,11 @@ public class ClusterImpl implements Cluster {
     injector.injectMembers(this);
     this.clusterEntity = clusterEntity;
 
-    this.serviceComponentHosts = new HashMap<String,
+    serviceComponentHosts = new HashMap<String,
       Map<String, Map<String, ServiceComponentHost>>>();
-    this.serviceComponentHostsByHost = new HashMap<String,
+    serviceComponentHostsByHost = new HashMap<String,
       List<ServiceComponentHost>>();
-    this.desiredStackVersion = gson.fromJson(
+    desiredStackVersion = gson.fromJson(
       clusterEntity.getDesiredStackVersion(), StackId.class);
     allConfigs = new HashMap<String, Map<String, Config>>();
     if (!clusterEntity.getClusterConfigEntities().isEmpty()) {
@@ -257,13 +281,17 @@ public class ClusterImpl implements Cluster {
    */
   public void loadServiceHostComponents() {
     loadServices();
-    if (svcHostsLoaded) return;
+    if (svcHostsLoaded) {
+      return;
+    }
     clusterGlobalLock.writeLock().lock();
     try {
       writeLock.lock();
       try {
         LOG.info("Loading Service Host Components");
-        if (svcHostsLoaded) return;
+        if (svcHostsLoaded) {
+          return;
+        }
         if (services != null) {
           for (Entry<String, Service> serviceKV : services.entrySet()) {
           /* get all the service component hosts **/
@@ -647,7 +675,7 @@ public class ClusterImpl implements Cluster {
         Iterator<Cluster> iter = cs.iterator();
         while (iter.hasNext()) {
           Cluster c = iter.next();
-          if (c.getClusterId() == this.getClusterId()) {
+          if (c.getClusterId() == getClusterId()) {
             clusterFound = true;
             break;
           }
@@ -725,7 +753,7 @@ public class ClusterImpl implements Cluster {
         Iterator<Cluster> iter = cs.iterator();
         while (iter.hasNext()) {
           Cluster c = iter.next();
-          if (c.getClusterId() == this.getClusterId()) {
+          if (c.getClusterId() == getClusterId()) {
             clusterFound = true;
             break;
           }
@@ -849,7 +877,7 @@ public class ClusterImpl implements Cluster {
             + ", clusterId=" + getClusterId()
             + ", serviceName=" + service.getName());
         }
-        this.services.put(service.getName(), service);
+        services.put(service.getName(), service);
       } finally {
         writeLock.unlock();
       }
@@ -879,7 +907,7 @@ public class ClusterImpl implements Cluster {
             + ", serviceName=" + serviceName);
         }
         Service s = serviceFactory.createNew(this, serviceName);
-        this.services.put(s.getName(), s);
+        services.put(s.getName(), s);
         return s;
       } finally {
         writeLock.unlock();
@@ -954,10 +982,10 @@ public class ClusterImpl implements Cluster {
           LOG.debug("Changing DesiredStackVersion of Cluster"
             + ", clusterName=" + getClusterName()
             + ", clusterId=" + getClusterId()
-            + ", currentDesiredStackVersion=" + this.desiredStackVersion
+            + ", currentDesiredStackVersion=" + desiredStackVersion
             + ", newDesiredStackVersion=" + stackVersion);
         }
-        this.desiredStackVersion = stackVersion;
+        desiredStackVersion = stackVersion;
         clusterEntity.setDesiredStackVersion(gson.toJson(stackVersion));
         clusterDAO.merge(clusterEntity);
         loadServiceConfigTypes();
@@ -991,19 +1019,20 @@ public class ClusterImpl implements Cluster {
       clusterGlobalLock.readLock().unlock();
     }
   }
-  
+
   @Override
-  public State getProvisioningState() {    
+  public State getProvisioningState() {
     clusterGlobalLock.readLock().lock();
     try {
       readLock.lock();
       State provisioningState = null;
       try {
         provisioningState = clusterEntity.getProvisioningState();
-        
-        if( null == provisioningState )
+
+        if( null == provisioningState ) {
           provisioningState = State.INIT;
-        
+        }
+
         return provisioningState;
       } finally {
         readLock.unlock();
@@ -1011,7 +1040,7 @@ public class ClusterImpl implements Cluster {
     } finally {
       clusterGlobalLock.readLock().unlock();
     }
-  }  
+  }
 
   @Override
   public void setProvisioningState(State provisioningState) {
@@ -1020,7 +1049,7 @@ public class ClusterImpl implements Cluster {
       writeLock.lock();
       try {
         clusterEntity.setProvisioningState(provisioningState);
-        clusterDAO.merge(clusterEntity);        
+        clusterDAO.merge(clusterEntity);
       } finally {
         writeLock.unlock();
       }
@@ -1071,8 +1100,9 @@ public class ClusterImpl implements Cluster {
     try {
       readWriteLock.writeLock().lock();
       try {
-        if (!allConfigs.containsKey(configType))
+        if (!allConfigs.containsKey(configType)) {
           return null;
+        }
 
         return Collections.unmodifiableMap(allConfigs.get(configType));
       } finally {
@@ -1329,7 +1359,9 @@ public class ClusterImpl implements Cluster {
 
   @Transactional
   protected void removeEntities() throws AmbariException {
-    clusterDAO.removeByPK(getClusterId());
+    long clusterId = getClusterId();
+    alertDefinitionDAO.removeAll(clusterId);
+    clusterDAO.removeByPK(clusterId);
   }
 
   @Override
@@ -1339,8 +1371,9 @@ public class ClusterImpl implements Cluster {
 
   @Override
   public ServiceConfigVersionResponse addDesiredConfig(String user, Config config, String serviceConfigVersionNote) {
-    if (null == user)
+    if (null == user) {
       throw new NullPointerException("User must be specified.");
+    }
 
     clusterGlobalLock.readLock().lock();
     try {
@@ -1489,8 +1522,9 @@ public class ClusterImpl implements Cluster {
 
   @Override
   public boolean setServiceConfigVersion(String serviceName, Long version, String user, String note) throws AmbariException {
-    if (null == user)
+    if (null == user) {
       throw new NullPointerException("User must be specified.");
+    }
 
     clusterGlobalLock.writeLock().lock();
     try {
@@ -1606,7 +1640,7 @@ public class ClusterImpl implements Cluster {
     serviceConfigVersionResponse.setClusterName(getClusterName());
     serviceConfigVersionResponse.setServiceName(serviceConfigEntity.getServiceName());
     serviceConfigVersionResponse.setVersion(serviceConfigEntity.getVersion());
-    serviceConfigVersionResponse.setCreateTime(serviceConfigEntity.getCreateTimestamp());    
+    serviceConfigVersionResponse.setCreateTime(serviceConfigEntity.getCreateTimestamp());
     serviceConfigVersionResponse.setUserName(serviceConfigEntity.getUser());
     serviceConfigVersionResponse.setNote(serviceConfigEntity.getNote());
     return serviceConfigVersionResponse;
@@ -1958,12 +1992,12 @@ public class ClusterImpl implements Cluster {
 
     return chr;
   }
-  
+
   @Override
   public void addAlerts(Collection<Alert> alerts) {
     try {
       writeLock.lock();
-      
+
       for (final Alert alert : alerts) {
         if (clusterAlerts.size() > 0) {
           CollectionUtils.filter(clusterAlerts, new Predicate() {
@@ -1974,7 +2008,7 @@ public class ClusterImpl implements Cluster {
             }
           });
         }
-        
+
         if (LOG.isDebugEnabled()) {
           LOG.debug("Adding alert for name={} service={}, on host={}",
               alert.getName(), alert.getService(), alert.getHost());
@@ -1987,12 +2021,12 @@ public class ClusterImpl implements Cluster {
       writeLock.unlock();
     }
   }
-  
+
   @Override
   public Collection<Alert> getAlerts() {
     try {
       readLock.lock();
-      
+
       return Collections.unmodifiableSet(clusterAlerts);
     } finally {
       readLock.unlock();

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
index ade5792..cc5bb5b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/svccomphost/ServiceComponentHostImpl.java
@@ -29,6 +29,7 @@ import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.agent.AlertDefinitionCommand;
 import org.apache.ambari.server.controller.ServiceComponentHostResponse;
 import org.apache.ambari.server.orm.dao.HostComponentDesiredStateDAO;
 import org.apache.ambari.server.orm.dao.HostComponentStateDAO;
@@ -55,6 +56,7 @@ import org.apache.ambari.server.state.ServiceComponentHostEvent;
 import org.apache.ambari.server.state.ServiceComponentHostEventType;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
+import org.apache.ambari.server.state.alert.AlertDefinitionHash;
 import org.apache.ambari.server.state.configgroup.ConfigGroup;
 import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
 import org.apache.ambari.server.state.fsm.SingleArcTransition;
@@ -101,6 +103,13 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
   @Inject
   ConfigHelper helper;
 
+  /**
+   * Used for creating commands to send to the agents when alert definitions are
+   * added as the result of a service install.
+   */
+  @Inject
+  private AlertDefinitionHash alertDefinitionHash;
+
   private HostComponentStateEntity stateEntity;
   private HostComponentDesiredStateEntity desiredStateEntity;
 
@@ -127,16 +136,21 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
          State.INSTALLING,
          ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL,
          new ServiceComponentHostOpStartedTransition())
+
      .addTransition(State.INSTALLING,
          State.INSTALLED,
          ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED,
          new ServiceComponentHostOpCompletedTransition())
-         
+
+  .addTransition(State.INSTALLING, State.INSTALLED,
+      ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED,
+      new AlertDefinitionCommandTransition())
+
      .addTransition(State.INSTALLED,
          State.INSTALLED,
          ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED,
          new ServiceComponentHostOpCompletedTransition())
-         
+
      .addTransition(State.INSTALLING,
          State.INSTALLING,
          ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS,
@@ -202,7 +216,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
          State.STARTING,
          ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS,
          new ServiceComponentHostOpInProgressTransition())
-         
+
      .addTransition(State.STARTING,
          State.STARTING,
          ServiceComponentHostEventType.HOST_SVCCOMP_START,
@@ -211,7 +225,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
          State.STARTED,
          ServiceComponentHostEventType.HOST_SVCCOMP_STARTED,
          new ServiceComponentHostOpCompletedTransition())
-         
+
      .addTransition(State.STARTING,
          State.INSTALLED,
          ServiceComponentHostEventType.HOST_SVCCOMP_OP_FAILED,
@@ -383,7 +397,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
          State.INSTALLING,
          ServiceComponentHostEventType.HOST_SVCCOMP_INSTALL,
          new ServiceComponentHostOpStartedTransition())
-     
+
      .addTransition(State.INSTALLING,
          State.INSTALLING,
          ServiceComponentHostEventType.HOST_SVCCOMP_OP_IN_PROGRESS,
@@ -516,10 +530,34 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
         ServiceComponentHostEvent event) {
       // TODO Audit logs
       impl.updateLastOpInfo(event.getType(), event.getOpTimestamp());
+
     }
 
   }
 
+  /**
+   * The {@link AlertDefinitionCommandTransition} is used to capture the
+   * transition from {@link State#INSTALLING} to {@link State#INSTALLED} so that
+   * the host affected will have new {@link AlertDefinitionCommand}s pushed to
+   * it.
+   */
+  static class AlertDefinitionCommandTransition implements
+      SingleArcTransition<ServiceComponentHostImpl, ServiceComponentHostEvent> {
+
+    @Override
+    public void transition(ServiceComponentHostImpl impl,
+        ServiceComponentHostEvent event) {
+      if (event.getType() != ServiceComponentHostEventType.HOST_SVCCOMP_OP_SUCCEEDED) {
+        return;
+      }
+
+      String hostName = impl.getHostName();
+      impl.alertDefinitionHash.invalidate(impl.getClusterName(), hostName);
+      impl.alertDefinitionHash.enqueueAgentCommands(impl.getClusterName(),
+          Collections.singleton(hostName));
+    }
+  }
+
   static class ServiceComponentHostOpStartedTransition
     implements SingleArcTransition<ServiceComponentHostImpl,
         ServiceComponentHostEvent> {
@@ -615,13 +653,13 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
     injector.injectMembers(this);
 
     if (serviceComponent.isClientComponent()) {
-      this.stateMachine = clientStateMachineFactory.make(this);
+      stateMachine = clientStateMachineFactory.make(this);
     } else {
-      this.stateMachine = daemonStateMachineFactory.make(this);
+      stateMachine = daemonStateMachineFactory.make(this);
     }
 
     this.serviceComponent = serviceComponent;
-    this.clusterGlobalLock = serviceComponent.getClusterGlobalLock();
+    clusterGlobalLock = serviceComponent.getClusterGlobalLock();
 
     stateEntity = new HostComponentStateEntity();
     stateEntity.setClusterId(serviceComponent.getClusterId());
@@ -646,14 +684,14 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
     }
 
     try {
-      this.host = clusters.getHost(hostName);
+      host = clusters.getHost(hostName);
     } catch (AmbariException e) {
       //TODO exception?
       LOG.error("Host '{}' was not found" + hostName);
       throw new RuntimeException(e);
     }
 
-    this.resetLastOpInfo();
+    resetLastOpInfo();
   }
 
   @AssistedInject
@@ -663,21 +701,21 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
                                   Injector injector) {
     injector.injectMembers(this);
     this.serviceComponent = serviceComponent;
-    this.clusterGlobalLock = serviceComponent.getClusterGlobalLock();
+    clusterGlobalLock = serviceComponent.getClusterGlobalLock();
 
     this.desiredStateEntity = desiredStateEntity;
     this.stateEntity = stateEntity;
 
     //TODO implement State Machine init as now type choosing is hardcoded in above code
     if (serviceComponent.isClientComponent()) {
-      this.stateMachine = clientStateMachineFactory.make(this);
+      stateMachine = clientStateMachineFactory.make(this);
     } else {
-      this.stateMachine = daemonStateMachineFactory.make(this);
+      stateMachine = daemonStateMachineFactory.make(this);
     }
-    this.stateMachine.setCurrentState(stateEntity.getCurrentState());
+    stateMachine.setCurrentState(stateEntity.getCurrentState());
 
     try {
-      this.host = clusters.getHost(stateEntity.getHostName());
+      host = clusters.getHost(stateEntity.getHostName());
     } catch (AmbariException e) {
       //TODO exception? impossible due to database restrictions
       LOG.error("Host '{}' was not found " + stateEntity.getHostName());
@@ -743,8 +781,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
         } catch (InvalidStateTransitionException e) {
           LOG.debug("Can't handle ServiceComponentHostEvent event at"
               + " current state"
-              + ", serviceComponentName=" + this.getServiceComponentName()
-              + ", hostName=" + this.getHostName()
+              + ", serviceComponentName=" + getServiceComponentName()
+              + ", hostName=" + getHostName()
               + ", currentState=" + oldState
               + ", eventType=" + event.getType()
               + ", event=" + event);
@@ -760,8 +798,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
     if (!oldState.equals(getState())) {
       if (LOG.isDebugEnabled()) {
         LOG.debug("ServiceComponentHost transitioned to a new state"
-            + ", serviceComponentName=" + this.getServiceComponentName()
-            + ", hostName=" + this.getHostName()
+            + ", serviceComponentName=" + getServiceComponentName()
+            + ", hostName=" + getHostName()
             + ", oldState=" + oldState
             + ", currentState=" + getState()
             + ", eventType=" + event.getType().name()
@@ -1269,7 +1307,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
           removeEntities();
           persisted = false;
         }
-        clusters.getCluster(this.getClusterName()).removeServiceComponentHost(this);
+        clusters.getCluster(getClusterName()).removeServiceComponentHost(this);
       } catch (AmbariException ex) {
         if (LOG.isDebugEnabled()) {
           LOG.error(ex.getMessage());
@@ -1301,7 +1339,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
 
     hostComponentDesiredStateDAO.removeByPK(desiredPK);
   }
-  
+
   @Override
   public void updateActualConfigs(Map<String, Map<String, String>> configTags) {
     Map<Long, ConfigGroup> configGroupMap;
@@ -1349,9 +1387,9 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
       clusterGlobalLock.readLock().unlock();
     }
   }
-  
-  
-  
+
+
+
   @Override
   public Map<String, HostConfig> getActualConfigs() {
     clusterGlobalLock.readLock().lock();
@@ -1382,7 +1420,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
       clusterGlobalLock.readLock().unlock();
     }
   }
-  
+
   @Override
   public void setMaintenanceState(MaintenanceState state) {
     clusterGlobalLock.readLock().lock();
@@ -1413,7 +1451,7 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
       clusterGlobalLock.readLock().unlock();
     }
   }
-  
+
   @Override
   public void setProcesses(List<Map<String, String>> procs) {
     clusterGlobalLock.readLock().lock();
@@ -1428,8 +1466,8 @@ public class ServiceComponentHostImpl implements ServiceComponentHost {
       clusterGlobalLock.readLock().unlock();
     }
   }
-  
-  @Override  
+
+  @Override
   public List<Map<String, String>> getProcesses() {
     clusterGlobalLock.readLock().lock();
     try {

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HBASE/alerts.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HBASE/alerts.json b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HBASE/alerts.json
new file mode 100644
index 0000000..3958106
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HBASE/alerts.json
@@ -0,0 +1,24 @@
+{
+  "service": [],
+  "HBASE_MASTER": [
+    {
+      "name": "hbase_master_process",
+      "label": "HBase Master Process",
+      "interval": 1,
+      "scope": "any",
+      "source": {
+        "type": "PORT",
+        "uri": "{{hbase-site/hbase.master.port}}",
+        "default_port": 60000,
+        "reporting": {
+          "ok": {
+            "text": "TCP OK - {0:.4f} response on port {1}"
+          },
+          "critical": {
+            "text": "Connection failed: {0} on host {1}:{2}"
+          }
+        }        
+      }
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/100fb9c0/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
index d621a9b..a7ef513 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDefinitionDAOTest.java
@@ -37,7 +37,10 @@ import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.orm.entities.AlertGroupEntity;
 import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
 import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
+import org.apache.ambari.server.orm.entities.ClusterEntity;
 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.NotificationState;
 import org.apache.ambari.server.state.alert.Scope;
@@ -319,4 +322,25 @@ public class AlertDefinitionDAOTest {
     assertNotNull(group.getAlertDefinitions());
     assertEquals(0, group.getAlertDefinitions().size());
   }
+
+  /**
+   * @throws Exception
+   */
+  @Test
+  public void testCascadeDeleteForCluster() throws Exception {
+    AlertDefinitionEntity definition = helper.createAlertDefinition(clusterId);
+    definition = dao.findById(definition.getDefinitionId());
+    dao.refresh(definition);
+
+    ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
+    ClusterEntity clusterEntity = clusterDAO.findById(clusterId);
+    clusterDAO.refresh(clusterEntity);
+
+    Clusters clusters = injector.getInstance(Clusters.class);
+    Cluster cluster = clusters.getClusterById(clusterId);
+    cluster.delete();
+
+    assertNull(clusterDAO.findById(clusterId));
+    assertNull(dao.findById(definition.getDefinitionId()));
+  }
 }