Repository: ambari Updated Branches: refs/heads/trunk 4541b382a -> cf094a7e5
AMBARI-10285 - Storm Shows An Alert for REST_API Component After Stack Upgrade (jonathanhurley) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/cf094a7e Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/cf094a7e Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/cf094a7e Branch: refs/heads/trunk Commit: cf094a7e5f5dfc88c5496aa504ca895a01cb58b3 Parents: 4541b38 Author: Jonathan Hurley <[email protected]> Authored: Mon Mar 30 16:54:08 2015 -0400 Committer: Jonathan Hurley <[email protected]> Committed: Tue Mar 31 08:18:02 2015 -0400 ---------------------------------------------------------------------- .../server/api/services/AmbariMetaInfo.java | 64 +++++++++++++++++++- .../server/orm/dao/AlertDefinitionDAO.java | 16 +++++ .../orm/entities/AlertDefinitionEntity.java | 1 + .../server/api/services/AmbariMetaInfoTest.java | 48 +++++++++++++-- .../apache/ambari/server/orm/OrmTestHelper.java | 12 +++- .../server/orm/dao/AlertDefinitionDAOTest.java | 21 +++++++ 6 files changed, 154 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/cf094a7e/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 143022e..0cb8fa4 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 @@ -40,8 +40,11 @@ import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.ParentObjectNotFoundException; import org.apache.ambari.server.StackAccessException; import org.apache.ambari.server.configuration.Configuration; +import org.apache.ambari.server.controller.RootServiceResponseFactory.Components; +import org.apache.ambari.server.controller.RootServiceResponseFactory.Services; import org.apache.ambari.server.customactions.ActionDefinition; import org.apache.ambari.server.customactions.ActionDefinitionManager; +import org.apache.ambari.server.events.AlertDefinitionDisabledEvent; import org.apache.ambari.server.events.AlertDefinitionRegistrationEvent; import org.apache.ambari.server.events.publishers.AmbariEventPublisher; import org.apache.ambari.server.metadata.ActionMetadata; @@ -176,6 +179,8 @@ public class AmbariMetaInfo { * <ul> * <li>{@link AlertDefinitionRegistrationEvent} when new alerts are merged * from the stack</li> + * <li>{@link AlertDefinitionDisabledEvent} when existing definitions are + * disabled after being removed from the current stack</li> * </ul> */ @Inject @@ -965,11 +970,17 @@ public class AmbariMetaInfo { StackInfo stackInfo = getStack(stackId.getStackName(), stackId.getStackVersion()); - // creating a mapping between service name and service for fast lookups + // creating a mapping between names and service/component for fast lookups Collection<ServiceInfo> stackServices = stackInfo.getServices(); Map<String, ServiceInfo> stackServiceMap = new HashMap<String, ServiceInfo>(); + Map<String, ComponentInfo> stackComponentMap = new HashMap<String, ComponentInfo>(); for (ServiceInfo stackService : stackServices) { stackServiceMap.put(stackService.getName(), stackService); + + List<ComponentInfo> components = stackService.getComponents(); + for (ComponentInfo component : components) { + stackComponentMap.put(component.getName(), component); + } } Map<String, Service> clusterServiceMap = cluster.getServices(); @@ -984,6 +995,7 @@ public class AmbariMetaInfo { continue; } + // get all alerts defined on the stack for each cluster service Set<AlertDefinition> serviceDefinitions = getAlertDefinitions(stackService); stackDefinitions.addAll(serviceDefinitions); @@ -1055,6 +1067,52 @@ public class AmbariMetaInfo { eventPublisher.publish(event); } + + // for every definition, determine if the service and the component are + // still valid; if they are not, disable them - this covers the case + // with STORM/REST_API where that component was removed from the + // stack but still exists in the database - we disable the alert to + // preserve historical references + List<AlertDefinitionEntity> definitions = alertDefinitionDao.findAllEnabled(clusterId); + List<AlertDefinitionEntity> definitionsToDisable = new ArrayList<AlertDefinitionEntity>(); + + for (AlertDefinitionEntity definition : definitions) { + String serviceName = definition.getServiceName(); + String componentName = definition.getComponentName(); + + // the AMBARI service is special, skip it here + if (Services.AMBARI.name().equals(serviceName) + && Components.AMBARI_AGENT.name().equals(componentName)) { + continue; + } + + if (!stackServiceMap.containsKey(serviceName)) { + LOG.info( + "The {} service has been marked as deleted for stack {}, disabling alert {}", + serviceName, stackId, definition.getDefinitionName()); + + definitionsToDisable.add(definition); + } else if (null != componentName + && !stackComponentMap.containsKey(componentName)) { + LOG.info( + "The {} component {} has been marked as deleted for stack {}, disabling alert {}", + serviceName, componentName, stackId, + definition.getDefinitionName()); + + definitionsToDisable.add(definition); + } + } + + // disable definitions and fire the event + for (AlertDefinitionEntity definition : definitionsToDisable) { + definition.setEnabled(false); + alertDefinitionDao.merge(definition); + + AlertDefinitionDisabledEvent event = new AlertDefinitionDisabledEvent( + clusterId, definition.getDefinitionId()); + + eventPublisher.publish(event); + } } } @@ -1107,10 +1165,10 @@ public class AmbariMetaInfo { throw new AmbariException(String.format("Failed to parse kerberos descriptor file %s", file.getAbsolutePath()), e); } - } - else + } else { throw new AmbariException(String.format("Unable to read kerberos descriptor file %s", file.getAbsolutePath())); + } } if (kerberosDescriptor == null) { http://git-wip-us.apache.org/repos/asf/ambari/blob/cf094a7e/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 659fb21..d838d25 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 @@ -159,6 +159,22 @@ public class AlertDefinitionDAO { } /** + * Gets all enabled alert definitions stored in the database for the specified + * cluster. + * + * @return all enabled alert definitions or empty list if none exist (never + * {@code null}). + */ + public List<AlertDefinitionEntity> findAllEnabled(long clusterId) { + TypedQuery<AlertDefinitionEntity> query = entityManagerProvider.get().createNamedQuery( + "AlertDefinitionEntity.findAllEnabledInCluster", + AlertDefinitionEntity.class); + + query.setParameter("clusterId", clusterId); + return daoUtils.selectList(query); + } + + /** * Gets all of the alert definitions for the list of IDs given. * * @param definitionIds http://git-wip-us.apache.org/repos/asf/ambari/blob/cf094a7e/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 cd06e23..6838983 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 @@ -59,6 +59,7 @@ import org.apache.ambari.server.state.alert.SourceType; @NamedQueries({ @NamedQuery(name = "AlertDefinitionEntity.findAll", query = "SELECT ad FROM AlertDefinitionEntity ad"), @NamedQuery(name = "AlertDefinitionEntity.findAllInCluster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.clusterId = :clusterId"), + @NamedQuery(name = "AlertDefinitionEntity.findAllEnabledInCluster", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.clusterId = :clusterId AND ad.enabled = 1"), @NamedQuery(name = "AlertDefinitionEntity.findByName", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.definitionName = :definitionName AND ad.clusterId = :clusterId"), @NamedQuery(name = "AlertDefinitionEntity.findByService", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName = :serviceName AND ad.clusterId = :clusterId"), @NamedQuery(name = "AlertDefinitionEntity.findByServiceAndComponent", query = "SELECT ad FROM AlertDefinitionEntity ad WHERE ad.serviceName = :serviceName AND ad.componentName = :componentName AND ad.clusterId = :clusterId"), http://git-wip-us.apache.org/repos/asf/ambari/blob/cf094a7e/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 96e7ff2..051cf54 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 @@ -38,6 +38,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import javax.persistence.EntityManager; @@ -76,6 +77,7 @@ import org.apache.ambari.server.state.alert.MetricSource; import org.apache.ambari.server.state.alert.PortSource; import org.apache.ambari.server.state.alert.Reporting; import org.apache.ambari.server.state.alert.Source; +import org.apache.ambari.server.state.alert.SourceType; import org.apache.ambari.server.state.kerberos.KerberosDescriptor; import org.apache.ambari.server.state.kerberos.KerberosDescriptorFactory; import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptorFactory; @@ -101,7 +103,6 @@ import com.google.inject.util.Modules; public class AmbariMetaInfoTest { private static final String STACK_NAME_HDP = "HDP"; - private static final String STACK_NAME_XYZ = "XYZ"; private static final String STACK_VERSION_HDP = "0.1"; private static final String EXT_STACK_NAME = "2.0.6"; private static final String STACK_VERSION_HDP_02 = "0.2"; @@ -1705,7 +1706,8 @@ public class AmbariMetaInfoTest { injector.getInstance(GuiceJpaInitializer.class); injector.getInstance(EntityManager.class); - injector.getInstance(OrmTestHelper.class).createCluster(); + long clusterId = injector.getInstance(OrmTestHelper.class).createCluster( + "cluster" + System.currentTimeMillis()); metaInfo.alertDefinitionDao = injector.getInstance(AlertDefinitionDAO.class); Class<?> c = metaInfo.getClass().getSuperclass(); @@ -1714,7 +1716,7 @@ public class AmbariMetaInfoTest { f.set(metaInfo, injector.getInstance(AgentAlertDefinitions.class)); Clusters clusters = injector.getInstance(Clusters.class); - Cluster cluster = clusters.getClusterById(1); + Cluster cluster = clusters.getClusterById(clusterId); cluster.setDesiredStackVersion( new StackId(STACK_NAME_HDP, "2.0.6")); @@ -1723,7 +1725,7 @@ public class AmbariMetaInfoTest { metaInfo.reconcileAlertDefinitions(clusters); AlertDefinitionDAO dao = injector.getInstance(AlertDefinitionDAO.class); - List<AlertDefinitionEntity> definitions = dao.findAll(); + List<AlertDefinitionEntity> definitions = dao.findAll(clusterId); assertEquals(7, definitions.size()); // figure out how many of these alerts were merged into from the @@ -1752,6 +1754,44 @@ public class AmbariMetaInfoTest { for (AlertDefinitionEntity definition : definitions) { assertEquals(28, definition.getScheduleInterval().intValue()); } + + // find all enabled for the cluster should find 6 (the ones from HDFS; + // it will not find the agent alert since it's not bound to the cluster) + definitions = dao.findAllEnabled(cluster.getClusterId()); + assertEquals(6, definitions.size()); + + // create new definition + AlertDefinitionEntity entity = new AlertDefinitionEntity(); + entity.setClusterId(clusterId); + entity.setDefinitionName("bad_hdfs_alert"); + entity.setLabel("Bad HDFS Alert"); + entity.setDescription("A way to fake a component being removed"); + entity.setEnabled(true); + entity.setHash(UUID.randomUUID().toString()); + entity.setScheduleInterval(1); + entity.setServiceName("HDFS"); + entity.setComponentName("BAD_COMPONENT"); + entity.setSourceType(SourceType.METRIC); + entity.setSource("{\"type\" : \"METRIC\"}"); + dao.create(entity); + + // verify the new definition is found (6 HDFS + 1 new one) + definitions = dao.findAllEnabled(cluster.getClusterId()); + assertEquals(7, definitions.size()); + + // reconcile, which should disable our bad definition + metaInfo.reconcileAlertDefinitions(clusters); + + // find all enabled for the cluster should find 6 + definitions = dao.findAllEnabled(cluster.getClusterId()); + assertEquals(6, definitions.size()); + + // find all should find 6 HDFS + 1 disabled + 1 agent alert + definitions = dao.findAll(); + assertEquals(8, definitions.size()); + + entity = dao.findById(entity.getDefinitionId()); + assertFalse(entity.getEnabled()); } @Test http://git-wip-us.apache.org/repos/asf/ambari/blob/cf094a7e/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java index b9fc424..6041066 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/OrmTestHelper.java @@ -296,6 +296,16 @@ public class OrmTestHelper { */ @Transactional public Long createCluster() { + return createCluster("test_cluster1"); + } + + /** + * Creates an empty cluster with an ID using the specified cluster name. + * + * @return the cluster ID. + */ + @Transactional + public Long createCluster(String clusterName) { ResourceTypeDAO resourceTypeDAO = injector.getInstance(ResourceTypeDAO.class); ResourceTypeEntity resourceTypeEntity = new ResourceTypeEntity(); @@ -309,7 +319,7 @@ public class OrmTestHelper { ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class); ClusterEntity clusterEntity = new ClusterEntity(); - clusterEntity.setClusterName("test_cluster1"); + clusterEntity.setClusterName(clusterName); clusterEntity.setClusterInfo("test_cluster_info1"); clusterEntity.setResource(resourceEntity); http://git-wip-us.apache.org/repos/asf/ambari/blob/cf094a7e/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 acf25d2..2e0f238 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 @@ -185,6 +185,27 @@ public class AlertDefinitionDAOTest { } /** + * + */ + @Test + public void testFindAllEnabled() { + List<AlertDefinitionEntity> definitions = dao.findAll(); + assertNotNull(definitions); + assertEquals(15, definitions.size()); + + List<AlertDefinitionEntity> enabledDefinitions = dao.findAllEnabled(clusterId); + assertNotNull(enabledDefinitions); + assertEquals(definitions.size(), enabledDefinitions.size()); + + enabledDefinitions.get(0).setEnabled(false); + dao.merge(enabledDefinitions.get(0)); + + enabledDefinitions = dao.findAllEnabled(clusterId); + assertNotNull(enabledDefinitions); + assertEquals(definitions.size() - 1, enabledDefinitions.size()); + } + + /** * */ @Test
