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/11/28 14:08:18 UTC

[2/2] ambari git commit: AMBARI-8460 - Alerts: AlertDefinition and AlertGroup Automatic Creation On Startup (jonathanhurley)

AMBARI-8460 - Alerts: AlertDefinition and AlertGroup Automatic Creation On Startup (jonathanhurley)


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

Branch: refs/heads/trunk
Commit: 9159421b39c4ef677a0bdc9445afe2ca2bd545ee
Parents: 378cf13
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Wed Nov 26 15:32:04 2014 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Fri Nov 28 08:04:39 2014 -0500

----------------------------------------------------------------------
 .../ambari/server/events/AmbariEvent.java       |   5 +
 .../ambari/server/events/HostAddedEvent.java    |  51 ++++
 .../server/events/HostRegisteredEvent.java      |  44 +++
 .../ambari/server/events/HostRemovedEvent.java  |   2 +-
 .../alerts/AlertHashInvalidationListener.java   |   3 +-
 .../listeners/alerts/AlertHostListener.java     | 119 +++++++-
 .../alerts/AlertServiceStateListener.java       |  12 +-
 .../server/orm/dao/AlertDefinitionDAO.java      |  31 ++-
 .../ambari/server/orm/dao/AlertDispatchDAO.java |  77 +++++-
 .../apache/ambari/server/orm/dao/AlertsDAO.java |   3 +-
 .../server/orm/dao/ClusterServiceDAO.java       |  21 +-
 .../dao/ServiceComponentDesiredStateDAO.java    |  21 +-
 .../orm/entities/AlertDefinitionEntity.java     |  18 ++
 .../server/orm/entities/AlertGroupEntity.java   |  17 +-
 .../server/orm/entities/AlertHistoryEntity.java |  17 ++
 .../server/orm/entities/AlertTargetEntity.java  |  13 +
 .../server/state/alert/AlertDefinitionHash.java |  66 +++--
 .../server/state/cluster/ClustersImpl.java      |  15 +-
 .../apache/ambari/server/orm/OrmTestHelper.java | 146 +++++++++-
 .../server/orm/dao/AlertDispatchDAOTest.java    | 276 ++++++++++++-------
 .../ambari/server/orm/dao/AlertsDAOTest.java    | 259 +++++++----------
 .../state/alerts/AlertReceivedListenerTest.java | 194 ++++++-------
 .../state/cluster/AlertDataManagerTest.java     | 185 ++++++++-----
 23 files changed, 1043 insertions(+), 552 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
