/** * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2009-2010], VMware, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * */ package org.hyperic.hq.alerts; import java.io.InputStream; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.bind.JAXBException; import org.hyperic.hibernate.PageInfo; import org.hyperic.hq.appdef.shared.AppdefEntityConstants; import org.hyperic.hq.appdef.shared.AppdefEntityTypeID; import org.hyperic.hq.authz.server.session.AuthzSubject; import org.hyperic.hq.authz.server.session.AuthzSubjectManagerImpl; import org.hyperic.hq.authz.server.session.Resource; import org.hyperic.hq.authz.server.session.ResourceManagerImpl; import org.hyperic.hq.authz.shared.AuthzConstants; import org.hyperic.hq.authz.shared.AuthzSubjectManager; import org.hyperic.hq.authz.shared.PermissionException; import org.hyperic.hq.authz.shared.ResourceManager; import org.hyperic.hq.events.EventConstants; import org.hyperic.hq.events.server.session.AlertDefinitionManagerImpl; import org.hyperic.hq.events.shared.AlertConditionValue; import org.hyperic.hq.events.shared.AlertDefinitionManager; import org.hyperic.hq.events.shared.AlertDefinitionValue; import org.hyperic.hq.measurement.server.session.MeasurementTemplate; import org.hyperic.hq.measurement.server.session.MeasurementTemplateSortField; import org.hyperic.hq.measurement.server.session.TemplateManagerImpl; import org.hyperic.hq.measurement.shared.TemplateManager; import org.hyperic.hq.product.LogTrackPlugin; import org.hyperic.hq.types.AlertCondition; import org.hyperic.hq.types.AlertDefinition; import org.hyperic.hq.types.AlertDefinitionsResponse; import org.hyperic.hq.types.XmlUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * Parser responsible for transforming AlertDefinitionsResponse XML to a Set of * {@link AlertDefinitionValue}s * @author jhickey * */ @Component public class AlertDefinitionXmlParser { private static final Map EVENT_LEVEL_TO_NUM = new HashMap(); static { EVENT_LEVEL_TO_NUM.put("ANY", Integer.valueOf(-1)); EVENT_LEVEL_TO_NUM.put("ERR", Integer.valueOf(LogTrackPlugin.LOGLEVEL_ERROR)); EVENT_LEVEL_TO_NUM.put("WRN", Integer.valueOf(LogTrackPlugin.LOGLEVEL_WARN)); EVENT_LEVEL_TO_NUM.put("INF", Integer.valueOf(LogTrackPlugin.LOGLEVEL_INFO)); EVENT_LEVEL_TO_NUM.put("DBG", Integer.valueOf(LogTrackPlugin.LOGLEVEL_DEBUG)); } private final ResourceManager resourceManager; private final TemplateManager templateManager; private final AuthzSubjectManager authzSubjectManager; private final AlertDefinitionManager alertDefinitionManager; @Autowired public AlertDefinitionXmlParser(ResourceManager resourceManager, TemplateManager templateManager, AuthzSubjectManager authzSubjectManager, AlertDefinitionManager alertDefinitionManager) { this.resourceManager = resourceManager; this.templateManager = templateManager; this.authzSubjectManager = authzSubjectManager; this.alertDefinitionManager = alertDefinitionManager; } private MeasurementTemplate find(List templates, String metricName, Resource resource) { for (Iterator templateIterator = templates.iterator(); templateIterator.hasNext();) { MeasurementTemplate template = (MeasurementTemplate) templateIterator.next(); if (template.getName().equals(metricName)) { return template; } } throw new AlertDefinitionXmlParserException("Unable to find metric " + metricName + " for resource " + resource.getName()); } private int getAppdefType(Resource resource) { Integer typeId = resource.getResourceType().getId(); if (AuthzConstants.authzPlatformProto.equals(typeId)) { return AppdefEntityConstants.APPDEF_TYPE_PLATFORM; } else if (AuthzConstants.authzServerProto.equals(typeId)) { return AppdefEntityConstants.APPDEF_TYPE_SERVER; } else if (AuthzConstants.authzServiceProto.equals(typeId)) { return AppdefEntityConstants.APPDEF_TYPE_SERVICE; } else { throw new AlertDefinitionXmlParserException("Resource [" + resource + "] is not an appdef " + "resource type"); } } private List getTemplates(AuthzSubject subject, Resource resource) { try { return templateManager.findTemplatesByMonitorableType(subject, PageInfo.getAll(MeasurementTemplateSortField.TEMPLATE_NAME, true), resource.getName(), null); } catch (PermissionException e) { throw new AlertDefinitionXmlParserException("Error obtaining measurement templates. Cause: " + e.getMessage()); } } private AlertConditionValue parse(AlertCondition condition, AlertDefinition definition, List templates, Resource resource, AuthzSubject subject) { AlertConditionValue alertConditionValue = new AlertConditionValue(); alertConditionValue.setRequired(condition.isRequired()); alertConditionValue.setType(condition.getType()); switch (alertConditionValue.getType()) { case EventConstants.TYPE_THRESHOLD: parseThresholdCondition(condition, definition, templates, resource, alertConditionValue); break; case EventConstants.TYPE_BASELINE: parseBaselineCondition(condition, definition, templates, resource, alertConditionValue); break; case EventConstants.TYPE_CONTROL: parseControlCondition(condition, definition, alertConditionValue); break; case EventConstants.TYPE_CHANGE: parseMetricChangeCondition(condition, definition, templates, resource, alertConditionValue); break; case EventConstants.TYPE_ALERT: parseAlertCondition(condition, definition, resource, subject, alertConditionValue); break; case EventConstants.TYPE_CUST_PROP: parsePropertyChangeCondition(condition, definition, alertConditionValue); break; case EventConstants.TYPE_LOG: parseLogCondition(condition, definition, alertConditionValue); break; case EventConstants.TYPE_CFG_CHG: parseConfigChangeCondition(condition, alertConditionValue); break; default: throw new AlertDefinitionXmlParserException("Unhandled AlertCondition " + "type " + alertConditionValue.getType() + " for " + definition.getName()); } return alertConditionValue; } AlertDefinitionValue parse(AlertDefinition definition) { if (definition.getName() == null) { throw new AlertDefinitionXmlParserException("Required attribute name not found for definition"); } String name = definition.getResourcePrototype().getName(); Resource resource = resourceManager.findResourcePrototypeByName(name); if (resource == null) { throw new AlertDefinitionXmlParserException("Cannot find resource type " + name + " for definition " + definition.getName()); } // Alert priority must be 1-3 int priority = definition.getPriority(); if (priority < 1 || priority > 3) { throw new AlertDefinitionXmlParserException("AlertDefinition priority must be " + "between 1 (low) and 3 (high) " + "found=" + priority); } // Alert frequency must be 0-4 int frequency = definition.getFrequency(); if (frequency != 0 && frequency != 2 && frequency != 4) { throw new AlertDefinitionXmlParserException("AlertDefinition frequency must be " + "either 0, 2, or 4 " + "found=" + frequency); } if (definition.getAlertCondition() == null || definition.getAlertCondition().size() < 1) { // At least one condition is always required throw new AlertDefinitionXmlParserException("At least 1 AlertCondition is " + "required for definition " + definition.getName()); } AppdefEntityTypeID aeid = new AppdefEntityTypeID(getAppdefType(resource), resource.getInstanceId()); AlertDefinitionValue alertDefValue = new AlertDefinitionValue(); alertDefValue.setName(definition.getName()); alertDefValue.setDescription(definition.getDescription()); alertDefValue.setAppdefType(aeid.getType()); alertDefValue.setAppdefId(aeid.getId()); alertDefValue.setParentId(EventConstants.TYPE_ALERT_DEF_ID); alertDefValue.setPriority(definition.getPriority()); alertDefValue.setActive(definition.isActive()); alertDefValue.setWillRecover(definition.isWillRecover()); alertDefValue.setNotifyFiltered(definition.isNotifyFiltered()); alertDefValue.setControlFiltered(definition.isControlFiltered()); alertDefValue.setFrequencyType(definition.getFrequency()); alertDefValue.setCount(definition.getCount()); alertDefValue.setRange(definition.getRange()); AuthzSubject overlord = authzSubjectManager.getOverlordPojo(); List templates = getTemplates(overlord, resource); for (Iterator conditions = definition.getAlertCondition().iterator(); conditions.hasNext();) { AlertCondition condition = (AlertCondition) conditions.next(); AlertConditionValue alertConditionValue = parse(condition, definition, templates, resource, overlord); alertDefValue.addCondition(alertConditionValue); } return alertDefValue; } /** * * @param alertDefinitionsXml InputStream of XML that can be deserialized to * an {@link AlertDefinitionsResponse} * @return A Set of {@link AlertDefinitionValue}s parsed from the XML */ public Set<AlertDefinitionValue> parse(InputStream alertDefinitionsXml) { List<AlertDefinition> alertDefinitions; try { AlertDefinitionsResponse response = (AlertDefinitionsResponse) XmlUtil.deserialize(AlertDefinitionsResponse.class, alertDefinitionsXml); alertDefinitions = response.getAlertDefinition(); } catch (JAXBException e) { throw new AlertDefinitionXmlParserException("Error parsing alert definition XML. Cause: " + e.getMessage()); } return parse(alertDefinitions); } Set<AlertDefinitionValue> parse(List<AlertDefinition> alertDefinitions) { final Set<AlertDefinitionValue> alertDefinitionValues = new HashSet<AlertDefinitionValue>(); for (AlertDefinition definition : alertDefinitions) { alertDefinitionValues.add(parse(definition)); } return alertDefinitionValues; } private void parseAlertCondition(AlertCondition condition, AlertDefinition definition, Resource resource, AuthzSubject subject, AlertConditionValue alertConditionValue) { if (condition.getRecover() == null) { throw new AlertDefinitionXmlParserException("Required attribute recover not found for condition of alert definition " + definition.getName()); } List resourceDefs; try { resourceDefs = alertDefinitionManager.findAlertDefinitions(subject, resource); } catch (PermissionException e) { throw new AlertDefinitionXmlParserException("Error obtaining resource type alerts. Cause: " + e.getMessage()); } boolean foundDefinition = false; for (Iterator resourceAlerts = resourceDefs.iterator(); resourceAlerts.hasNext();) { org.hyperic.hq.events.server.session.AlertDefinition resourceDef = (org.hyperic.hq.events.server.session.AlertDefinition) resourceAlerts.next(); if (condition.getRecover().equals(resourceDef.getName())) { alertConditionValue.setMeasurementId(resourceDef.getId().intValue()); foundDefinition = true; break; } } if (!foundDefinition) { throw new AlertDefinitionXmlParserException("Unable to find recovery " + "with name '" + condition.getRecover() + "'"); } } private void parseBaselineCondition(AlertCondition condition, AlertDefinition definition, List templates, Resource resource, AlertConditionValue alertConditionValue) { if (condition.getBaselineMetric() == null) { throw new AlertDefinitionXmlParserException("Required attribute baselineMetric not found for condition of alert definition " + definition.getName()); } if (condition.getBaselineComparator() == null) { throw new AlertDefinitionXmlParserException("Required attribute baselineComparator not found for condition of alert definition " + definition.getName()); } alertConditionValue.setName(condition.getBaselineMetric()); MeasurementTemplate template = find(templates, alertConditionValue.getName(), resource); String baselineType = condition.getBaselineType(); if (!"min".equals(baselineType) && !"max".equals(baselineType) && !"mean".equals(baselineType)) { throw new AlertDefinitionXmlParserException("Invalid baseline type '" + baselineType + "'"); } alertConditionValue.setMeasurementId(template.getId().intValue()); alertConditionValue.setComparator(condition.getBaselineComparator()); alertConditionValue.setThreshold(condition.getBaselinePercentage().doubleValue()); alertConditionValue.setOption(baselineType); } private void parseConfigChangeCondition(AlertCondition condition, AlertConditionValue alertConditionValue) { String configMatch = condition.getConfigMatch(); if (configMatch != null) { alertConditionValue.setOption(configMatch); } } private void parseControlCondition(AlertCondition condition, AlertDefinition definition, AlertConditionValue alertConditionValue) { if (condition.getControlAction() == null) { throw new AlertDefinitionXmlParserException("Required attribute controlAction not found for condition of alert definition " + definition.getName()); } String controlStatus = condition.getControlStatus(); if (!"Completed".equals(controlStatus) && !"In Progress".equals(controlStatus) && !"Failed".equals(controlStatus)) { throw new AlertDefinitionXmlParserException("Invalid control condition " + "status " + controlStatus); } alertConditionValue.setName(condition.getControlAction()); alertConditionValue.setOption(controlStatus); } private void parseLogCondition(AlertCondition condition, AlertDefinition definition, AlertConditionValue alertConditionValue) { Integer level = (Integer) EVENT_LEVEL_TO_NUM.get(condition.getLogLevel()); if (level == null) { throw new AlertDefinitionXmlParserException("Unknown log level " + condition.getLogLevel()); } alertConditionValue.setName(level.toString()); alertConditionValue.setOption(condition.getLogMatches()); } private void parseMetricChangeCondition(AlertCondition condition, AlertDefinition definition, List templates, Resource resource, AlertConditionValue alertConditionValue) { if (condition.getMetricChange() == null) { throw new AlertDefinitionXmlParserException("Required attribute metricChange not found for condition of alert definition " + definition.getName()); } alertConditionValue.setName(condition.getMetricChange()); MeasurementTemplate template = find(templates, alertConditionValue.getName(), resource); alertConditionValue.setMeasurementId(template.getId().intValue()); } private void parsePropertyChangeCondition(AlertCondition condition, AlertDefinition definition, AlertConditionValue alertConditionValue) { if (condition.getProperty() == null) { throw new AlertDefinitionXmlParserException("Required attribute property not found for condition of alert definition " + definition.getName()); } alertConditionValue.setName(condition.getProperty()); } private void parseThresholdCondition(AlertCondition condition, AlertDefinition definition, List templates, Resource resource, AlertConditionValue alertConditionValue) { if (condition.getThresholdMetric() == null) { throw new AlertDefinitionXmlParserException("Required attribute thresholdMetric not found for condition of alert definition " + definition.getName()); } if (condition.getThresholdComparator() == null) { throw new AlertDefinitionXmlParserException("Required attribute thresholdComparator not found for condition of alert definition " + definition.getName()); } alertConditionValue.setName(condition.getThresholdMetric()); MeasurementTemplate template = find(templates, alertConditionValue.getName(), resource); alertConditionValue.setMeasurementId(template.getId().intValue()); alertConditionValue.setComparator(condition.getThresholdComparator()); alertConditionValue.setThreshold(condition.getThresholdValue().doubleValue()); } }