You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2014/07/18 14:13:49 UTC

[1/2] AMBARI-6528. Add AlertDefinition endpoint and resource provider (ncole)

Repository: ambari
Updated Branches:
  refs/heads/trunk 7bdb1e42c -> 39a92eb49


http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
new file mode 100644
index 0000000..de48756
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProviderTest.java
@@ -0,0 +1,162 @@
+/**
+ * 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.controller.internal;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+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.MetricAlert;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * AlertDefinition tests
+ */
+public class AlertDefinitionResourceProviderTest {
+
+  AlertDefinitionDAO dao = null;
+  
+  @Before
+  public void before() {
+    dao = EasyMock.createStrictMock(AlertDefinitionDAO.class);
+    
+    AlertDefinitionResourceProvider.init(dao);
+  }
+  
+  @Test
+  public void testGetResourcesNoPredicate() throws Exception {
+    AlertDefinitionResourceProvider provider = createProvider(null);
+    
+    Request request = PropertyHelper.getReadRequest("AlertDefinition/cluster_name",
+        "AlertDefinition/id");
+    
+    EasyMock.expect(dao.findAll()).andReturn(getMockEntities());
+
+    EasyMock.replay(dao);
+    
+    Set<Resource> results = provider.getResources(request, null);
+    
+    assertEquals(0, results.size());
+  }  
+
+  @Test
+  public void testGetResourcesClusterPredicate() throws Exception {
+    Request request = PropertyHelper.getReadRequest(
+        AlertDefinitionResourceProvider.ALERT_DEF_CLUSTER_NAME,
+        AlertDefinitionResourceProvider.ALERT_DEF_ID,
+        AlertDefinitionResourceProvider.ALERT_DEF_NAME);
+    
+    AmbariManagementController amc = EasyMock.createMock(AmbariManagementController.class);
+    Clusters clusters = EasyMock.createMock(Clusters.class);
+    Cluster cluster = EasyMock.createMock(Cluster.class);
+    EasyMock.expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+    EasyMock.expect(clusters.getCluster(EasyMock.<String>anyObject())).andReturn(cluster).atLeastOnce();
+    EasyMock.expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).anyTimes();
+    
+    Predicate predicate = new PredicateBuilder().property(
+        AlertDefinitionResourceProvider.ALERT_DEF_CLUSTER_NAME).equals("c1").toPredicate();    
+    
+    EasyMock.expect(dao.findAll(1L)).andReturn(getMockEntities());
+
+    EasyMock.replay(amc, clusters, cluster, dao);
+    
+    AlertDefinitionResourceProvider provider = createProvider(amc);    
+    Set<Resource> results = provider.getResources(request, predicate);
+    
+    assertEquals(1, results.size());
+    
+    Resource r = results.iterator().next();
+    
+    Assert.assertEquals("my_def", r.getPropertyValue(AlertDefinitionResourceProvider.ALERT_DEF_NAME));
+  }
+  
+  @Test
+  public void testGetSingleResource() throws Exception {
+    Request request = PropertyHelper.getReadRequest(
+        AlertDefinitionResourceProvider.ALERT_DEF_CLUSTER_NAME,
+        AlertDefinitionResourceProvider.ALERT_DEF_ID,
+        AlertDefinitionResourceProvider.ALERT_DEF_NAME,
+        AlertDefinitionResourceProvider.ALERT_DEF_SOURCE_TYPE);
+    
+    AmbariManagementController amc = EasyMock.createMock(AmbariManagementController.class);
+    Clusters clusters = EasyMock.createMock(Clusters.class);
+    Cluster cluster = EasyMock.createMock(Cluster.class);
+    EasyMock.expect(amc.getClusters()).andReturn(clusters).atLeastOnce();
+    EasyMock.expect(clusters.getCluster(EasyMock.<String>anyObject())).andReturn(cluster).atLeastOnce();
+    EasyMock.expect(cluster.getClusterId()).andReturn(Long.valueOf(1)).anyTimes();
+    
+    Predicate predicate = new PredicateBuilder().property(
+        AlertDefinitionResourceProvider.ALERT_DEF_CLUSTER_NAME).equals("c1")
+          .and().property(AlertDefinitionResourceProvider.ALERT_DEF_ID).equals("1").toPredicate();    
+    
+    EasyMock.expect(dao.findById(1L)).andReturn(getMockEntities().get(0));
+
+    EasyMock.replay(amc, clusters, cluster, dao);
+    
+    AlertDefinitionResourceProvider provider = createProvider(amc);    
+    Set<Resource> results = provider.getResources(request, predicate);
+    
+    assertEquals(1, results.size());
+    
+    Resource r = results.iterator().next();
+    
+    Assert.assertEquals("my_def", r.getPropertyValue(AlertDefinitionResourceProvider.ALERT_DEF_NAME));
+    Assert.assertEquals("metric", r.getPropertyValue(AlertDefinitionResourceProvider.ALERT_DEF_SOURCE_TYPE));
+    Assert.assertNotNull(r.getPropertyValue("AlertDefinition/metric"));
+    Assert.assertEquals(MetricAlert.class, r.getPropertyValue("AlertDefinition/metric").getClass());
+  }
+  
+  private AlertDefinitionResourceProvider createProvider(AmbariManagementController amc) {
+    return new AlertDefinitionResourceProvider(
+        PropertyHelper.getPropertyIds(Resource.Type.AlertDefinition),
+        PropertyHelper.getKeyPropertyIds(Resource.Type.AlertDefinition),
+        amc);
+  }
+  
+  private List<AlertDefinitionEntity> getMockEntities() {
+    AlertDefinitionEntity entity = new AlertDefinitionEntity();
+    entity.setClusterId(Long.valueOf(1L));
+    entity.setComponentName(null);
+    entity.setDefinitionId(Long.valueOf(1L));
+    entity.setDefinitionName("my_def");
+    entity.setEnabled(true);
+    entity.setHash("tmphash");
+    entity.setScheduleInterval(Long.valueOf(2L));
+    entity.setServiceName(null);
+    entity.setSourceType("metric");
+    entity.setSource("{'jmx': 'beanName/attributeName', 'host': '{{aa:123445}}'}");
+    
+    return Arrays.asList(entity);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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 b34a7dd..ca2d24e 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
@@ -81,7 +81,9 @@ public class AlertDefinitionDAOTest {
   public void testFindByName() {
     AlertDefinitionEntity entity = new AlertDefinitionEntity();
     TypedQuery<AlertDefinitionEntity> query = createStrictMock(TypedQuery.class);
-    
+
+    expect(query.setParameter("clusterId", 12345L)).andReturn(query);
+
     expect(query.setParameter("definitionName", "alert-definition-1")).andReturn(
         query);
 
@@ -93,7 +95,7 @@ public class AlertDefinitionDAOTest {
 
     replay(query, entityManager);
 
-    AlertDefinitionEntity result = dao.findByName("alert-definition-1");
+    AlertDefinitionEntity result = dao.findByName(12345L, "alert-definition-1");
 
     assertSame(result, entity);
     verify(entityManagerProvider, entityManager);

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/test/resources/stacks/HDP/2.0.5/services/HDFS/alerts.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/resources/stacks/HDP/2.0.5/services/HDFS/alerts.json b/ambari-server/src/test/resources/stacks/HDP/2.0.5/services/HDFS/alerts.json
new file mode 100644
index 0000000..7988d8b
--- /dev/null
+++ b/ambari-server/src/test/resources/stacks/HDP/2.0.5/services/HDFS/alerts.json
@@ -0,0 +1,52 @@
+{
+  "service": [
+  ],
+  "SECONDARY_NAMENODE": [
+    {
+      "name": "secondary_namenode_process",
+      "label": "Secondary NameNode process",
+      "interval": 1,
+      "scope": "service",
+      "source": "port",
+      "port": {
+        "config": "{{hdfs-site/dfs.namenode.secondary.http-address}}:50071",
+        "default": 50071
+      }
+    }
+  ],
+  "NAMENODE": [
+    {
+      "name": "namenode_cpu",
+      "label": "NameNode host CPU Utilization",
+      "scope": "host",
+      "source": "metric",
+      "metric": {
+        "jmx": "java.lang:type=OperatingSystem/SystemCpuLoad",
+        "host": "{{hdfs-site/dfs.namenode.secondary.http-address}}"
+      }
+    },
+    {
+      "name": "namenode_process",
+      "label": "NameNode process",
+      "interval": 1,
+      "scope": "host",
+      "source": "port",
+      "port": {
+        "uri": "{{hdfs-site/dfs.namenode.http-address}}:50070"
+       }
+    },
+    {
+      "name": "hdfs_last_checkpoint",
+      "label": "Last Checkpoint Time",
+      "interval": 1,
+      "scope": "service",
+      "source": "script",
+      "enabled": false,
+      "script": {
+        "path": "scripts/alerts/last_checkpoint.py"
+      }
+    }
+  ],
+  "DATANODE": [
+  ]
+}


[2/2] git commit: AMBARI-6528. Add AlertDefinition endpoint and resource provider (ncole)

Posted by nc...@apache.org.
AMBARI-6528. Add AlertDefinition endpoint and resource provider (ncole)


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

Branch: refs/heads/trunk
Commit: 39a92eb492833ace0b997b2cc4c9523c61832cc0
Parents: 7bdb1e4
Author: Nate Cole <nc...@hortonworks.com>
Authored: Thu Jul 17 15:18:05 2014 -0400
Committer: Nate Cole <nc...@hortonworks.com>
Committed: Fri Jul 18 07:47:48 2014 -0400

----------------------------------------------------------------------
 .../resources/AlertDefResourceDefinition.java   |  44 ++++
 .../resources/ClusterResourceDefinition.java    |   1 +
 .../resources/ResourceInstanceFactoryImpl.java  |   4 +
 .../api/services/AlertDefinitionService.java    |  93 ++++++++
 .../server/api/services/AmbariMetaInfo.java     |  43 ++++
 .../server/api/services/ClusterService.java     |   9 +
 .../server/api/util/StackExtensionHelper.java   |  12 +-
 .../ambari/server/controller/AmbariServer.java  |   3 +
 .../AbstractControllerResourceProvider.java     |   2 +
 .../AlertDefinitionResourceProvider.java        | 178 ++++++++++++++
 .../ambari/server/controller/spi/Resource.java  |   6 +-
 .../server/orm/dao/AlertDefinitionDAO.java      |  27 ++-
 .../ambari/server/orm/dao/AlertDispatchDAO.java | 230 ++++++++++++++++++-
 .../apache/ambari/server/orm/dao/AlertsDAO.java | 138 +++++++++++
 .../server/orm/entities/AlertCurrentEntity.java |  27 +++
 .../orm/entities/AlertDefinitionEntity.java     |  78 ++++++-
 .../server/orm/entities/AlertGroupEntity.java   |  46 +++-
 .../server/orm/entities/AlertHistoryEntity.java |  36 ++-
 .../server/orm/entities/AlertNoticeEntity.java  |  29 +++
 .../server/orm/entities/AlertTargetEntity.java  |  38 ++-
 .../apache/ambari/server/state/ServiceInfo.java |  18 +-
 .../server/state/alert/AlertDefinition.java     | 117 ++++++++++
 .../ambari/server/state/alert/MetricAlert.java  |  57 +++++
 .../apache/ambari/server/state/alert/Scope.java |  33 +++
 .../ambari/server/state/alert/SourceType.java   |  40 ++++
 .../resources/Ambari-DDL-Postgres-CREATE.sql    |   1 +
 .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql     |   1 +
 .../src/main/resources/key_properties.json      |   4 +
 .../src/main/resources/properties.json          |  11 +
 .../stacks/HDP/2.0.6/services/HDFS/alerts.json  |  59 +++++
 .../ClusterResourceDefinitionTest.java          |   3 +-
 .../server/api/services/AmbariMetaInfoTest.java |  22 ++
 .../AlertDefinitionResourceProviderTest.java    | 162 +++++++++++++
 .../server/orm/dao/AlertDefinitionDAOTest.java  |   6 +-
 .../stacks/HDP/2.0.5/services/HDFS/alerts.json  |  52 +++++
 35 files changed, 1594 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertDefResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertDefResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertDefResourceDefinition.java
new file mode 100644
index 0000000..1a63097
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertDefResourceDefinition.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.api.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Resource Definition for AlertDefinition types.
+ * @author ncole
+ *
+ */
+public class AlertDefResourceDefinition extends BaseResourceDefinition {
+
+  public AlertDefResourceDefinition() {
+    super(Resource.Type.AlertDefinition);
+  }
+  
+  @Override
+  public String getPluralName() {
+    // TODO Auto-generated method stub
+    return "alert_definitions";
+  }
+  
+  @Override
+  public String getSingularName() {
+    return "alert_definition";
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
index 43578c6..644e8d2 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java
@@ -65,6 +65,7 @@ public class ClusterResourceDefinition extends BaseResourceDefinition {
     setChildren.add(new SubResourceDefinition(Resource.Type.Request));
     setChildren.add(new SubResourceDefinition(Resource.Type.Workflow));
     setChildren.add(new SubResourceDefinition(Resource.Type.ConfigGroup));
+    setChildren.add(new SubResourceDefinition(Resource.Type.AlertDefinition));
 
     return setChildren;
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index 2a87c4f..4532919 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -233,6 +233,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
       case Permission:
         resourceDefinition = new PermissionResourceDefinition();
         break;
+        
+      case AlertDefinition:
+        resourceDefinition = new AlertDefResourceDefinition();
+        break;
 
       default:
         throw new IllegalArgumentException("Unsupported resource type: " + type);

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertDefinitionService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertDefinitionService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertDefinitionService.java
new file mode 100644
index 0000000..ee3d29a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/AlertDefinitionService.java
@@ -0,0 +1,93 @@
+/**
+ * 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.api.services;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Endpoint for alert definitions.
+ */
+public class AlertDefinitionService extends BaseService {
+
+  private String m_clusterName = null;
+  
+  AlertDefinitionService(String clusterName) {
+    m_clusterName = clusterName;
+  }
+  
+  @GET
+  @Produces("text/plain")
+  public Response getDefinitions(String body,
+      @Context HttpHeaders headers,
+      @Context UriInfo ui) {
+    return handleRequest(headers, body, ui, Request.Type.GET,
+      createResourceInstance(m_clusterName, null));
+  }
+  
+  @POST
+  @Produces("text/plain")
+  public Response createDefinition(String body,
+      @Context HttpHeaders headers,
+      @Context UriInfo ui) {
+    return handleRequest(headers, body, ui, Request.Type.POST,
+      createResourceInstance(m_clusterName, null));
+  }
+  
+  
+  @GET
+  @Path("{alertDefinitionId}")
+  @Produces("text/plain")
+  public Response getDefinitions(String body,
+      @Context HttpHeaders headers,
+      @Context UriInfo ui,
+      @PathParam("alertDefinitionId") Long id) {
+    return handleRequest(headers, body, ui, Request.Type.GET,
+      createResourceInstance(m_clusterName, id));
+  }
+  
+  
+  /**
+   * Create a request schedule resource instance
+   * @param clusterName
+   * @param requestScheduleId
+   * @return
+   */
+  private ResourceInstance createResourceInstance(String clusterName,
+      Long definitionId) {
+    Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+    mapIds.put(Resource.Type.Cluster, clusterName);
+    mapIds.put(Resource.Type.AlertDefinition, null == definitionId ? null : definitionId.toString());
+
+    return createResource(Resource.Type.AlertDefinition, mapIds);
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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 9bbebf5..c8ccf9a 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
@@ -31,6 +31,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Scanner;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -58,6 +59,7 @@ import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.Stack;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.StackInfo;
+import org.apache.ambari.server.state.alert.AlertDefinition;
 import org.apache.ambari.server.state.stack.LatestRepoCallable;
 import org.apache.ambari.server.state.stack.MetricDefinition;
 import org.apache.ambari.server.state.stack.RepositoryXml;
@@ -86,6 +88,7 @@ public class AmbariMetaInfo {
   public static final String SERVICE_CONFIG_FILE_NAME_POSTFIX = ".xml";
   public static final String RCO_FILE_NAME = "role_command_order.json";
   public static final String SERVICE_METRIC_FILE_NAME = "metrics.json";
+  public static final String SERVICE_ALERT_FILE_NAME = "alerts.json";
   /**
    * This string is used in placeholder in places that are common for
    * all operating systems or in situations where os type is not important.
@@ -1049,5 +1052,45 @@ public class AmbariMetaInfo {
     }
     return requiredProperties;
   }
+  
+  public Set<AlertDefinition> getAlertDefinitions(String stackName, String stackVersion,
+      String serviceName) throws AmbariException {
+    
+    ServiceInfo svc = getService(stackName, stackVersion, serviceName);
+
+    if (null == svc.getAlertsFile() || !svc.getAlertsFile().exists()) {
+      LOG.debug("Alerts file for " + stackName + "/" + stackVersion + "/" + serviceName + " not found.");
+      return null;
+    }
+    
+    
+    Map<String, List<AlertDefinition>> map = null;
+    
+    Type type = new TypeToken<Map<String, List<AlertDefinition>>>(){}.getType();
+    
+    Gson gson = new Gson();
+
+    try {
+      map = gson.fromJson(new FileReader(svc.getAlertsFile()), type);
+
+    } catch (Exception e) {
+      LOG.error ("Could not read the alert definition file", e);
+      throw new AmbariException("Could not read alert definition file", e);
+    }
+
+    Set<AlertDefinition> defs = new HashSet<AlertDefinition>();
+    
+    for (Entry<String, List<AlertDefinition>> entry : map.entrySet()) {
+      for (AlertDefinition ad : entry.getValue()) {
+        ad.setServiceName(serviceName);
+        if (!entry.getKey().equals("service")) {
+          ad.setComponentName(entry.getKey());
+        }
+      }
+      defs.addAll(entry.getValue());
+    }
+    
+    return defs;
+  }
 
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
index 29ca8a0..b7da169 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java
@@ -207,6 +207,15 @@ public class ClusterService extends BaseService {
                              (@PathParam ("clusterName") String clusterName) {
     return new RequestScheduleService(clusterName);
   }
+  
+  /**
+   * Gets the alert definition service
+   */
+  @Path("{clusterName}/alert_definitions")
+  public AlertDefinitionService getAlertDefinitionService(
+      @PathParam("clusterName") String clusterName) {
+    return new AlertDefinitionService(clusterName);
+  }
 
   /**
    * Create a cluster resource instance.

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
index 15c382b..8b41a1b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/util/StackExtensionHelper.java
@@ -185,6 +185,10 @@ public class StackExtensionHelper {
     // metrics
     if (null == childService.getMetricsFile() && null != parentService.getMetricsFile())
       mergedServiceInfo.setMetricsFile(parentService.getMetricsFile());
+    
+    // alerts
+    if (null == childService.getAlertsFile() && null != parentService.getAlertsFile())
+      mergedServiceInfo.setAlertsFile(parentService.getAlertsFile());    
 
     populateComponents(mergedServiceInfo, parentService, childService);
 
@@ -407,6 +411,9 @@ public class StackExtensionHelper {
           // get metrics file, if it exists
           File metricsJson = new File(serviceFolder.getAbsolutePath()
             + File.separator + AmbariMetaInfo.SERVICE_METRIC_FILE_NAME);
+          
+          File alertsJson = new File(serviceFolder.getAbsolutePath() +
+              File.separator + AmbariMetaInfo.SERVICE_ALERT_FILE_NAME);
 
           //Reading v2 service metainfo (may contain multiple services)
           // Get services from metadata
@@ -426,7 +433,10 @@ public class StackExtensionHelper {
             // process metrics.json
             if (metricsJson.exists())
               serviceInfo.setMetricsFile(metricsJson);
-
+            
+            if (alertsJson.exists())
+              serviceInfo.setAlertsFile(alertsJson);
+            
             // Get all properties from all "configs/*-site.xml" files
             setPropertiesFromConfigs(serviceFolder, serviceInfo);
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index d71cb8c..2011367 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -44,6 +44,7 @@ import org.apache.ambari.server.bootstrap.BootStrapImpl;
 import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.internal.AbstractControllerResourceProvider;
+import org.apache.ambari.server.controller.internal.AlertDefinitionResourceProvider;
 import org.apache.ambari.server.controller.internal.BlueprintResourceProvider;
 import org.apache.ambari.server.controller.internal.ClusterResourceProvider;
 import org.apache.ambari.server.controller.internal.StackDefinedPropertyProvider;
@@ -51,6 +52,7 @@ import org.apache.ambari.server.controller.internal.StackDependencyResourceProvi
 import org.apache.ambari.server.controller.nagios.NagiosPropertyProvider;
 import org.apache.ambari.server.orm.GuiceJpaInitializer;
 import org.apache.ambari.server.orm.PersistenceType;
+import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.BlueprintDAO;
 import org.apache.ambari.server.orm.dao.MetainfoDAO;
 import org.apache.ambari.server.orm.dao.ViewDAO;
@@ -527,6 +529,7 @@ public class AmbariServer {
     StackDependencyResourceProvider.init(ambariMetaInfo);
     ClusterResourceProvider.init(injector.getInstance(BlueprintDAO.class), ambariMetaInfo);
     ViewRegistry.init(injector.getInstance(ViewDAO.class), injector.getInstance(ViewInstanceDAO.class));
+    AlertDefinitionResourceProvider.init(injector.getInstance(AlertDefinitionDAO.class));
   }
   
   /**

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index f68f21c..5ba926c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -144,6 +144,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractResourc
         return new HostComponentProcessResourceProvider(propertyIds, keyPropertyIds, managementController);
       case Blueprint:
         return new BlueprintResourceProvider(propertyIds, keyPropertyIds, managementController);
+      case AlertDefinition:
+        return new AlertDefinitionResourceProvider(propertyIds, keyPropertyIds, managementController);
       default:
         throw new IllegalArgumentException("Unknown type " + type);
     }

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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
new file mode 100644
index 0000000..c83615a
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertDefinitionResourceProvider.java
@@ -0,0 +1,178 @@
+/**
+ * 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.controller.internal;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
+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.alert.MetricAlert;
+
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+
+/**
+ * ResourceProvider for Alert Definitions
+ */
+public class AlertDefinitionResourceProvider extends AbstractControllerResourceProvider {
+
+  protected static final String ALERT_DEF_CLUSTER_NAME = "AlertDefinition/cluster_name";
+  protected static final String ALERT_DEF_ID = "AlertDefinition/id";
+  protected static final String ALERT_DEF_NAME = "AlertDefinition/name";
+  protected static final String ALERT_DEF_INTERVAL = "AlertDefinition/interval";
+  protected static final String ALERT_DEF_SOURCE_TYPE = "AlertDefinition/source";
+  protected static final String ALERT_DEF_SERVICE_NAME = "AlertDefinition/service_name";
+  protected static final String ALERT_DEF_COMPONENT_NAME = "AlertDefinition/component_name";
+  protected static final String ALERT_DEF_ENABLED = "AlertDefinition/enabled";
+  protected static final String ALERT_DEF_SCOPE = "AlertDefinition/scope";
+  
+  private static Set<String> pkPropertyIds = new HashSet<String>(
+      Arrays.asList(ALERT_DEF_ID, ALERT_DEF_NAME));
+  private static AlertDefinitionDAO alertDefinitionDAO = null;
+  
+  /**
+   * @param instance
+   */
+  @Inject
+  public static void init(AlertDefinitionDAO instance) {
+    alertDefinitionDAO = instance;
+  }
+  
+  AlertDefinitionResourceProvider(Set<String> propertyIds,
+      Map<Resource.Type, String> keyPropertyIds,
+      AmbariManagementController managementController) {
+    super(propertyIds, keyPropertyIds, managementController);
+  }
+  
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return pkPropertyIds;
+  }
+
+  @Override
+  public RequestStatus createResources(Request request) throws SystemException,
+      UnsupportedPropertyException, ResourceAlreadyExistsException,
+      NoSuchParentResourceException {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public Set<Resource> getResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    
+    Set<String> requestPropertyIds = getRequestPropertyIds(request, predicate);
+    
+    Set<Resource> results = new HashSet<Resource>();
+    
+    for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
+      String clusterName = (String) propertyMap.get(ALERT_DEF_CLUSTER_NAME);
+      
+      if (null == clusterName || clusterName.isEmpty())
+        throw new IllegalArgumentException("Invalid argument, cluster name is required");
+      
+      String id = (String) propertyMap.get(ALERT_DEF_ID);
+      if (null != id) {
+        AlertDefinitionEntity entity = alertDefinitionDAO.findById(Long.parseLong(id));
+        if (null != entity) {
+          results.add(toResource(false, clusterName, entity, requestPropertyIds));
+        }
+      } else {
+        
+        Cluster cluster = null;
+        try {
+          cluster = getManagementController().getClusters().getCluster(clusterName);
+        } catch (AmbariException e) {
+          throw new NoSuchResourceException("Parent Cluster resource doesn't exist", e);
+        }
+        
+        List<AlertDefinitionEntity> entities = alertDefinitionDAO.findAll(
+            cluster.getClusterId());
+
+        for (AlertDefinitionEntity entity : entities) {
+          results.add(toResource(true, clusterName, entity, requestPropertyIds));
+        }
+      }
+    }
+    
+    return results;
+  }
+
+  @Override
+  public RequestStatus updateResources(Request request, Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    throw new UnsupportedOperationException("Not currently supported.");
+  }
+
+  @Override
+  public RequestStatus deleteResources(Predicate predicate)
+      throws SystemException, UnsupportedPropertyException,
+      NoSuchResourceException, NoSuchParentResourceException {
+    throw new UnsupportedOperationException("Not currently supported.");
+  }
+
+  
+  private Resource toResource(boolean isCollection, String clusterName,
+      AlertDefinitionEntity entity, Set<String> requestedIds) {
+    Resource resource = new ResourceImpl(Resource.Type.AlertDefinition);
+    
+    setResourceProperty(resource, ALERT_DEF_CLUSTER_NAME, clusterName, requestedIds);
+    setResourceProperty(resource, ALERT_DEF_ID, entity.getDefinitionId(), requestedIds);
+    setResourceProperty(resource, ALERT_DEF_NAME, entity.getDefinitionName(), requestedIds);
+    setResourceProperty(resource, ALERT_DEF_INTERVAL, entity.getScheduleInterval(), requestedIds);
+    setResourceProperty(resource, ALERT_DEF_SOURCE_TYPE, entity.getSourceType(), requestedIds);
+    setResourceProperty(resource, ALERT_DEF_SERVICE_NAME, entity.getServiceName(), requestedIds);
+    setResourceProperty(resource, ALERT_DEF_COMPONENT_NAME, entity.getComponentName(), requestedIds);
+    setResourceProperty(resource, ALERT_DEF_ENABLED, Boolean.valueOf(entity.getEnabled()), requestedIds);
+    setResourceProperty(resource, ALERT_DEF_SCOPE, entity.getScope(), requestedIds);
+    
+    if (!isCollection && null != resource.getPropertyValue(ALERT_DEF_SOURCE_TYPE)) {
+      Gson gson = new Gson();
+      
+      if (entity.getSourceType().equals("metric")) {
+        try {
+          MetricAlert ma = gson.fromJson(entity.getSource(), MetricAlert.class);
+          resource.setProperty("AlertDefinition/metric", ma);
+        } catch (Exception e) {
+          LOG.error("Could not coerce alert source into a type");
+        }
+      }
+    }
+    
+    return resource;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index b70f335..a61ab37 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -22,6 +22,8 @@ package org.apache.ambari.server.controller.spi;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
+import org.apache.ambari.server.controller.spi.Resource.Type;
+
 /**
  * The resource object represents a requested resource.  The resource
  * contains a collection of values for the requested properties.
@@ -110,7 +112,8 @@ public interface Resource {
     ViewInstance,
     Blueprint,
     HostComponentProcess,
-    Permission;
+    Permission,
+    AlertDefinition;
 
     /**
      * Get the {@link Type} that corresponds to this InternalType.
@@ -182,6 +185,7 @@ public interface Resource {
     public static final Type Blueprint = InternalType.Blueprint.getType();
     public static final Type HostComponentProcess = InternalType.HostComponentProcess.getType();
     public static final Type Permission = InternalType.Permission.getType();
+    public static final Type AlertDefinition = InternalType.AlertDefinition.getType();
 
     /**
      * The type name.

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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 6f084df..9163d6e 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
@@ -62,17 +62,21 @@ public class AlertDefinitionDAO {
   }
 
   /**
-   * Gets an alert definition with the specified name.
+   * Gets an alert definition with the specified name. Alert definition names
+   * are unique within a cluster.
    * 
+   * @param clusterId
+   *          the ID of the cluster.
    * @param definitionName
    *          the name of the definition (not {@code null}).
    * @return the alert definition or {@code null} if none exists.
    */
   @RequiresSession
-  public AlertDefinitionEntity findByName(String definitionName) {
+  public AlertDefinitionEntity findByName(long clusterId, String definitionName) {
     TypedQuery<AlertDefinitionEntity> query = entityManagerProvider.get().createNamedQuery(
         "AlertDefinitionEntity.findByName", AlertDefinitionEntity.class);
 
+    query.setParameter("clusterId", clusterId);
     query.setParameter("definitionName", definitionName);
 
     return daoUtils.selectSingle(query);
@@ -81,7 +85,8 @@ public class AlertDefinitionDAO {
   /**
    * Gets all alert definitions stored in the database.
    * 
-   * @return all alert definitions or {@code null} if none exist.
+   * @return all alert definitions or an empty list if none exist (never
+   *         {@code null}).
    */
   @RequiresSession
   public List<AlertDefinitionEntity> findAll() {
@@ -92,6 +97,22 @@ public class AlertDefinitionDAO {
   }
 
   /**
+   * Gets all alert definitions stored in the database.
+   * 
+   * @return all alert definitions or empty list if none exist (never
+   *         {@code null}).
+   */
+  @RequiresSession
+  public List<AlertDefinitionEntity> findAll(long clusterId) {
+    TypedQuery<AlertDefinitionEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertDefinitionEntity.findAllInCluster", AlertDefinitionEntity.class);
+
+    query.setParameter("clusterId", clusterId);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
    * Persists a new alert definition.
    * 
    * @param alertDefinition

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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 c5a9186..0fa803b 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,14 +17,23 @@
  */
 package org.apache.ambari.server.orm.dao;
 
+import java.util.List;
+
 import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.AlertGroupEntity;
+import org.apache.ambari.server.orm.entities.AlertTargetEntity;
 
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
 
 /**
- * 
+ * The {@link AlertDispatchDAO} class manages the {@link AlertTargetEntity},
+ * {@link AlertGroupEntity}, and the associations between them.
  */
 @Singleton
 public class AlertDispatchDAO {
@@ -33,4 +42,223 @@ public class AlertDispatchDAO {
    */
   @Inject
   Provider<EntityManager> entityManagerProvider;
+
+  /**
+   * DAO utilities for dealing mostly with {@link TypedQuery} results.
+   */
+  @Inject
+  DaoUtils daoUtils;
+
+  /**
+   * Gets an alert group with the specified ID.
+   * 
+   * @param groupId
+   *          the ID of the group to retrieve.
+   * @return the group or {@code null} if none exists.
+   */
+  @RequiresSession
+  public AlertGroupEntity findGroupById(long groupId) {
+    return entityManagerProvider.get().find(AlertGroupEntity.class, groupId);
+  }
+
+  /**
+   * Gets an alert target with the specified ID.
+   * 
+   * @param targetId
+   *          the ID of the target to retrieve.
+   * @return the target or {@code null} if none exists.
+   */
+  @RequiresSession
+  public AlertTargetEntity findTargetById(long targetId) {
+    return entityManagerProvider.get().find(AlertTargetEntity.class, targetId);
+  }
+
+  /**
+   * Gets an alert group with the specified name across all clusters. Alert
+   * group names are unique within a cluster.
+   * 
+   * @param groupName
+   *          the name of the group (not {@code null}).
+   * @return the alert group or {@code null} if none exists.
+   */
+  @RequiresSession
+  public AlertGroupEntity findGroupByName(String groupName) {
+    TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertGroup.findByName", AlertGroupEntity.class);
+
+    query.setParameter("groupName", groupName);
+
+    return daoUtils.selectSingle(query);
+  }
+
+  /**
+   * Gets an alert group with the specified name for the given cluster. Alert
+   * group names are unique within a cluster.
+   * 
+   * @param clusterId
+   *          the ID of the cluster.
+   * @param groupName
+   *          the name of the group (not {@code null}).
+   * @return the alert group or {@code null} if none exists.
+   */
+  @RequiresSession
+  public AlertGroupEntity findGroupByName(long clusterId, String groupName) {
+    TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertGroup.findByNameInCluster", AlertGroupEntity.class);
+
+    query.setParameter("clusterId", clusterId);
+    query.setParameter("groupName", groupName);
+
+    return daoUtils.selectSingle(query);
+  }
+
+  /**
+   * Gets an alert target with the specified name. Alert target names are unique
+   * across all clusters.
+   * 
+   * @param targetName
+   *          the name of the target (not {@code null}).
+   * @return the alert target or {@code null} if none exists.
+   */
+  @RequiresSession
+  public AlertTargetEntity findTargetByName(String targetName) {
+    TypedQuery<AlertTargetEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertGroup.findByName", AlertTargetEntity.class);
+
+    query.setParameter("targetName", targetName);
+
+    return daoUtils.selectSingle(query);
+  }
+
+  /**
+   * Gets all alert groups stored in the database across all clusters.
+   * 
+   * @return all alert groups or empty list if none exist (never {@code null}).
+   */
+  @RequiresSession
+  public List<AlertGroupEntity> findAllGroups() {
+    TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertGroupEntity.findAll", AlertGroupEntity.class);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Gets all alert groups stored in the database for the specified cluster.
+   * 
+   * @return all alert groups in the specified cluster or empty list if none
+   *         exist (never {@code null}).
+   */
+  @RequiresSession
+  public List<AlertGroupEntity> findAllGroups(long clusterId) {
+    TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertGroupEntity.findAllInCluster", AlertGroupEntity.class);
+
+    query.setParameter("clusterId", clusterId);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Gets all alert targets stored in the database.
+   * 
+   * @return all alert targets or empty list if none exist (never {@code null}).
+   */
+  @RequiresSession
+  public List<AlertTargetEntity> findAllTargets() {
+    TypedQuery<AlertTargetEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertTargetEntity.findAll", AlertTargetEntity.class);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Persists a new alert group.
+   * 
+   * @param alertGroup
+   *          the group to persist (not {@code null}).
+   */
+  @Transactional
+  public void create(AlertGroupEntity alertGroup) {
+    entityManagerProvider.get().persist(alertGroup);
+  }
+
+  /**
+   * Refresh the state of the alert group from the database.
+   * 
+   * @param alertGroup
+   *          the group to refresh (not {@code null}).
+   */
+  @Transactional
+  public void refresh(AlertGroupEntity alertGroup) {
+    entityManagerProvider.get().refresh(alertGroup);
+  }
+
+  /**
+   * Merge the speicified alert group with the existing group in the database.
+   * 
+   * @param alertGroup
+   *          the group to merge (not {@code null}).
+   * @return the updated group with merged content (never {@code null}).
+   */
+  @Transactional
+  public AlertGroupEntity merge(AlertGroupEntity alertGroup) {
+    return entityManagerProvider.get().merge(alertGroup);
+  }
+
+  /**
+   * Removes the specified alert group from the database.
+   * 
+   * @param alertGroup
+   *          the group to remove.
+   */
+  @Transactional
+  public void remove(AlertGroupEntity alertGroup) {
+    entityManagerProvider.get().remove(merge(alertGroup));
+  }
+
+  /**
+   * Persists a new alert target.
+   * 
+   * @param alertTarget
+   *          the target to persist (not {@code null}).
+   */
+  @Transactional
+  public void create(AlertTargetEntity alertTarget) {
+    entityManagerProvider.get().persist(alertTarget);
+  }
+
+  /**
+   * Refresh the state of the alert target from the database.
+   * 
+   * @param alertTarget
+   *          the target to refresh (not {@code null}).
+   */
+  @Transactional
+  public void refresh(AlertTargetEntity alertTarget) {
+    entityManagerProvider.get().refresh(alertTarget);
+  }
+
+  /**
+   * Merge the speicified alert target with the existing target in the database.
+   * 
+   * @param alertTarget
+   *          the target to merge (not {@code null}).
+   * @return the updated target with merged content (never {@code null}).
+   */
+  @Transactional
+  public AlertTargetEntity merge(AlertTargetEntity alertTarget) {
+    return entityManagerProvider.get().merge(alertTarget);
+  }
+
+  /**
+   * Removes the specified alert target from the database.
+   * 
+   * @param alertTarget
+   *          the target to remove.
+   */
+  @Transactional
+  public void remove(AlertTargetEntity alertTarget) {
+    entityManagerProvider.get().remove(merge(alertTarget));
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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
new file mode 100644
index 0000000..9f36860
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java
@@ -0,0 +1,138 @@
+/**
+ * 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.orm.dao;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+
+import org.apache.ambari.server.orm.RequiresSession;
+import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
+import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.google.inject.persist.Transactional;
+
+/**
+ * The {@link AlertsDAO} class manages the {@link AlertHistoryEntity} and
+ * {@link AlertCurrentEntity} instances.Each {@link AlertHistoryEntity} is known
+ * as an "alert" that has been triggered and received.
+ */
+@Singleton
+public class AlertsDAO {
+  /**
+   * JPA entity manager
+   */
+  @Inject
+  Provider<EntityManager> entityManagerProvider;
+
+  /**
+   * DAO utilities for dealing mostly with {@link TypedQuery} results.
+   */
+  @Inject
+  DaoUtils daoUtils;
+
+  /**
+   * Gets an alert with the specified ID.
+   * 
+   * @param alertId
+   *          the ID of the alert to retrieve.
+   * @return the alert or {@code null} if none exists.
+   */
+  @RequiresSession
+  public AlertHistoryEntity findById(long alertId) {
+    return entityManagerProvider.get().find(AlertHistoryEntity.class, alertId);
+  }
+
+  /**
+   * Gets all alerts stored in the database across all clusters.
+   * 
+   * @return all alerts or empty list if none exist (never {@code null}).
+   */
+  @RequiresSession
+  public List<AlertHistoryEntity> findAll() {
+    TypedQuery<AlertHistoryEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertHistoryEntity.findAll", AlertHistoryEntity.class);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Gets all alerts stored in the database for the given cluster.
+   * 
+   * @return all alerts in the specified cluster or empty list if none exist
+   *         (never {@code null}).
+   */
+  @RequiresSession
+  public List<AlertHistoryEntity> findAll(long clusterId) {
+    TypedQuery<AlertHistoryEntity> query = entityManagerProvider.get().createNamedQuery(
+        "AlertHistoryEntity.findAllInCluster", AlertHistoryEntity.class);
+
+    query.setParameter("clusterId", clusterId);
+
+    return daoUtils.selectList(query);
+  }
+
+  /**
+   * Persists a new alert.
+   * 
+   * @param alert
+   *          the alert to persist (not {@code null}).
+   */
+  @Transactional
+  public void create(AlertHistoryEntity alert) {
+    entityManagerProvider.get().persist(alert);
+  }
+
+  /**
+   * Refresh the state of the alert from the database.
+   * 
+   * @param alert
+   *          the alert to refresh (not {@code null}).
+   */
+  @Transactional
+  public void refresh(AlertHistoryEntity alert) {
+    entityManagerProvider.get().refresh(alert);
+  }
+
+  /**
+   * Merge the speicified alert with the existing alert in the database.
+   * 
+   * @param alert
+   *          the alert to merge (not {@code null}).
+   * @return the updated alert with merged content (never {@code null}).
+   */
+  @Transactional
+  public AlertHistoryEntity merge(AlertHistoryEntity alert) {
+    return entityManagerProvider.get().merge(alert);
+  }
+
+  /**
+   * Removes the specified alert from the database.
+   * 
+   * @param alert
+   *          the alert to remove.
+   */
+  @Transactional
+  public void remove(AlertHistoryEntity alert) {
+    entityManagerProvider.get().remove(merge(alert));
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
index aa99a08..65c2d0f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertCurrentEntity.java
@@ -175,4 +175,31 @@ public class AlertCurrentEntity {
     this.alertHistory = alertHistory;
   }
 
+  /**
+   *
+   */
+  @Override
+  public boolean equals(Object object) {
+    if (this == object)
+      return true;
+
+    if (object == null || getClass() != object.getClass())
+      return false;
+
+    AlertCurrentEntity that = (AlertCurrentEntity) object;
+
+    if (alertId != null ? !alertId.equals(that.alertId) : that.alertId != null)
+      return false;
+
+    return true;
+  }
+
+  /**
+   *
+   */
+  @Override
+  public int hashCode() {
+    int result = null != alertId ? alertId.hashCode() : 0;
+    return result;
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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 98af71d..997fdfd 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
@@ -17,7 +17,7 @@
  */
 package org.apache.ambari.server.orm.entities;
 
-import java.util.List;
+import java.util.Set;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -40,7 +40,8 @@ import javax.persistence.UniqueConstraint;
     "cluster_id", "definition_name" }))
 @NamedQueries({
     @NamedQuery(name = "AlertDefinitionEntity.findAll", query = "SELECT alertDefinition FROM AlertDefinitionEntity alertDefinition"),
-    @NamedQuery(name = "AlertDefinitionEntity.findByName", query = "SELECT alertDefinition FROM AlertDefinitionEntity alertDefinition WHERE alertDefinition.definitionName = :definitionName"), })
+    @NamedQuery(name = "AlertDefinitionEntity.findAllInCluster", query = "SELECT alertDefinition FROM AlertDefinitionEntity alertDefinition WHERE alertDefinition.clusterId = :clusterId"),
+    @NamedQuery(name = "AlertDefinitionEntity.findByName", query = "SELECT alertDefinition FROM AlertDefinitionEntity alertDefinition WHERE alertDefinition.definitionName = :definitionName AND alertDefinition.clusterId = :clusterId"), })
 public class AlertDefinitionEntity {
 
   @Id
@@ -49,7 +50,7 @@ public class AlertDefinitionEntity {
   private Long definitionId;
 
   @Column(name = "alert_source", nullable = false, length = 2147483647)
-  private String alertSource;
+  private String source;
 
   @Column(name = "cluster_id", nullable = false)
   private Long clusterId;
@@ -59,6 +60,9 @@ public class AlertDefinitionEntity {
 
   @Column(name = "definition_name", nullable = false, length = 255)
   private String definitionName;
+  
+  @Column(name = "scope", length = 255)
+  private String scope;
 
   @Column(nullable = false)
   private Integer enabled = Integer.valueOf(1);
@@ -79,7 +83,7 @@ public class AlertDefinitionEntity {
    * Bi-directional many-to-many association to {@link AlertGroupEntity}
    */
   @ManyToMany(mappedBy = "alertDefinitions")
-  private List<AlertGroupEntity> alertGroups;
+  private Set<AlertGroupEntity> alertGroups;
 
   /**
    * Constructor.
@@ -113,8 +117,8 @@ public class AlertDefinitionEntity {
    * 
    * @return the alert source (never {@code null}).
    */
-  public String getAlertSource() {
-    return alertSource;
+  public String getSource() {
+    return source;
   }
 
   /**
@@ -124,8 +128,8 @@ public class AlertDefinitionEntity {
    * @param alertSource
    *          the alert source (not {@code null}).
    */
-  public void setAlertSource(String alertSource) {
-    this.alertSource = alertSource;
+  public void setSource(String alertSource) {
+    this.source = alertSource;
   }
 
   /**
@@ -173,6 +177,27 @@ public class AlertDefinitionEntity {
   }
 
   /**
+   * Gets the scope of the alert definition. The scope is defined as either
+   * being for a SERVICE or a HOST.
+   * 
+   * @return the scope, or {@code null} if not defined.
+   */
+  public String getScope() {
+    return scope;
+  }
+
+  /**
+   * Sets the scope of the alert definition. The scope is defined as either
+   * being for a SERVICE or a HOST.
+   * 
+   * @param scope
+   *          the scope to set, or {@code null} for none.
+   */
+  public void setScope(String scope) {
+    this.scope = scope;
+  }
+
+  /**
    * Gets the name of this alert definition. Alert definition names are unique
    * within a cluster.
    * 
@@ -201,8 +226,8 @@ public class AlertDefinitionEntity {
    * @return {@code true} if this alert definition is enabled, {@code false}
    *         otherwise.
    */
-  public Integer getEnabled() {
-    return enabled;
+  public boolean getEnabled() {
+    return enabled == 0 ? false : true;
   }
 
   /**
@@ -298,7 +323,7 @@ public class AlertDefinitionEntity {
    * 
    * @return the groups, or {@code null} if none.
    */
-  public List<AlertGroupEntity> getAlertGroups() {
+  public Set<AlertGroupEntity> getAlertGroups() {
     return alertGroups;
   }
 
@@ -308,7 +333,36 @@ public class AlertDefinitionEntity {
    * @param alertGroups
    *          the groups, or {@code null} for none.
    */
-  public void setAlertGroups(List<AlertGroupEntity> alertGroups) {
+  public void setAlertGroups(Set<AlertGroupEntity> alertGroups) {
     this.alertGroups = alertGroups;
   }
+
+  /**
+   *
+   */
+  @Override
+  public boolean equals(Object object) {
+    if (this == object)
+      return true;
+
+    if (object == null || getClass() != object.getClass())
+      return false;
+
+    AlertDefinitionEntity that = (AlertDefinitionEntity) object;
+
+    if (definitionId != null ? !definitionId.equals(that.definitionId)
+        : that.definitionId != null)
+      return false;
+
+    return true;
+  }
+
+  /**
+   *
+   */
+  @Override
+  public int hashCode() {
+    int result = null != definitionId ? definitionId.hashCode() : 0;
+    return result;
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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 6df6be2..12b1fff 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
@@ -17,7 +17,7 @@
  */
 package org.apache.ambari.server.orm.entities;
 
-import java.util.List;
+import java.util.Set;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -42,7 +42,9 @@ import javax.persistence.UniqueConstraint;
     "cluster_id", "group_name" }))
 @NamedQueries({
     @NamedQuery(name = "AlertGroupEntity.findAll", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup"),
-    @NamedQuery(name = "AlertGroupEntity.findByName", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.groupName = :groupName"), })
+    @NamedQuery(name = "AlertGroupEntity.findAllInCluster", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.clusterId = :clusterId"),
+    @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"), })
 public class AlertGroupEntity {
 
   @Id
@@ -64,13 +66,13 @@ public class AlertGroupEntity {
    */
   @ManyToMany
   @JoinTable(name = "alert_grouping", joinColumns = { @JoinColumn(name = "group_id", nullable = false) }, inverseJoinColumns = { @JoinColumn(name = "definition_id", nullable = false) })
-  private List<AlertDefinitionEntity> alertDefinitions;
+  private Set<AlertDefinitionEntity> alertDefinitions;
 
   /**
    * Bi-directional many-to-many association to {@link AlertTargetEntity}
    */
   @ManyToMany(mappedBy = "alertGroups")
-  private List<AlertTargetEntity> alertTargets;
+  private Set<AlertTargetEntity> alertTargets;
 
   /**
    * Constructor.
@@ -164,7 +166,7 @@ public class AlertGroupEntity {
    * 
    * @return the alert definitions or {@code null} if none.
    */
-  public List<AlertDefinitionEntity> getAlertDefinitions() {
+  public Set<AlertDefinitionEntity> getAlertDefinitions() {
     return alertDefinitions;
   }
 
@@ -174,7 +176,7 @@ public class AlertGroupEntity {
    * @param alertDefinitions
    *          the definitions, or {@code null} for none.
    */
-  public void setAlertDefinitions(List<AlertDefinitionEntity> alertDefinitions) {
+  public void setAlertDefinitions(Set<AlertDefinitionEntity> alertDefinitions) {
     this.alertDefinitions = alertDefinitions;
   }
 
@@ -184,7 +186,7 @@ public class AlertGroupEntity {
    * 
    * @return the targets, or {@code null} if there are none.
    */
-  public List<AlertTargetEntity> getAlertTargets() {
+  public Set<AlertTargetEntity> getAlertTargets() {
     return alertTargets;
   }
 
@@ -195,7 +197,35 @@ public class AlertGroupEntity {
    * @param alertTargets
    *          the targets, or {@code null} if there are none.
    */
-  public void setAlertTargets(List<AlertTargetEntity> alertTargets) {
+  public void setAlertTargets(Set<AlertTargetEntity> alertTargets) {
     this.alertTargets = alertTargets;
   }
+
+  /**
+   *
+   */
+  @Override
+  public boolean equals(Object object) {
+    if (this == object)
+      return true;
+
+    if (object == null || getClass() != object.getClass())
+      return false;
+
+    AlertGroupEntity that = (AlertGroupEntity) object;
+
+    if (groupId != null ? !groupId.equals(that.groupId) : that.groupId != null)
+      return false;
+
+    return true;
+  }
+
+  /**
+   *
+   */
+  @Override
+  public int hashCode() {
+    int result = null != groupId ? groupId.hashCode() : 0;
+    return result;
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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 c1e346a..2b01514 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
@@ -26,6 +26,7 @@ import javax.persistence.GenerationType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
@@ -41,7 +42,9 @@ import org.apache.ambari.server.state.AlertState;
  */
 @Entity
 @Table(name = "alert_history")
-@NamedQuery(name = "AlertHistoryEntity.findAll", query = "SELECT alertHistory FROM AlertHistoryEntity alertHistory")
+@NamedQueries({
+    @NamedQuery(name = "AlertHistoryEntity.findAll", query = "SELECT alertHistory FROM AlertHistoryEntity alertHistory"),
+    @NamedQuery(name = "AlertHistoryEntity.findAllInCluster", query = "SELECT alertHistory FROM AlertHistoryEntity alertHistory WHERE alertHistory.clusterId = :clusterId") })
 public class AlertHistoryEntity {
 
   @Id
@@ -80,7 +83,7 @@ public class AlertHistoryEntity {
   /**
    * Bi-directional one-to-one association to {@link AlertCurrentEntity}.
    */
-  @OneToOne(mappedBy = "alertHistory")
+  @OneToOne(mappedBy = "alertHistory", orphanRemoval = true)
   private AlertCurrentEntity alertCurrent;
 
   /**
@@ -341,4 +344,33 @@ public class AlertHistoryEntity {
   public void setAlertDefinition(AlertDefinitionEntity alertDefinition) {
     this.alertDefinition = alertDefinition;
   }
+
+  /**
+   *
+   */
+  @Override
+  public boolean equals(Object object) {
+    if (this == object)
+      return true;
+
+    if (object == null || getClass() != object.getClass())
+      return false;
+
+    AlertHistoryEntity that = (AlertHistoryEntity) object;
+
+    if (alertId != null ? !alertId.equals(that.alertId) : that.alertId != null)
+      return false;
+
+    return true;
+  }
+
+  /**
+   *
+   */
+  @Override
+  public int hashCode() {
+    int result = null != alertId ? alertId.hashCode() : 0;
+    return result;
+  }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java
index bc3958e..8f84b49 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertNoticeEntity.java
@@ -152,4 +152,33 @@ public class AlertNoticeEntity {
     this.alertTarget = alertTarget;
   }
 
+  /**
+   *
+   */
+  @Override
+  public boolean equals(Object object) {
+    if (this == object)
+      return true;
+
+    if (object == null || getClass() != object.getClass())
+      return false;
+
+    AlertNoticeEntity that = (AlertNoticeEntity) object;
+
+    if (notificationId != null ? !notificationId.equals(that.notificationId)
+        : that.notificationId != null)
+      return false;
+
+    return true;
+  }
+
+  /**
+   *
+   */
+  @Override
+  public int hashCode() {
+    int result = null != notificationId ? notificationId.hashCode() : 0;
+    return result;
+  }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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 595a3b8..32a2979 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
@@ -17,7 +17,7 @@
  */
 package org.apache.ambari.server.orm.entities;
 
-import java.util.List;
+import java.util.Set;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
@@ -64,7 +64,7 @@ public class AlertTargetEntity {
    */
   @ManyToMany
   @JoinTable(name = "alert_group_target", joinColumns = { @JoinColumn(name = "target_id", nullable = false) }, inverseJoinColumns = { @JoinColumn(name = "group_id", nullable = false) })
-  private List<AlertGroupEntity> alertGroups;
+  private Set<AlertGroupEntity> alertGroups;
 
   /**
    * Constructor.
@@ -163,7 +163,7 @@ public class AlertTargetEntity {
    * @return the groups that will send to this target when an alert in that
    *         group is received, or {@code null} for none.
    */
-  public List<AlertGroupEntity> getAlertGroups() {
+  public Set<AlertGroupEntity> getAlertGroups() {
     return alertGroups;
   }
 
@@ -174,7 +174,37 @@ public class AlertTargetEntity {
    *          the groups that will send to this target when an alert in that
    *          group is received, or {@code null} for none.
    */
-  public void setAlertGroups(List<AlertGroupEntity> alertGroups) {
+  public void setAlertGroups(Set<AlertGroupEntity> alertGroups) {
     this.alertGroups = alertGroups;
   }
+
+  /**
+   *
+   */
+  @Override
+  public boolean equals(Object object) {
+    if (this == object)
+      return true;
+
+    if (object == null || getClass() != object.getClass())
+      return false;
+
+    AlertTargetEntity that = (AlertTargetEntity) object;
+
+    if (targetId != null ? !targetId.equals(that.targetId)
+        : that.targetId != null)
+      return false;
+
+    return true;
+  }
+
+  /**
+   *
+   */
+  @Override
+  public int hashCode() {
+    int result = null != targetId ? targetId.hashCode() : 0;
+    return result;
+  }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
index 44bc369..2ac4a14 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
@@ -81,7 +81,9 @@ public class ServiceInfo {
   private File metricsFile = null;
   @XmlTransient
   private Map<String, Map<String, List<MetricDefinition>>> metrics = null;
-
+  
+  @XmlTransient
+  private File alertsFile = null;
 
   /**
    * Internal list of os-specific details (loaded from xml). Added at schema ver 2
@@ -405,4 +407,18 @@ public class ServiceInfo {
   public void setMonitoringService(Boolean monitoringService) {
     this.monitoringService = monitoringService;
   }
+
+  /**
+   * @param file the file containing the alert definitions
+   */
+  public void setAlertsFile(File file) {
+    alertsFile = file;
+  }
+  
+  /**
+   * @return the alerts file, or <code>null</code> if none exists
+   */
+  public File getAlertsFile() {
+    return alertsFile;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/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
new file mode 100644
index 0000000..f8df108
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/AlertDefinition.java
@@ -0,0 +1,117 @@
+/**
+® * 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.state.alert;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * @author ncole
+ *
+ */
+public class AlertDefinition {
+
+  private String serviceName = null;
+  private String componentName = null;
+  
+  private String name = null;
+  private String label = null;
+  private String scope = null;
+  private String source = null;
+  private int interval = 1;
+  private boolean enabled = true;
+  
+  @SerializedName("metric")
+  private MetricAlert metricAlert = null;
+  
+  public String getServiceName() {
+    return serviceName;
+  }
+  
+  public void setServiceName(String name) {
+    serviceName = name;
+  }
+  
+  public String getComponentName() {
+    return componentName;
+  }
+  
+  public void setComponentName(String name) {
+    componentName = name;
+  }
+  
+  /**
+   * @return the name
+   */
+  public String getName() {
+    return name;
+  }
+  
+  /**
+   * @return the label
+   */
+  public String getLabel() {
+    return label;
+  }
+  
+  /**
+   * @return the scope
+   */
+  public String getScope() {
+    return scope;
+  }
+  
+  /**
+   * @return the source
+   */
+  public String getSource() {
+    return source;
+  }
+  
+  /**
+  * @return the interval
+   */
+  public int getInterval() {
+    return interval;
+  }
+  
+  /**
+   * @return <code>true</code> if enabled
+   */
+  public boolean isEnabled() {
+    return enabled;
+  }
+  
+  @Override
+  public boolean equals(Object obj) {
+    if (null == obj || !obj.getClass().equals(AlertDefinition.class))
+      return false;
+    
+    return name.equals(((AlertDefinition) obj).name);
+  }
+  
+  @Override
+  public int hashCode() {
+    return name.hashCode();
+  }
+  
+  @Override
+  public String toString() {
+    return name;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricAlert.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricAlert.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricAlert.java
new file mode 100644
index 0000000..b565a3f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/MetricAlert.java
@@ -0,0 +1,57 @@
+/**
+ * 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.state.alert;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Alert when the source type is defined as {@link SourceType#METRIC}
+ */
+public class MetricAlert {
+  
+  private String host = null;
+  
+  @SerializedName("jmx")
+  private String jmxInfo = null;
+  
+  @SerializedName("ganglia")
+  private String gangliaInfo = null;
+  
+  /**
+   * @return the jmx info, if this metric is jmx-based
+   */
+  public String getJmxInfo() {
+    return jmxInfo;
+  }
+  
+  /**
+   * @return the ganglia info, if this metric is ganglia-based
+   */
+  public String getGangliaInfo() {
+    return gangliaInfo;
+  }
+  
+  /**
+   * @return the host info, which may include port information
+   */
+  public String getHost() {
+    return host;
+  }
+  
+  
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Scope.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Scope.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Scope.java
new file mode 100644
index 0000000..4b06b62
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/Scope.java
@@ -0,0 +1,33 @@
+/**
+ * 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.state.alert;
+
+/**
+ * Assigns a scope to an alert.
+ * 
+ */
+public enum Scope {
+  /**
+   * Definition is scoped to a host only
+   */
+  HOST,
+  /**
+   * Definition is scoped to a service only
+   */
+  SERVICE
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/java/org/apache/ambari/server/state/alert/SourceType.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/alert/SourceType.java b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/SourceType.java
new file mode 100644
index 0000000..8289d6f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/alert/SourceType.java
@@ -0,0 +1,40 @@
+/**
+ * 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.state.alert;
+
+/**
+ * Source type refers to how the alert is to be collected. 
+ */
+public enum SourceType {
+  /**
+   * Source is from metric data.
+   */
+  METRIC,
+  /**
+   * Source is generated using of a script
+   */
+  SCRIPT,
+  /**
+   * Source is a simple port check
+   */
+  PORT,
+  /**
+   * Source is an aggregate of a collection of other alert states
+   */
+  AGGREGATE
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
index 5a42153..09cb052 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql
@@ -150,6 +150,7 @@ CREATE TABLE alert_definition (
   definition_name VARCHAR(255) NOT NULL,
   service_name VARCHAR(255) NOT NULL,
   component_name VARCHAR(255),
+  scope VARCHAR(255),
   enabled SMALLINT DEFAULT 1 NOT NULL,
   schedule_interval BIGINT NOT NULL,
   source_type VARCHAR(255) NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
index deb70ab..f837e0a 100644
--- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
+++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql
@@ -207,6 +207,7 @@ CREATE TABLE ambari.alert_definition (
   definition_name VARCHAR(255) NOT NULL,
   service_name VARCHAR(255) NOT NULL,
   component_name VARCHAR(255),
+  scope VARCHAR(255),
   enabled SMALLINT DEFAULT 1 NOT NULL,
   schedule_interval BIGINT NOT NULL,
   source_type VARCHAR(255) NOT NULL,

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/resources/key_properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/key_properties.json b/ambari-server/src/main/resources/key_properties.json
index 68aa632..13adde8 100644
--- a/ambari-server/src/main/resources/key_properties.json
+++ b/ambari-server/src/main/resources/key_properties.json
@@ -130,5 +130,9 @@
     "Component": "HostComponentProcess/component_name",
     "HostComponent": "HostComponentProcess/component_name",
     "HostComponentProcess": "HostComponentProcess/name"
+  },
+  "AlertDefinition": {
+    "Cluster": "AlertDefinition/cluster_name",
+    "AlertDefinition": "AlertDefinition/id"
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/resources/properties.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json
index a6cdac4..4d5407c 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -355,5 +355,16 @@
       "HostComponentProcess/component_name",
       "HostComponentProcess/name",
       "HostComponentProcess/status"
+    ],
+    "AlertDefinition": [
+      "AlertDefinition/cluster_name",
+      "AlertDefinition/service_name",
+      "AlertDefinition/component_name",
+      "AlertDefinition/id",
+      "AlertDefinition/name",
+      "AlertDefinition/interval",
+      "AlertDefinition/source",
+      "AlertDefinition/enabled",
+      "AlertDefinition/scope"      
     ]
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/alerts.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/alerts.json b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/alerts.json
new file mode 100644
index 0000000..c1918e5
--- /dev/null
+++ b/ambari-server/src/main/resources/stacks/HDP/2.0.6/services/HDFS/alerts.json
@@ -0,0 +1,59 @@
+{
+  "service": [
+    // datanode space aggregate
+    // datanode process aggregate
+  ],
+  "SECONDARY_NAMENODE": [
+    {
+      "name": "secondary_namenode_process",
+      "label": "Secondary NameNode process",
+      "interval": 1,
+      "scope": "service",
+      "source": "port",
+      "port": {
+        "config": "{{hdfs-site/dfs.namenode.secondary.http-address}}:50071",
+        "default": 50071
+      }
+    }
+  ],
+  "NAMENODE": [
+    // name node cpu utilization (metric)
+    {
+      "name": "namenode_cpu",
+      "label": "NameNode host CPU Utilization",
+      "scope": "host",
+      "source": "metric",
+      "metric": {
+        "jmx_object": "java.lang:type=OperatingSystem",
+        "jmx_attribute": "SystemCpuLoad",
+        "host": "{{hdfs-site/dfs.namenode.secondary.http-address}}"
+      }
+    },
+    // namenode process (port check)
+    {
+      "name": "namenode_process",
+      "label": "NameNode process",
+      "interval": 1,
+      "scope": "host",
+      "source": "port",
+      "port": {
+        "uri": "{{hdfs-site/dfs.namenode.http-address}}:50070"
+       }
+    },
+    {
+      "name": "hdfs_last_checkpoint",
+      "label": "Last Checkpoint Time",
+      "interval": 1,
+      "scope": "service",
+      "source": "script",
+      "enabled": false
+      "script": {
+        "path": "scripts/alerts/last_checkpoint.py"
+      }
+    }
+  ],
+  "DATANODE": [
+    // datanode process (port check)
+    // datanode space
+  ]
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java
index a4ee74b..6a48134 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/resources/ClusterResourceDefinitionTest.java
@@ -50,13 +50,14 @@ public class ClusterResourceDefinitionTest {
     ResourceDefinition resource = new ClusterResourceDefinition();
     Set<SubResourceDefinition> subResources = resource.getSubResourceDefinitions();
 
-    assertEquals(6, subResources.size());
+    assertEquals(7, subResources.size());
     assertTrue(includesType(subResources, Resource.Type.Service));
     assertTrue(includesType(subResources, Resource.Type.Host));
     assertTrue(includesType(subResources, Resource.Type.Configuration));
     assertTrue(includesType(subResources, Resource.Type.Request));
     assertTrue(includesType(subResources, Resource.Type.Workflow));
     assertTrue(includesType(subResources, Resource.Type.ConfigGroup));
+    assertTrue(includesType(subResources, Resource.Type.AlertDefinition));
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/39a92eb4/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
index 71bc1f8..0c6f8f0 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/AmbariMetaInfoTest.java
@@ -61,6 +61,7 @@ import org.apache.ambari.server.state.RepositoryInfo;
 import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.Stack;
 import org.apache.ambari.server.state.StackInfo;
+import org.apache.ambari.server.state.alert.AlertDefinition;
 import org.apache.ambari.server.state.stack.MetricDefinition;
 import org.apache.commons.io.FileUtils;
 import org.junit.Before;
@@ -1382,4 +1383,25 @@ public class AmbariMetaInfoTest {
     Assert.assertNotNull(passwordProperty);
     Assert.assertEquals("javax.jdo.option.ConnectionPassword", passwordProperty.getName());
   }
+  
+  @Test
+  public void testAlertsJson() throws Exception {
+    ServiceInfo svc = metaInfo.getService(STACK_NAME_HDP, "2.0.5", "HDFS");
+    Assert.assertNotNull(svc);
+    Assert.assertNotNull(svc.getAlertsFile());
+
+    svc = metaInfo.getService(STACK_NAME_HDP, "2.0.6", "HDFS");
+    Assert.assertNotNull(svc);
+    Assert.assertNotNull(svc.getAlertsFile());
+
+    svc = metaInfo.getService(STACK_NAME_HDP, "1.3.4", "HDFS");
+    Assert.assertNotNull(svc);
+    Assert.assertNull(svc.getAlertsFile());
+    
+    Set<AlertDefinition> set = metaInfo.getAlertDefinitions(STACK_NAME_HDP,
+        "2.0.5", "HDFS");
+    Assert.assertNotNull(set);
+    Assert.assertTrue(set.size() > 0);
+    
+  }  
 }