index de9b6dc..e708473 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java
@@ -68,6 +68,11 @@ public abstract class AmbariEvent {
     ALERT_DEFINITION_DISABLED,
 
     /**
+     * A host was registered with the server.
+     */
+    HOST_REGISTERED,
+
+    /**
      * A host was added to the cluster.
      */
     HOST_ADDED,

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/events/HostAddedEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/HostAddedEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/HostAddedEvent.java
new file mode 100644
index 0000000..7832c16
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/HostAddedEvent.java
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.events;
+
+/**
+ * The {@link HostAddedEvent} is fired when a host is added to a cluster.
+ */
+public class HostAddedEvent extends ClusterEvent {
+
+  /**
+   * The host's name.
+   */
+  protected final String m_hostName;
+
+  /**
+   * Constructor.
+   *
+   * @param clusterId
+   *          the ID of the cluster.
+   * @param hostName
+   *          the name of the host.
+   */
+  public HostAddedEvent(long clusterId, String hostName) {
+    super(AmbariEventType.HOST_ADDED, clusterId);
+    m_hostName = hostName;
+  }
+
+  /**
+   * Gets the host's name that the event belongs to.
+   *
+   * @return the hostName
+   */
+  public String getHostName() {
+    return m_hostName;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/events/HostRegisteredEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/HostRegisteredEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/HostRegisteredEvent.java
new file mode 100644
index 0000000..07ff526
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/HostRegisteredEvent.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ambari.server.events;
+
+/**
+ * The {@link HostRegisteredEvent} class is fired when a host registered with
+ * the server.
+ */
+public class HostRegisteredEvent extends HostEvent {
+  /**
+   * Constructor.
+   *
+   * @param hostName
+   */
+  public HostRegisteredEvent(String hostName) {
+    super(AmbariEventType.HOST_REGISTERED, hostName);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString() {
+    StringBuilder buffer = new StringBuilder("HostRegistered{ ");
+    buffer.append("hostName=").append(m_hostName);
+    buffer.append("}");
+    return buffer.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/events/HostRemovedEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/HostRemovedEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/HostRemovedEvent.java
index a0aae66..e005754 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/HostRemovedEvent.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/HostRemovedEvent.java
@@ -28,7 +28,7 @@ public class HostRemovedEvent extends HostEvent {
    * @param hostName
    */
   public HostRemovedEvent(String hostName) {
-    super(AmbariEventType.HOST_ADDED, hostName);
+    super(AmbariEventType.HOST_REMOVED, hostName);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHashInvalidationListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHashInvalidationListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHashInvalidationListener.java
index 0accaf9..655352f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHashInvalidationListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHashInvalidationListener.java
@@ -91,7 +91,8 @@ public class AlertHashInvalidationListener {
       return;
     }
 
-    m_alertDefinitionHash.get().enqueueAgentCommands(clusterId, hosts);
+    AlertDefinitionHash hash = m_alertDefinitionHash.get();
+    hash.enqueueAgentCommands(clusterId, hosts);
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHostListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHostListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHostListener.java
index 51e5e67..d478bf5 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHostListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertHostListener.java
@@ -17,13 +17,26 @@
  */
 package org.apache.ambari.server.events.listeners.alerts;
 
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.EagerSingleton;
+import org.apache.ambari.server.events.AlertHashInvalidationEvent;
+import org.apache.ambari.server.events.HostAddedEvent;
 import org.apache.ambari.server.events.HostRemovedEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
+import org.apache.ambari.server.metadata.AgentAlertDefinitions;
+import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.AlertsDAO;
 import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.state.alert.AlertDefinition;
+import org.apache.ambari.server.state.alert.AlertDefinitionFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.eventbus.AllowConcurrentEvents;
 import com.google.common.eventbus.Subscribe;
@@ -31,8 +44,9 @@ import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
 /**
- * The {@link AlertHostListener} class handles {@link HostRemovedEvent} and
- * ensures that {@link AlertCurrentEntity} instances are properly cleaned up
+ * The {@link AlertHostListener} class handles {@link HostAddedEvent} and
+ * {@link HostRemovedEvent} and ensures that {@link AlertCurrentEntity}
+ * instances are properly cleaned up
  */
 @Singleton
 @EagerSingleton
@@ -40,7 +54,7 @@ public class AlertHostListener {
   /**
    * Logger.
    */
-  private static Log LOG = LogFactory.getLog(AlertHostListener.class);
+  private final static Logger LOG = LoggerFactory.getLogger(AlertHostListener.class);
 
   /**
    * Used for removing current alerts when a service is removed.
@@ -49,6 +63,37 @@ public class AlertHostListener {
   private AlertsDAO m_alertsDao;
 
   /**
+   * Used for checking to see if definitions already exist for a cluster.
+   */
+  @Inject
+  private AlertDefinitionDAO m_alertDefinitionDao;
+
+  /**
+   * Used to publish events when an alert definition has a lifecycle event.
+   */
+  @Inject
+  private AmbariEventPublisher m_eventPublisher;
+
+  /**
+   * All of the {@link AlertDefinition}s that are scoped for the agents.
+   */
+  @Inject
+  private AgentAlertDefinitions m_agentAlertDefinitions;
+
+  /**
+   * Used when a host is added to a cluster to coerce an {@link AlertDefinition}
+   * into an {@link AlertDefinitionEntity}.
+   */
+  @Inject
+  private AlertDefinitionFactory m_alertDefinitionFactory;
+
+  /**
+   * Used to prevent multiple threads from trying to create host alerts
+   * simultaneously.
+   */
+  private Lock m_hostAlertLock = new ReentrantLock();
+
+  /**
    * Constructor.
    *
    * @param publisher
@@ -59,15 +104,69 @@ public class AlertHostListener {
   }
 
   /**
-   * Removes any current alerts associated with the specified host.
-   *
-   * @param event
-   *          the published event being handled (not {@code null}).
+   * Handles the {@link HostAddedEvent} by performing the following actions:
+   * <ul>
+   * <li>Ensures that all host-level alerts are loaded for the cluster. This is
+   * especially useful when creating a cluster and no alerts were loaded on
+   * Ambari startup</li>
+   * <li>Broadcasts the {@link AlertHashInvalidationEvent} in order to push host
+   * alert definitions</li>
+   * </ul>
+   */
+  @Subscribe
+  @AllowConcurrentEvents
+  public void onAmbariEvent(HostAddedEvent event) {
+    LOG.debug("Received event {}", event);
+
+    long clusterId = event.getClusterId();
+
+    // load the host-only alert definitions
+    List<AlertDefinition> agentDefinitions = m_agentAlertDefinitions.getDefinitions();
+
+    // lock to prevent multiple threads from trying to create alert
+    // definitions at the same time
+    m_hostAlertLock.lock();
+
+    try {
+      for (AlertDefinition agentDefinition : agentDefinitions) {
+        AlertDefinitionEntity definition = m_alertDefinitionDao.findByName(
+            clusterId, agentDefinition.getName());
+
+        // this host definition does not exist, add it
+        if (null == definition) {
+          definition = m_alertDefinitionFactory.coerce(clusterId,
+              agentDefinition);
+
+          try {
+            m_alertDefinitionDao.create(definition);
+          } catch (AmbariException ambariException) {
+            LOG.error(
+                "Unable to create a host alert definition name {} in cluster {}",
+                definition.getDefinitionName(), definition.getClusterId(),
+                ambariException);
+          }
+        }
+      }
+    } finally {
+      m_hostAlertLock.unlock();
+    }
+
+    AlertHashInvalidationEvent invalidationEvent = new AlertHashInvalidationEvent(
+        event.getClusterId(), Collections.singletonList(event.getHostName()));
+
+    m_eventPublisher.publish(invalidationEvent);
+  }
+
+  /**
+   * Handles the {@link HostRemovedEvent} by performing the following actions:
+   * <ul>
+   * <li>Removes all {@link AlertCurrentEntity} for the removed host</li>
+   * </ul>
    */
   @Subscribe
   @AllowConcurrentEvents
   public void onAmbariEvent(HostRemovedEvent event) {
-    LOG.debug(event);
+    LOG.debug("Received event {}", event);
 
     // remove any current alerts for the removed host
     m_alertsDao.removeCurrentByHost(event.getHostName());

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertServiceStateListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertServiceStateListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertServiceStateListener.java
index b56f23d..fd7035d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertServiceStateListener.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/alerts/AlertServiceStateListener.java
@@ -126,13 +126,11 @@ public class AlertServiceStateListener {
     // create the default alert group for the new service; this MUST be done
     // before adding definitions so that they are properly added to the
     // default group
-    AlertGroupEntity serviceAlertGroup = new AlertGroupEntity();
-    serviceAlertGroup.setClusterId(clusterId);
-    serviceAlertGroup.setDefault(true);
-    serviceAlertGroup.setGroupName(serviceName);
-    serviceAlertGroup.setServiceName(serviceName);
-
-    m_alertDispatchDao.create(serviceAlertGroup);
+    try {
+      m_alertDispatchDao.createDefaultGroup(clusterId, serviceName);
+    } catch (AmbariException ambariException) {
+      LOG.error(ambariException);
+    }
 
     // populate alert definitions for the new service from the database, but
     // don't worry about sending down commands to the agents; the host

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/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 8e8c808..23de17e 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
@@ -24,6 +24,7 @@ import java.util.Set;
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.RootServiceResponseFactory;
 import org.apache.ambari.server.events.AlertDefinitionDeleteEvent;
 import org.apache.ambari.server.events.AlertDefinitionRegistrationEvent;
@@ -56,25 +57,25 @@ public class AlertDefinitionDAO {
    * JPA entity manager
    */
   @Inject
-  Provider<EntityManager> entityManagerProvider;
+  private Provider<EntityManager> entityManagerProvider;
 
   /**
    * DAO utilities for dealing mostly with {@link TypedQuery} results.
    */
   @Inject
-  DaoUtils daoUtils;
+  private DaoUtils daoUtils;
 
   /**
    * Alert history DAO.
    */
   @Inject
-  AlertsDAO alertsDao;
+  private AlertsDAO alertsDao;
 
   /**
    * Alert dispatch DAO.
    */
   @Inject
-  AlertDispatchDAO dispatchDao;
+  private AlertDispatchDAO dispatchDao;
 
   /**
    * Publishes the following events:
@@ -284,16 +285,25 @@ public class AlertDefinitionDAO {
    *          the definition to persist (not {@code null}).
    */
   @Transactional
-  public void create(AlertDefinitionEntity alertDefinition) {
+  public void create(AlertDefinitionEntity alertDefinition)
+      throws AmbariException {
     entityManagerProvider.get().persist(alertDefinition);
 
-    AlertGroupEntity group = dispatchDao.findDefaultServiceGroup(alertDefinition.getServiceName());
+    AlertGroupEntity group = dispatchDao.findDefaultServiceGroup(
+        alertDefinition.getClusterId(), alertDefinition.getServiceName());
 
-    if (null != group) {
-      group.addAlertDefinition(alertDefinition);
-      dispatchDao.merge(group);
+    if (null == group) {
+      // create the default alert group for the new service; this MUST be done
+      // before adding definitions so that they are properly added to the
+      // default group
+      String serviceName = alertDefinition.getServiceName();
+      group = dispatchDao.createDefaultGroup(alertDefinition.getClusterId(),
+          serviceName);
     }
 
+    group.addAlertDefinition(alertDefinition);
+    dispatchDao.merge(group);
+
     // publish the alert definition registration
     AlertDefinition coerced = alertDefinitionFactory.coerce(alertDefinition);
     if (null != coerced) {
@@ -339,7 +349,8 @@ public class AlertDefinitionDAO {
    * @param alertDefinition
    *          the definition to create or update (not {@code null}).
    */
-  public void createOrUpdate(AlertDefinitionEntity alertDefinition) {
+  public void createOrUpdate(AlertDefinitionEntity alertDefinition)
+      throws AmbariException {
     if (null == alertDefinition.getDefinitionId()) {
       create(alertDefinition);
     } else {

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
index b6c1e90..3a3ad15 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
@@ -17,7 +17,11 @@
  */
 package org.apache.ambari.server.orm.dao;
 
+import java.text.MessageFormat;
 import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
@@ -25,9 +29,11 @@ import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Order;
 import javax.persistence.metamodel.SingularAttribute;
 
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.api.query.JpaPredicateVisitor;
 import org.apache.ambari.server.api.query.JpaSortBuilder;
 import org.apache.ambari.server.controller.AlertNoticeRequest;
+import org.apache.ambari.server.controller.RootServiceResponseFactory.Services;
 import org.apache.ambari.server.controller.spi.Predicate;
 import org.apache.ambari.server.controller.utilities.PredicateHelper;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
@@ -35,7 +41,10 @@ import org.apache.ambari.server.orm.entities.AlertGroupEntity;
 import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
 import org.apache.ambari.server.orm.entities.AlertNoticeEntity_;
 import org.apache.ambari.server.orm.entities.AlertTargetEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.NotificationState;
+import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.alert.AlertGroup;
 
 import com.google.inject.Inject;
@@ -53,13 +62,26 @@ public class AlertDispatchDAO {
    * JPA entity manager
    */
   @Inject
-  Provider<EntityManager> entityManagerProvider;
+  private Provider<EntityManager> entityManagerProvider;
 
   /**
    * DAO utilities for dealing mostly with {@link TypedQuery} results.
    */
   @Inject
-  DaoUtils daoUtils;
+  private DaoUtils daoUtils;
+
+  /**
+   * Used to retrieve a cluster and its services when creating a default
+   * {@link AlertGroupEntity} for a service.
+   */
+  @Inject
+  private Provider<Clusters> m_clusters;
+
+  /**
+   * A lock that ensures that group writes are protected. This is useful since
+   * groups can be created through different events/threads in the system.
+   */
+  private final Lock m_groupLock = new ReentrantLock();
 
   /**
    * Gets an alert group with the specified ID.
@@ -256,18 +278,22 @@ public class AlertDispatchDAO {
   }
 
   /**
-   * Gets the default group for the specified service.
+   * Gets the default group for the specified cluster and service.
    *
+   * @param clusterId
+   *          the cluster that the group belongs to
    * @param serviceName
    *          the name of the service (not {@code null}).
    * @return the default group, or {@code null} if the service name is not valid
    *         for an installed service; otherwise {@code null} should not be
    *         possible.
    */
-  public AlertGroupEntity findDefaultServiceGroup(String serviceName) {
+  public AlertGroupEntity findDefaultServiceGroup(long clusterId,
+      String serviceName) {
     TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertGroupEntity.findServiceDefaultGroup", AlertGroupEntity.class);
 
+    query.setParameter("clusterId", clusterId);
     query.setParameter("serviceName", serviceName);
     return daoUtils.selectSingle(query);
   }
@@ -364,6 +390,49 @@ public class AlertDispatchDAO {
   }
 
   /**
+   * Creates a default group in the specified cluster and service. If the
+   * service is not valid, then this will throw an {@link AmbariException}.
+   *
+   * @param clusterId
+   *          the cluster that the group is in.
+   * @param serviceName
+   *          the name of the group which is also the service name.
+   */
+  public AlertGroupEntity createDefaultGroup(long clusterId, String serviceName)
+      throws AmbariException {
+    // AMBARI is a special service that we let through, otherwise we need to
+    // verify that the service exists before we create the default group
+    String ambariServiceName = Services.AMBARI.name();
+    if (!ambariServiceName.equals(serviceName)) {
+      Cluster cluster = m_clusters.get().getClusterById(clusterId);
+      Map<String, Service> services = cluster.getServices();
+
+      if (!services.containsKey(serviceName)) {
+        String message = MessageFormat.format(
+            "Unable to create a default alert group for unknown service {0} in cluster {1}",
+            serviceName, cluster.getClusterName());
+        throw new AmbariException(message);
+      }
+    }
+
+    AlertGroupEntity group = new AlertGroupEntity();
+
+    m_groupLock.lock();
+    try {
+      group.setClusterId(clusterId);
+      group.setDefault(true);
+      group.setGroupName(serviceName);
+      group.setServiceName(serviceName);
+
+      create(group);
+    } finally {
+      m_groupLock.unlock();
+    }
+
+    return group;
+  }
+
+  /**
    * Refresh the state of the alert group from the database.
    *
    * @param alertGroup

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
index 1127dd1..4908eea 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
@@ -503,8 +503,7 @@ public class AlertsDAO {
    */
   @Transactional
   public int removeCurrentByServiceComponentHost(String serviceName,
-      String componentName,
-      String hostName) {
+      String componentName, String hostName) {
 
     TypedQuery<AlertCurrentEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertCurrentEntity.removeByHostComponent", AlertCurrentEntity.class);

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
index dcad56e..1306c6c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ClusterServiceDAO.java
@@ -18,18 +18,20 @@
 
 package org.apache.ambari.server.orm.dao;
 
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.google.inject.persist.Transactional;
-import org.apache.ambari.server.orm.RequiresSession;
-import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
-import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
+import java.util.List;
 
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
-import java.util.List;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.ClusterServiceEntity;
+import org.apache.ambari.server.orm.entities.ClusterServiceEntityPK;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
 
 @Singleton
 public class ClusterServiceDAO {
@@ -84,7 +86,8 @@ public class ClusterServiceDAO {
 
   @Transactional
   public void removeByPK(ClusterServiceEntityPK clusterServiceEntityPK) {
-    remove(findByPK(clusterServiceEntityPK));
+    ClusterServiceEntity entity = findByPK(clusterServiceEntityPK);
+    entityManagerProvider.get().remove(entity);
   }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
index 8cf7ec3..341d1fd 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceComponentDesiredStateDAO.java
@@ -18,18 +18,20 @@
 
 package org.apache.ambari.server.orm.dao;
 
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.google.inject.persist.Transactional;
-import org.apache.ambari.server.orm.RequiresSession;
-import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntityPK;
-import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
+import java.util.List;
 
 import javax.persistence.EntityManager;
 import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
-import java.util.List;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntity;
+import org.apache.ambari.server.orm.entities.ServiceComponentDesiredStateEntityPK;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
 
 @Singleton
 public class ServiceComponentDesiredStateDAO {
@@ -75,6 +77,7 @@ public class ServiceComponentDesiredStateDAO {
 
   @Transactional
   public void removeByPK(ServiceComponentDesiredStateEntityPK primaryKey) {
-    remove(findByPK(primaryKey));
+    ServiceComponentDesiredStateEntity entity = findByPK(primaryKey);
+    entityManagerProvider.get().remove(entity);
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/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 a330c90..81fb133 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
@@ -536,4 +536,22 @@ public class AlertDefinitionEntity {
     int result = null != definitionId ? definitionId.hashCode() : 0;
     return result;
   }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString() {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append(getClass().getSimpleName());
+    buffer.append("{");
+    buffer.append("id=").append(definitionId);
+    buffer.append(", name=").append(definitionName);
+    buffer.append(", serviceName=").append(serviceName);
+    buffer.append(", componentName=").append(componentName);
+    buffer.append(", enabled=").append(enabled);
+    buffer.append(", hash=").append(hash);
+    buffer.append("}");
+    return buffer.toString();
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
index ac3586d..6607fb0 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
@@ -51,7 +51,7 @@ import javax.persistence.UniqueConstraint;
     @NamedQuery(name = "AlertGroupEntity.findByName", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.groupName = :groupName"),
     @NamedQuery(name = "AlertGroupEntity.findByNameInCluster", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.groupName = :groupName AND alertGroup.clusterId = :clusterId"),
     @NamedQuery(name = "AlertGroupEntity.findByAssociatedDefinition", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE :alertDefinition MEMBER OF alertGroup.alertDefinitions"),
-    @NamedQuery(name = "AlertGroupEntity.findServiceDefaultGroup", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.serviceName = :serviceName AND alertGroup.isDefault = 1") })
+    @NamedQuery(name = "AlertGroupEntity.findServiceDefaultGroup", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.clusterId = :clusterId AND alertGroup.serviceName = :serviceName AND alertGroup.isDefault = 1") })
 public class AlertGroupEntity {
 
   @Id
@@ -353,4 +353,19 @@ public class AlertGroupEntity {
     int result = null != groupId ? groupId.hashCode() : 0;
     return result;
   }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString() {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append(getClass().getSimpleName());
+    buffer.append("{");
+    buffer.append("id=").append(groupId);
+    buffer.append(", name=").append(groupName);
+    buffer.append(", default=").append(isDefault);
+    buffer.append("}");
+    return buffer.toString();
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java
index a671ae1..8e96aca 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertHistoryEntity.java
@@ -355,4 +355,21 @@ public class AlertHistoryEntity {
     return result;
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString() {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append(getClass().getSimpleName());
+    buffer.append("{");
+    buffer.append("id=").append(alertId);
+    buffer.append(", serviceName=").append(serviceName);
+    buffer.append(", componentName=").append(componentName);
+    buffer.append(", state=").append(alertState);
+    buffer.append(", label=").append(alertLabel);
+    buffer.append("}");
+    return buffer.toString();
+  }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java
index d18ec68..9f24dc3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertTargetEntity.java
@@ -295,4 +295,17 @@ public class AlertTargetEntity {
     return result;
   }
 
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString() {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append(getClass().getSimpleName());
+    buffer.append("{");
+    buffer.append("id=").append(targetId);
+    buffer.append(", name=").append(targetName);
+    buffer.append("}");
+    return buffer.toString();
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/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 abffa5d..c8b78a0 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
@@ -584,8 +584,8 @@ public class AlertDefinitionHash {
    *         {@code null}).
    */
   private Set<AlertDefinitionEntity> getAlertDefinitionEntities(
-      String clusterName,
-      String hostName) {
+      String clusterName, String hostName) {
+
     Set<AlertDefinitionEntity> definitions = new HashSet<AlertDefinitionEntity>();
 
     try {
@@ -598,45 +598,41 @@ public class AlertDefinitionHash {
       }
 
       long clusterId = cluster.getClusterId();
-      List<ServiceComponentHost> serviceComponents = cluster.getServiceComponentHosts(hostName);
-      if (null == serviceComponents || serviceComponents.size() == 0) {
-        LOG.warn(
-            "Unable to get alert definitions for {} since there are no service components defined",
-            hostName);
-
-        return Collections.emptySet();
-      }
-
-      for (ServiceComponentHost serviceComponent : serviceComponents) {
-        String serviceName = serviceComponent.getServiceName();
-        String componentName = serviceComponent.getServiceComponentName();
 
-        // add all alerts for this service/component pair
-        definitions.addAll(m_definitionDao.findByServiceComponent(
-            clusterId, serviceName, componentName));
-      }
+      // services and components
+      List<ServiceComponentHost> serviceComponents = cluster.getServiceComponentHosts(hostName);
+      if (null == serviceComponents || !serviceComponents.isEmpty()) {
+        for (ServiceComponentHost serviceComponent : serviceComponents) {
+          String serviceName = serviceComponent.getServiceName();
+          String componentName = serviceComponent.getServiceComponentName();
+
+          // add all alerts for this service/component pair
+          definitions.addAll(m_definitionDao.findByServiceComponent(clusterId,
+              serviceName, componentName));
+        }
 
-      // for every service, get the master components and see if the host
-      // is a master
-      Set<String> services = new HashSet<String>();
-      for (Entry<String, Service> entry : cluster.getServices().entrySet()) {
-        Service service = entry.getValue();
-        Map<String, ServiceComponent> components = service.getServiceComponents();
-        for (Entry<String, ServiceComponent> component : components.entrySet()) {
-          if (component.getValue().isMasterComponent()) {
-            Map<String, ServiceComponentHost> hosts = component.getValue().getServiceComponentHosts();
-
-            if( hosts.containsKey( hostName ) ){
-              services.add(service.getName());
+        // for every service, get the master components and see if the host
+        // is a master
+        Set<String> services = new HashSet<String>();
+        for (Entry<String, Service> entry : cluster.getServices().entrySet()) {
+          Service service = entry.getValue();
+          Map<String, ServiceComponent> components = service.getServiceComponents();
+          for (Entry<String, ServiceComponent> component : components.entrySet()) {
+            if (component.getValue().isMasterComponent()) {
+              Map<String, ServiceComponentHost> hosts = component.getValue().getServiceComponentHosts();
+
+              if (hosts.containsKey(hostName)) {
+                services.add(service.getName());
+              }
             }
           }
         }
-      }
 
-      // add all service scoped alerts
-      if( services.size() > 0 ){
-        definitions.addAll(m_definitionDao.findByServiceMaster(clusterId,
-            services));
+        // add all service scoped alerts
+        if (services.size() > 0) {
+          definitions.addAll(m_definitionDao.findByServiceMaster(clusterId,
+              services));
+        }
       }
 
       // add any alerts not bound to a service (host level alerts)

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/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 991d289..d2c7428 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
@@ -39,11 +39,12 @@ import org.apache.ambari.server.HostNotFoundException;
 import org.apache.ambari.server.agent.DiskInfo;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.events.HostAddedEvent;
+import org.apache.ambari.server.events.HostRegisteredEvent;
 import org.apache.ambari.server.events.HostRemovedEvent;
 import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.dao.ClusterDAO;
 import org.apache.ambari.server.orm.dao.ClusterVersionDAO;
-import org.apache.ambari.server.orm.dao.ConfigGroupHostMappingDAO;
 import org.apache.ambari.server.orm.dao.HostDAO;
 import org.apache.ambari.server.orm.dao.HostVersionDAO;
 import org.apache.ambari.server.orm.dao.ResourceDAO;
@@ -121,8 +122,6 @@ public class ClustersImpl implements Clusters {
   @Inject
   Gson gson;
   @Inject
-  private ConfigGroupHostMappingDAO configGroupHostMappingDAO;
-  @Inject
   private SecurityHelper securityHelper;
 
   /**
@@ -341,12 +340,14 @@ public class ClustersImpl implements Clusters {
   @Override
   public void addHost(String hostname) throws AmbariException {
     checkLoaded();
+
     String duplicateMessage = "Duplicate entry for Host"
         + ", hostName= " + hostname;
 
     if (hosts.containsKey(hostname)) {
       throw new AmbariException(duplicateMessage);
     }
+
     r.lock();
 
     try {
@@ -371,6 +372,10 @@ public class ClustersImpl implements Clusters {
     } finally {
       r.unlock();
     }
+
+    // publish the event
+    HostRegisteredEvent event = new HostRegisteredEvent(hostname);
+    eventPublisher.publish(event);
   }
 
   private boolean isOsSupportedByClusterStack(Cluster c, Host h) throws AmbariException {
@@ -558,6 +563,10 @@ public class ClustersImpl implements Clusters {
 
     clusterDAO.merge(clusterEntity);
     hostDAO.merge(hostEntity);
+
+    // publish the event for adding a host to a cluster
+    HostAddedEvent event = new HostAddedEvent(clusterId, hostName);
+    eventPublisher.publish(event);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/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 dc71862..0c93ec2 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
@@ -20,12 +20,15 @@ package org.apache.ambari.server.orm;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
@@ -59,11 +62,22 @@ import org.apache.ambari.server.orm.entities.ResourceEntity;
 import org.apache.ambari.server.orm.entities.ResourceTypeEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.orm.entities.UserEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.HostState;
+import org.apache.ambari.server.state.RepositoryVersionState;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
+import org.apache.ambari.server.state.ServiceComponentFactory;
+import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.ServiceComponentHostFactory;
+import org.apache.ambari.server.state.ServiceFactory;
+import org.apache.ambari.server.state.StackId;
+import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.alert.Scope;
 import org.apache.ambari.server.state.alert.SourceType;
 import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.util.Assert;
 
 import com.google.inject.Inject;
 import com.google.inject.Injector;
@@ -289,11 +303,131 @@ public class OrmTestHelper {
     clusterDAO.create(clusterEntity);
 
     clusterEntity = clusterDAO.findByName(clusterEntity.getClusterName());
-    Assert.notNull(clusterEntity);
-    Assert.isTrue(clusterEntity.getClusterId() > 0);
+    assertNotNull(clusterEntity);
+    assertTrue(clusterEntity.getClusterId() > 0);
     return clusterEntity.getClusterId();
   }
 
+  public Cluster buildNewCluster(Clusters clusters,
+      ServiceFactory serviceFactory, ServiceComponentFactory componentFactory,
+      ServiceComponentHostFactory schFactory, String hostName) throws Exception {
+    String clusterName = "cluster-" + System.currentTimeMillis();
+    clusters.addCluster(clusterName);
+    Cluster cluster = clusters.getCluster(clusterName);
+    cluster = initializeClusterWithStack(cluster);
+
+    addHost(clusters, cluster, hostName);
+
+    installHdfsService(cluster, serviceFactory, componentFactory, schFactory, hostName);
+    installYarnService(cluster, serviceFactory, componentFactory, schFactory,
+        hostName);
+    return cluster;
+  }
+
+  public Cluster initializeClusterWithStack(Cluster cluster) throws Exception {
+    StackId stackId = new StackId("HDP", "2.0.6");
+    cluster.setDesiredStackVersion(stackId);
+    cluster.createClusterVersion(stackId.getStackName(),
+        stackId.getStackVersion(), "admin", RepositoryVersionState.CURRENT);
+    return cluster;
+  }
+
+  /**
+   * @throws Exception
+   */
+  public void addHost(Clusters clusters, Cluster cluster, String hostName)
+      throws Exception {
+    clusters.addHost(hostName);
+
+    Host host = clusters.getHost(hostName);
+    Map<String, String> hostAttributes = new HashMap<String, String>();
+    hostAttributes.put("os_family", "redhat");
+    hostAttributes.put("os_release_version", "6.4");
+    host.setHostAttributes(hostAttributes);
+    host.setState(HostState.HEALTHY);
+    host.persist();
+
+    clusters.mapHostToCluster(hostName, cluster.getClusterName());
+  }
+
+  /**
+   * Calls {@link Service#persist()} to mock a service install along with
+   * creating a single {@link Host} and {@link ServiceComponentHost}.
+   */
+  public void installHdfsService(Cluster cluster,
+      ServiceFactory serviceFactory, ServiceComponentFactory componentFactory,
+      ServiceComponentHostFactory schFactory, String hostName) throws Exception {
+    String serviceName = "HDFS";
+    Service service = serviceFactory.createNew(cluster, serviceName);
+    cluster.addService(service);
+    service.persist();
+    service = cluster.getService(serviceName);
+    assertNotNull(service);
+
+    ServiceComponent datanode = componentFactory.createNew(service, "DATANODE");
+
+    service.addServiceComponent(datanode);
+    datanode.setDesiredState(State.INSTALLED);
+    datanode.persist();
+
+    ServiceComponentHost sch = schFactory.createNew(datanode, hostName);
+
+    datanode.addServiceComponentHost(sch);
+    sch.setDesiredState(State.INSTALLED);
+    sch.setState(State.INSTALLED);
+    sch.setDesiredStackVersion(new StackId("HDP-2.0.6"));
+    sch.setStackVersion(new StackId("HDP-2.0.6"));
+
+    sch.persist();
+
+    ServiceComponent namenode = componentFactory.createNew(service, "NAMENODE");
+
+    service.addServiceComponent(namenode);
+    namenode.setDesiredState(State.INSTALLED);
+    namenode.persist();
+
+    sch = schFactory.createNew(namenode, hostName);
+    namenode.addServiceComponentHost(sch);
+    sch.setDesiredState(State.INSTALLED);
+    sch.setState(State.INSTALLED);
+    sch.setDesiredStackVersion(new StackId("HDP-2.0.6"));
+    sch.setStackVersion(new StackId("HDP-2.0.6"));
+
+    sch.persist();
+  }
+
+  /**
+   * Calls {@link Service#persist()} to mock a service install along with
+   * creating a single {@link Host} and {@link ServiceComponentHost}.
+   */
+  public void installYarnService(Cluster cluster,
+      ServiceFactory serviceFactory, ServiceComponentFactory componentFactory,
+      ServiceComponentHostFactory schFactory, String hostName) throws Exception {
+    String serviceName = "YARN";
+    Service service = serviceFactory.createNew(cluster, serviceName);
+    cluster.addService(service);
+    service.persist();
+    service = cluster.getService(serviceName);
+    assertNotNull(service);
+
+    ServiceComponent resourceManager = componentFactory.createNew(service,
+        "RESOURCEMANAGER");
+
+    service.addServiceComponent(resourceManager);
+    resourceManager.setDesiredState(State.INSTALLED);
+    resourceManager.persist();
+
+    ServiceComponentHost sch = schFactory.createNew(resourceManager, hostName);
+
+    resourceManager.addServiceComponentHost(sch);
+    sch.setDesiredState(State.INSTALLED);
+    sch.setState(State.INSTALLED);
+    sch.setDesiredStackVersion(new StackId("HDP-2.0.6"));
+    sch.setStackVersion(new StackId("HDP-2.0.6"));
+
+    sch.persist();
+  }
+
   /**
    * Creates an alert target.
    *
@@ -324,7 +458,7 @@ public class OrmTestHelper {
     AlertDefinitionEntity definition = new AlertDefinitionEntity();
     definition.setDefinitionName("Alert Definition "
         + System.currentTimeMillis());
-    definition.setServiceName("Service " + System.currentTimeMillis());
+    definition.setServiceName("AMBARI");
     definition.setComponentName(null);
     definition.setClusterId(clusterId);
     definition.setHash(UUID.randomUUID().toString());
@@ -385,8 +519,8 @@ public class OrmTestHelper {
 
     List<AlertGroupEntity> defaultGroups = alertDispatchDAO.findAllGroups(clusterId);
     assertEquals(2, defaultGroups.size());
-    assertNotNull(alertDispatchDAO.findDefaultServiceGroup("HDFS"));
-    assertNotNull(alertDispatchDAO.findDefaultServiceGroup("OOZIE"));
+    assertNotNull(alertDispatchDAO.findDefaultServiceGroup(clusterId, "HDFS"));
+    assertNotNull(alertDispatchDAO.findDefaultServiceGroup(clusterId, "OOZIE"));
 
     return defaultGroups;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9159421b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
index 0d2d305..3d8f898 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
@@ -19,21 +19,20 @@
 package org.apache.ambari.server.orm.dao;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.lang.reflect.Field;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
-import junit.framework.Assert;
-
+import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.AlertNoticeRequest;
 import org.apache.ambari.server.controller.internal.AlertNoticeResourceProvider;
 import org.apache.ambari.server.controller.internal.PageRequestImpl;
@@ -44,6 +43,8 @@ import org.apache.ambari.server.controller.spi.SortRequest;
 import org.apache.ambari.server.controller.spi.SortRequest.Order;
 import org.apache.ambari.server.controller.spi.SortRequestProperty;
 import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.events.listeners.alerts.AlertServiceStateListener;
+import org.apache.ambari.server.events.publishers.AmbariEventPublisher;
 import org.apache.ambari.server.orm.AlertDaoHelper;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
@@ -55,25 +56,18 @@ import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
 import org.apache.ambari.server.orm.entities.AlertTargetEntity;
 import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.Cluster;
-import org.apache.ambari.server.state.RepositoryVersionState;
 import org.apache.ambari.server.state.Clusters;
-import org.apache.ambari.server.state.Host;
-import org.apache.ambari.server.state.HostState;
 import org.apache.ambari.server.state.NotificationState;
-import org.apache.ambari.server.state.Service;
-import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentFactory;
-import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceComponentHostFactory;
 import org.apache.ambari.server.state.ServiceFactory;
-import org.apache.ambari.server.state.StackId;
-import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.alert.Scope;
 import org.apache.ambari.server.state.alert.SourceType;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.google.common.eventbus.EventBus;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
 import com.google.inject.persist.PersistService;
@@ -86,7 +80,7 @@ public class AlertDispatchDAOTest {
   private final static String HOSTNAME = "c6401.ambari.apache.org";
 
   private Clusters m_clusters;
-  private Long m_clusterId;
+  private Cluster m_cluster;
   private Injector m_injector;
   private AlertDispatchDAO m_dao;
   private AlertDefinitionDAO m_definitionDao;
@@ -97,6 +91,8 @@ public class AlertDispatchDAOTest {
   private ServiceComponentFactory m_componentFactory;
   private ServiceComponentHostFactory m_schFactory;
   private AlertDaoHelper m_alertHelper;
+  private AmbariEventPublisher m_eventPublisher;
+  private EventBus m_synchronizedBus;
 
   /**
    *
@@ -114,15 +110,24 @@ public class AlertDispatchDAOTest {
     m_schFactory = m_injector.getInstance(ServiceComponentHostFactory.class);
     m_clusters = m_injector.getInstance(Clusters.class);
     m_alertHelper = m_injector.getInstance(AlertDaoHelper.class);
+    m_eventPublisher = m_injector.getInstance(AmbariEventPublisher.class);
+
+    // !!! need a synchronous op for testing
+    m_synchronizedBus = new EventBus();
+    Field field = AmbariEventPublisher.class.getDeclaredField("m_eventBus");
+    field.setAccessible(true);
+    field.set(m_eventPublisher, m_synchronizedBus);
+
+    m_cluster = m_clusters.getClusterById(m_helper.createCluster());
+    m_helper.initializeClusterWithStack(m_cluster);
 
-    m_clusterId = m_helper.createCluster();
     Set<AlertTargetEntity> targets = createTargets();
 
     for (int i = 0; i < 10; i++) {
       AlertGroupEntity group = new AlertGroupEntity();
       group.setDefault(false);
       group.setGroupName("Group Name " + i);
-      group.setClusterId(m_clusterId);
+      group.setClusterId(m_cluster.getClusterId());
       for (AlertTargetEntity alertTarget : targets) {
         group.addAlertTarget(alertTarget);
       }
@@ -214,7 +219,8 @@ public class AlertDispatchDAOTest {
     Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
     targets.add(target);
 
-    AlertGroupEntity group = m_helper.createAlertGroup(m_clusterId, targets);
+    AlertGroupEntity group = m_helper.createAlertGroup(
+        m_cluster.getClusterId(), targets);
     AlertGroupEntity actual = m_dao.findGroupById(group.getGroupId());
     assertNotNull(group);
 
@@ -231,7 +237,8 @@ public class AlertDispatchDAOTest {
   public void testGroupDefinitions() throws Exception {
     List<AlertDefinitionEntity> definitions = createDefinitions();
 
-    AlertGroupEntity group = m_helper.createAlertGroup(m_clusterId, null);
+    AlertGroupEntity group = m_helper.createAlertGroup(
+        m_cluster.getClusterId(), null);
 
     group = m_dao.findGroupById(group.getGroupId());
     assertNotNull(group);
@@ -272,7 +279,8 @@ public class AlertDispatchDAOTest {
     Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
     targets.add(target);
 
-    AlertGroupEntity group = m_helper.createAlertGroup(m_clusterId, targets);
+    AlertGroupEntity group = m_helper.createAlertGroup(
+        m_cluster.getClusterId(), targets);
     AlertTargetEntity actual = m_dao.findTargetById(target.getTargetId());
     assertNotNull(actual);
 
@@ -297,7 +305,8 @@ public class AlertDispatchDAOTest {
   public void testDeleteGroup() throws Exception {
     int targetCount = m_dao.findAllTargets().size();
 
-    AlertGroupEntity group = m_helper.createAlertGroup(m_clusterId, null);
+    AlertGroupEntity group = m_helper.createAlertGroup(
+        m_cluster.getClusterId(), null);
     AlertTargetEntity target = m_helper.createAlertTarget();
     assertEquals(targetCount + 1, m_dao.findAllTargets().size());
 
@@ -347,7 +356,8 @@ public class AlertDispatchDAOTest {
     Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
     targets.add(target);
 
-    AlertGroupEntity group = m_helper.createAlertGroup(m_clusterId, targets);
+    AlertGroupEntity group = m_helper.createAlertGroup(
+        m_cluster.getClusterId(), targets);
     assertEquals(1, group.getAlertTargets().size());
 
     target = m_dao.findTargetById(target.getTargetId());
@@ -377,7 +387,8 @@ public class AlertDispatchDAOTest {
 
     String groupName = "Group Name " + System.currentTimeMillis();
 
-    AlertGroupEntity group = m_helper.createAlertGroup(m_clusterId, null);
+    AlertGroupEntity group = m_helper.createAlertGroup(
+        m_cluster.getClusterId(), null);
 
     group = m_dao.findGroupById(group.getGroupId());
     group.setGroupName(groupName + "FOO");
@@ -406,7 +417,8 @@ public class AlertDispatchDAOTest {
   @Test
   public void testFindGroupsByDefinition() throws Exception {
     List<AlertDefinitionEntity> definitions = createDefinitions();
-    AlertGroupEntity group = m_helper.createAlertGroup(m_clusterId, null);
+    AlertGroupEntity group = m_helper.createAlertGroup(
+        m_cluster.getClusterId(), null);
 
     group = m_dao.findGroupById(group.getGroupId());
     assertNotNull(group);
@@ -420,10 +432,11 @@ public class AlertDispatchDAOTest {
     group = m_dao.findGroupByName(group.getGroupName());
     assertEquals(definitions.size(), group.getAlertDefinitions().size());
 
+    // assert that the definition is now part of 2 groups (the default group
+    // and the newly associated group from above)
     for (AlertDefinitionEntity definition : definitions) {
       List<AlertGroupEntity> groups = m_dao.findGroupsByDefinition(definition);
-      assertEquals(1, groups.size());
-      assertEquals(group.getGroupId(), groups.get(0).getGroupId());
+      assertEquals(2, groups.size());
     }
   }
 
@@ -437,7 +450,7 @@ public class AlertDispatchDAOTest {
 
     AlertHistoryEntity history = new AlertHistoryEntity();
     history.setServiceName(definition.getServiceName());
-    history.setClusterId(m_clusterId);
+    history.setClusterId(m_cluster.getClusterId());
     history.setAlertDefinition(definition);
     history.setAlertLabel("Label");
     history.setAlertState(AlertState.OK);
@@ -468,7 +481,9 @@ public class AlertDispatchDAOTest {
    */
   @Test
   public void testAlertNoticePredicate() throws Exception {
-    Cluster cluster = initializeNewCluster();
+    Cluster cluster = m_helper.buildNewCluster(m_clusters, m_serviceFactory,
+        m_componentFactory, m_schFactory, HOSTNAME);
+
     m_alertHelper.populateData(cluster);
 
     Predicate clusterPredicate = null;
@@ -544,7 +559,9 @@ public class AlertDispatchDAOTest {
    */
   @Test
   public void testAlertNoticePagination() throws Exception {
-    Cluster cluster = initializeNewCluster();
+    Cluster cluster = m_helper.buildNewCluster(m_clusters, m_serviceFactory,
+        m_componentFactory, m_schFactory, HOSTNAME);
+
     m_alertHelper.populateData(cluster);
 
     AlertNoticeRequest request = new AlertNoticeRequest();
@@ -583,7 +600,9 @@ public class AlertDispatchDAOTest {
    */
   @Test
   public void testAlertNoticeSorting() throws Exception {
-    Cluster cluster = initializeNewCluster();
+    Cluster cluster = m_helper.buildNewCluster(m_clusters, m_serviceFactory,
+        m_componentFactory, m_schFactory, HOSTNAME);
+
     m_alertHelper.populateData(cluster);
 
     List<SortRequestProperty> sortProperties = new ArrayList<SortRequestProperty>();
@@ -640,15 +659,135 @@ public class AlertDispatchDAOTest {
   }
 
   /**
+   *
+   */
+  @Test
+  public void testFindDefaultGroup() throws Exception {
+    m_synchronizedBus.register(m_injector.getInstance(AlertServiceStateListener.class));
+
+    List<AlertGroupEntity> groups = m_dao.findAllGroups();
+    assertNotNull(groups);
+    assertEquals(10, groups.size());
+
+    for (AlertGroupEntity group : groups) {
+      assertFalse(group.isDefault());
+    }
+
+    Cluster cluster = m_helper.buildNewCluster(m_clusters, m_serviceFactory,
+        m_componentFactory, m_schFactory, HOSTNAME);
+
+    AlertGroupEntity hdfsGroup = m_dao.findDefaultServiceGroup(
+        cluster.getClusterId(), "HDFS");
+
+    assertNotNull(hdfsGroup);
+    assertTrue(hdfsGroup.isDefault());
+  }
+
+  /**
+   * Tests that when creating a new {@link AlertDefinitionEntity}, if the group
+   * for its service does not exist, then it will be created.
+   */
+  @Test
+  public void testDefaultGroupAutomaticCreation() throws Exception {
+    m_synchronizedBus.register(m_injector.getInstance(AlertServiceStateListener.class));
+
+    List<AlertGroupEntity> groups = m_dao.findAllGroups();
+    assertNotNull(groups);
+    assertEquals(10, groups.size());
+
+    for (AlertGroupEntity group : groups) {
+      assertFalse(group.isDefault());
+    }
+
+    Cluster cluster = m_helper.buildNewCluster(m_clusters, m_serviceFactory,
+        m_componentFactory, m_schFactory, HOSTNAME);
+
+    AlertGroupEntity hdfsGroup = m_dao.findDefaultServiceGroup(
+        cluster.getClusterId(), "HDFS");
+
+    // remove the HDFS default group
+    m_dao.remove(hdfsGroup);
+    hdfsGroup = m_dao.findDefaultServiceGroup(cluster.getClusterId(), "HDFS");
+    assertNull(hdfsGroup);
+
+    AlertDefinitionEntity datanodeProcess = new AlertDefinitionEntity();
+    datanodeProcess.setClusterId(cluster.getClusterId());
+    datanodeProcess.setDefinitionName("datanode_process");
+    datanodeProcess.setServiceName("HDFS");
+    datanodeProcess.setComponentName("DATANODE");
+    datanodeProcess.setHash(UUID.randomUUID().toString());
+    datanodeProcess.setScheduleInterval(60);
+    datanodeProcess.setScope(Scope.SERVICE);
+    datanodeProcess.setSource("{\"type\" : \"SCRIPT\"}");
+    datanodeProcess.setSourceType(SourceType.SCRIPT);
+    m_definitionDao.create(datanodeProcess);
+
+    // the group should be created and should be default
+    hdfsGroup = m_dao.findDefaultServiceGroup(cluster.getClusterId(), "HDFS");
+    assertNotNull(hdfsGroup);
+    assertTrue(hdfsGroup.isDefault());
+  }
+
+  /**
+   * Tests that when creating a new {@link AlertDefinitionEntity}, if the group
+   * for its service does not exist, then it will not be created if the service
+   * is invalid.
+   */
+  @Test(expected = AmbariException.class)
+  public void testDefaultGroupInvalidServiceNoCreation() throws Exception {
+    m_synchronizedBus.register(m_injector.getInstance(AlertServiceStateListener.class));
+
+    List<AlertGroupEntity> groups = m_dao.findAllGroups();
+    assertNotNull(groups);
+    assertEquals(10, groups.size());
+
+    for (AlertGroupEntity group : groups) {
+      assertFalse(group.isDefault());
+    }
+
+    Cluster cluster = m_helper.buildNewCluster(m_clusters, m_serviceFactory,
+        m_componentFactory, m_schFactory, HOSTNAME);
+
+    assertEquals(12, m_dao.findAllGroups().size());
+
+    // create a definition with an invalid service
+    AlertDefinitionEntity datanodeProcess = new AlertDefinitionEntity();
+    datanodeProcess.setClusterId(cluster.getClusterId());
+    datanodeProcess.setDefinitionName("datanode_process");
+    datanodeProcess.setServiceName("INVALID");
+    datanodeProcess.setComponentName("DATANODE");
+    datanodeProcess.setHash(UUID.randomUUID().toString());
+    datanodeProcess.setScheduleInterval(60);
+    datanodeProcess.setScope(Scope.SERVICE);
+    datanodeProcess.setSource("{\"type\" : \"SCRIPT\"}");
+    datanodeProcess.setSourceType(SourceType.SCRIPT);
+
+    try {
+      m_definitionDao.create(datanodeProcess);
+    } finally {
+      // assert no group was added
+      assertEquals(12, m_dao.findAllGroups().size());
+    }
+  }
+
+  /**
    * @return
    */
   private List<AlertDefinitionEntity> createDefinitions() throws Exception {
+    // add a host to the cluster
+    m_helper.addHost(m_clusters, m_cluster, HOSTNAME);
+
+    // install YARN (which doesn't have any alerts defined in the test JSON)
+    // so that the definitions get created correctly
+    m_helper.installYarnService(m_cluster, m_serviceFactory,
+        m_componentFactory, m_schFactory, HOSTNAME);
+
     for (int i = 0; i < 8; i++) {
       AlertDefinitionEntity definition = new AlertDefinitionEntity();
       definition.setDefinitionName("Alert Definition " + i);
-      definition.setServiceName("HDFS");
+      definition.setServiceName("YARN");
       definition.setComponentName(null);
-      definition.setClusterId(m_clusterId);
+      definition.setClusterId(m_cluster.getClusterId());
       definition.setHash(UUID.randomUUID().toString());
       definition.setScheduleInterval(60);
       definition.setScope(Scope.SERVICE);
@@ -680,81 +819,4 @@ public class AlertDispatchDAOTest {
 
     return targets;
   }
-
-  private Cluster initializeNewCluster() throws Exception {
-    String clusterName = "cluster-" + System.currentTimeMillis();
-    m_clusters.addCluster(clusterName);
-
-    Cluster cluster = m_clusters.getCluster(clusterName);
-    StackId stackId = new StackId("HDP", "2.0.6");
-    cluster.setDesiredStackVersion(stackId);
-    cluster.createClusterVersion(stackId.getStackName(), stackId.getStackVersion(), "admin", RepositoryVersionState.CURRENT);
-
-    addHost();
-    m_clusters.mapHostToCluster(HOSTNAME, cluster.getClusterName());
-
-    installHdfsService(cluster);
-    return cluster;
-  }
-
-  /**
-   * @throws Exception
-   */
-  private void addHost() throws Exception {
-    m_clusters.addHost(HOSTNAME);
-
-    Host host = m_clusters.getHost(HOSTNAME);
-    Map<String, String> hostAttributes = new HashMap<String, String>();
-    hostAttributes.put("os_family", "redhat");
-    hostAttributes.put("os_release_version", "6.4");
-    host.setHostAttributes(hostAttributes);
-    host.setState(HostState.HEALTHY);
-    host.persist();
-  }
-
-  /**
-   * Calls {@link Service#persist()} to mock a service install along with
-   * creating a single {@link Host} and {@link ServiceComponentHost}.
-   */
-  private void installHdfsService(Cluster cluster) throws Exception {
-    String serviceName = "HDFS";
-    Service service = m_serviceFactory.createNew(cluster, serviceName);
-    cluster.addService(service);
-    service.persist();
-    service = cluster.getService(serviceName);
-    Assert.assertNotNull(service);
-
-    ServiceComponent datanode = m_componentFactory.createNew(service,
-        "DATANODE");
-
-    service.addServiceComponent(datanode);
-    datanode.setDesiredState(State.INSTALLED);
-    datanode.persist();
-
-    ServiceComponentHost sch = m_schFactory.createNew(datanode, HOSTNAME);
-
-    datanode.addServiceComponentHost(sch);
-    sch.setDesiredState(State.INSTALLED);
-    sch.setState(State.INSTALLED);
-    sch.setDesiredStackVersion(new StackId("HDP-2.0.6"));
-    sch.setStackVersion(new StackId("HDP-2.0.6"));
-
-    sch.persist();
-
-    ServiceComponent namenode = m_componentFactory.createNew(service,
-        "NAMENODE");
-
-    service.addServiceComponent(namenode);
-    namenode.setDesiredState(State.INSTALLED);
-    namenode.persist();
-
-    sch = m_schFactory.createNew(namenode, HOSTNAME);
-    namenode.addServiceComponentHost(sch);
-    sch.setDesiredState(State.INSTALLED);
-    sch.setState(State.INSTALLED);
-    sch.setDesiredStackVersion(new StackId("HDP-2.0.6"));
-    sch.setStackVersion(new StackId("HDP-2.0.6"));
-
-    sch.persist();
-  }
 }