org.rhq.enterprise.server.plugins.alertdef.AlertDefinitionServerPluginComponent.java Source code

Java tutorial

Introduction

Here is the source code for org.rhq.enterprise.server.plugins.alertdef.AlertDefinitionServerPluginComponent.java

Source

/*
 * RHQ Management Platform
 * Copyright 2013, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation version 2 of the License.
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.rhq.enterprise.server.plugins.alertdef;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.rhq.core.domain.alert.AlertCondition;
import org.rhq.core.domain.alert.AlertConditionCategory;
import org.rhq.core.domain.alert.AlertDampening;
import org.rhq.core.domain.alert.AlertDampening.TimeUnits;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.alert.AlertPriority;
import org.rhq.core.domain.alert.BooleanExpression;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
import org.rhq.core.domain.criteria.ResourceTypeCriteria;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.operation.OperationRequestStatus;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal;
import org.rhq.enterprise.server.alert.AlertTemplateManagerLocal;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal;
import org.rhq.enterprise.server.plugin.pc.ControlFacet;
import org.rhq.enterprise.server.plugin.pc.ControlResults;
import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;

/**
 * An alert definition server-side plugin component that the server uses to inject "factory-installed" alert definitions.
 *
 * @author Jay Shaughnessy
 */
public class AlertDefinitionServerPluginComponent implements ServerPluginComponent, ControlFacet {

    private final Log log = LogFactory.getLog(AlertDefinitionServerPluginComponent.class);

    private static final String DATA_DISK_USED_PERCENTAGE_METRIC_NAME = "Calculated.DataDiskUsedPercentage";
    private static final String TOTAL_DISK_USED_PERCENTAGE_METRIC_NAME = "Calculated.TotalDiskUsedPercentage";
    private static final String FREE_DISK_TO_DATA_SIZE_RATIO_METRIC_NAME = "Calculated.FreeDiskToDataSizeRatio";
    private static final String TAKE_SNAPSHOT_OPERATION_NAME = "takeSnapshot";
    private static final String[] MAINTENANCE_OPERATIONS = new String[] { "readRepair", "addNodeMaintenance",
            "removeNodeMaintenance", "announce", "unannounce", "prepareForBootstrap", "prepareForUpgrade",
            "updateSeedsList", "updateConfiguration", "takeSnapshot" };

    static private final List<InjectedTemplate> injectedTemplates;
    static private final InjectedTemplate storageNodeHighHeapTemplate;
    static private final InjectedTemplate storageNodeHighDiskUsageTemplate;
    static private final InjectedTemplate storageNodeSnapshotFailureTemplate;
    static private final InjectedTemplate storageNodeMaintenanceOperationsFailureTemplate;

    static {
        storageNodeHighHeapTemplate = new InjectedTemplate("RHQStorage", //
                "VM Memory System", //
                "StorageNodeHighHeap", //
                "Increase the storage node heap. If you cannot increase the heap or if you continue receiving alerts, then"
                        + " deploy another storage node. Consult <a href='.#Help/Section1/Section1Item4'>wiki</a> for more info.");

        storageNodeHighDiskUsageTemplate = new InjectedTemplate("RHQStorage", //
                "StorageService", //
                "StorageNodeHighDiskUsage", //
                "Increase the storage node disk size. If you cannot increase the disk size or if you continue receiving "
                        + "alerts, then deploy another storage node. Consult <a href='.#Help/Section1/Section1Item4'>wiki</a> for more info.");

        storageNodeSnapshotFailureTemplate = new InjectedTemplate("RHQStorage", //
                "StorageService", //
                "StorageNodeSnapshotFailure", //
                "Snapshot operation failed for an RHQ Storage Node. When fired please see documentation for the proper corrective action.");

        storageNodeMaintenanceOperationsFailureTemplate = new InjectedTemplate("RHQStorage", //
                "RHQ Storage Node", //
                "StorageNodeMaintenanceOperationsFailure", //
                "Maintenance operation failed for an RHQ Storage Node. When fired please see documentation for the proper corrective action.");

        injectedTemplates = new ArrayList<InjectedTemplate>();
        injectedTemplates.add(storageNodeHighHeapTemplate);
        injectedTemplates.add(storageNodeHighDiskUsageTemplate);
        injectedTemplates.add(storageNodeSnapshotFailureTemplate);
        injectedTemplates.add(storageNodeMaintenanceOperationsFailureTemplate);

    }

    private ServerPluginContext context;

    @Override
    public void initialize(ServerPluginContext context) throws Exception {
        this.context = context;
        log.debug("The RHQ AlertDefinition plugin has been initialized!!! : " + this);
    }

    @Override
    public void start() {
        boolean injectAtPluginStartup = Boolean
                .valueOf(context.getPluginConfiguration().getSimpleValue("injectAtPluginStartup", "true"));
        boolean replaceIfExists = Boolean
                .valueOf(context.getPluginConfiguration().getSimpleValue("replaceIfExists", "false"));

        if (injectAtPluginStartup) {
            injectAllAlertDefs(replaceIfExists);
        }

        log.debug("The RHQ AlertDefinition plugin has started!!! : " + this);

    }

    @Override
    public void stop() {
        log.debug("The RHQ AlertDefinition plugin has stopped!!! : " + this);
    }

    @Override
    public void shutdown() {
        log.debug("The RHQ AlertDefinition plugin has been shut down!!! : " + this);
    }

    @Override
    public ControlResults invoke(String name, Configuration parameters) {
        ControlResults controlResults = new ControlResults();

        try {
            if (name.equals("listInjectedAlertDefinitions")) {
                PropertyList result = new PropertyList("injectedAlertDefinitions");
                for (InjectedTemplate iad : injectedTemplates) {
                    PropertyMap map = new PropertyMap("injectedAlertDefinition");
                    map.put(new PropertySimple(InjectedTemplate.FIELD_PLUGIN_NAME, iad.getPluginName()));
                    map.put(new PropertySimple(InjectedTemplate.FIELD_RESOURCE_TYPE_NAME,
                            iad.getResourceTypeName()));
                    map.put(new PropertySimple(InjectedTemplate.FIELD_NAME, iad.getName()));
                    map.put(new PropertySimple(InjectedTemplate.FIELD_DESCRIPTION, iad.getDescription()));
                    result.add(map);
                }
                controlResults.getComplexResults().put(result);

            } else if (name.equals("injectAllAlertDefinitions")) {
                injectAllAlertDefs(Boolean.valueOf(parameters.getSimpleValue("replaceIfExists")));

            } else if (name.equals("injectAlertDefinition")) {
                InjectedTemplate requestedInjection = new InjectedTemplate( //
                        parameters.getSimpleValue(InjectedTemplate.FIELD_PLUGIN_NAME), //
                        parameters.getSimpleValue(InjectedTemplate.FIELD_RESOURCE_TYPE_NAME), //
                        parameters.getSimpleValue(InjectedTemplate.FIELD_NAME), null);
                boolean injected = false;
                for (InjectedTemplate iad : injectedTemplates) {
                    if (iad.equals(requestedInjection)) {
                        injectAlertDef(iad, Boolean.valueOf(parameters.getSimpleValue("replaceIfExists", "false")));
                        injected = true;
                        break;
                    }
                }

                if (!injected) {
                    controlResults
                            .setError("Unknown requested alert definition. Check spelling: " + requestedInjection);
                }

            } else {
                controlResults.setError("Unknown control name: " + name);
            }
        } catch (Throwable t) {
            controlResults.setError(t);
        }

        return controlResults;
    }

    private List<AlertDefinition> injectAllAlertDefs(boolean replaceIfExists) {

        List<AlertDefinition> result = new ArrayList<AlertDefinition>();

        for (InjectedTemplate iad : injectedTemplates) {
            AlertDefinition newAlertDef = injectAlertDef(iad, replaceIfExists);
            if (null != newAlertDef) {
                result.add(newAlertDef);
            }
        }

        return result;
    }

    private AlertDefinition injectAlertDef(InjectedTemplate injectedAlertDef, boolean replaceIfExists) {

        AlertDefinition result = null;
        ResourceTypeManagerLocal typeManager = LookupUtil.getResourceTypeManager();
        AlertDefinitionManagerLocal alertDefManager = LookupUtil.getAlertDefinitionManager();
        SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();

        ResourceTypeCriteria rtc = new ResourceTypeCriteria();
        rtc.addFilterPluginName(injectedAlertDef.getPluginName());
        rtc.addFilterName(injectedAlertDef.getResourceTypeName());
        rtc.fetchMetricDefinitions(true);
        List<ResourceType> resourceTypes = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(),
                rtc);

        if (resourceTypes.isEmpty()) {
            return result;
        }

        assert 1 == resourceTypes.size() : "Found more than 1 resource type!";
        ResourceType resourceType = resourceTypes.get(0);

        AlertDefinitionCriteria adc = new AlertDefinitionCriteria();
        adc.addFilterName(injectedAlertDef.getName());
        adc.addFilterAlertTemplateResourceTypeId(resourceType.getId());
        List<AlertDefinition> alertDefs = alertDefManager
                .findAlertDefinitionsByCriteria(subjectManager.getOverlord(), adc);

        if (!alertDefs.isEmpty()) {
            assert 1 == alertDefs.size() : "Found more than 1 existing alert def!";

            if (!replaceIfExists) {
                return result;
            }

            int[] alertDefIdArray = new int[1];
            alertDefIdArray[0] = alertDefs.get(0).getId();
            alertDefManager.removeAlertDefinitions(subjectManager.getOverlord(), alertDefIdArray);
        }

        int newAlertDefId = 0;

        if (storageNodeHighHeapTemplate.equals(injectedAlertDef)) {
            newAlertDefId = injectStorageNodeHighHeapTemplate(resourceType);
        } else if (storageNodeHighDiskUsageTemplate.equals(injectedAlertDef)) {
            newAlertDefId = injectStorageNodeHighDiskUsageTemplate(resourceType);
        } else if (storageNodeSnapshotFailureTemplate.equals(injectedAlertDef)) {
            newAlertDefId = injectStorageNodeSnapshotFailureTemplate(resourceType);
        } else if (storageNodeMaintenanceOperationsFailureTemplate.equals(injectedAlertDef)) {
            newAlertDefId = injectStorageNodeMaintenanceOperationsFailureTemplate(resourceType);
        }

        adc.addFilterId(newAlertDefId);
        alertDefs = alertDefManager.findAlertDefinitionsByCriteria(subjectManager.getOverlord(), adc);
        assert 1 == alertDefs.size() : "Found more than 1 new alert def!";
        result = alertDefs.get(0);

        return result;
    }

    private int injectStorageNodeHighHeapTemplate(ResourceType resourceType) {
        AlertTemplateManagerLocal alertTemplateManager = LookupUtil.getAlertTemplateManager();
        SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();

        AlertDefinition newTemplate = new AlertDefinition();
        newTemplate.setName(storageNodeHighHeapTemplate.getName());
        newTemplate.setResourceType(resourceType);
        newTemplate.setPriority(AlertPriority.MEDIUM);
        newTemplate.setConditionExpression(BooleanExpression.ANY);
        newTemplate.setDescription(storageNodeHighHeapTemplate.getDescription());
        newTemplate.setRecoveryId(0);
        newTemplate.setEnabled(true);

        AlertCondition ac = new AlertCondition();
        ac.setCategory(AlertConditionCategory.THRESHOLD);
        ac.setComparator(">");
        ac.setThreshold(0.75D);

        List<Integer> measurementDefinitionIds = new ArrayList<Integer>(2);
        for (MeasurementDefinition d : resourceType.getMetricDefinitions()) {
            if ("Calculated.HeapUsagePercentage".equals(d.getName())) {
                measurementDefinitionIds.add(d.getId());
                ac.setMeasurementDefinition(d);
                ac.setName(d.getDisplayName());
            } else if ("{HeapMemoryUsage.used}".equals(d.getName())) {
                measurementDefinitionIds.add(d.getId());
            }
        }
        assert null != ac
                .getMeasurementDefinition() : "Did not find expected measurement definition [Calculated.HeapUsagePercentage] for "
                        + resourceType;
        newTemplate.addCondition(ac);

        AlertDampening dampener = new AlertDampening(AlertDampening.Category.PARTIAL_COUNT);
        dampener.setPeriod(15);
        dampener.setPeriodUnits(TimeUnits.MINUTES);
        dampener.setValue(10);
        newTemplate.setAlertDampening(dampener);

        int newTemplateId = alertTemplateManager.createAlertTemplate(subjectManager.getOverlord(), newTemplate,
                resourceType.getId());

        // additionally, we want to ensure that the metric is enabled and collecting at a more frequent interval than
        // is set by default.
        MeasurementScheduleManagerLocal measurementManager = LookupUtil.getMeasurementScheduleManager();
        measurementManager.updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(
                subjectManager.getOverlord(),
                ArrayUtils.toPrimitive(measurementDefinitionIds.toArray(new Integer[2])), 60000L, true, true);

        return newTemplateId;
    }

    private int injectStorageNodeHighDiskUsageTemplate(ResourceType resourceType) {
        AlertTemplateManagerLocal alertTemplateManager = LookupUtil.getAlertTemplateManager();
        SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();

        AlertDefinition newTemplate = new AlertDefinition();
        newTemplate.setName(storageNodeHighDiskUsageTemplate.getName());
        newTemplate.setResourceType(resourceType);
        newTemplate.setPriority(AlertPriority.MEDIUM);
        newTemplate.setConditionExpression(BooleanExpression.ANY);
        newTemplate.setDescription(storageNodeHighDiskUsageTemplate.getDescription());
        newTemplate.setRecoveryId(0);
        newTemplate.setEnabled(true);

        AlertCondition dataDiskUsedAlertCondition = new AlertCondition();
        dataDiskUsedAlertCondition.setCategory(AlertConditionCategory.THRESHOLD);
        dataDiskUsedAlertCondition.setComparator(">");
        dataDiskUsedAlertCondition.setThreshold(0.5D);

        AlertCondition totalDiskUsedAlertCondition = new AlertCondition();
        totalDiskUsedAlertCondition.setCategory(AlertConditionCategory.THRESHOLD);
        totalDiskUsedAlertCondition.setComparator(">");
        totalDiskUsedAlertCondition.setThreshold(0.75D);

        AlertCondition freeSpaveDataRatioAlertCondition = new AlertCondition();
        freeSpaveDataRatioAlertCondition.setCategory(AlertConditionCategory.THRESHOLD);
        freeSpaveDataRatioAlertCondition.setComparator("<");
        freeSpaveDataRatioAlertCondition.setThreshold(1.5D);

        List<Integer> measurementDefinitionIds = new ArrayList<Integer>(1);
        for (MeasurementDefinition d : resourceType.getMetricDefinitions()) {
            if (DATA_DISK_USED_PERCENTAGE_METRIC_NAME.equals(d.getName())) {
                measurementDefinitionIds.add(d.getId());
                dataDiskUsedAlertCondition.setMeasurementDefinition(d);
                dataDiskUsedAlertCondition.setName(d.getDisplayName());
            } else if (TOTAL_DISK_USED_PERCENTAGE_METRIC_NAME.equals(d.getName())) {
                measurementDefinitionIds.add(d.getId());
                totalDiskUsedAlertCondition.setMeasurementDefinition(d);
                totalDiskUsedAlertCondition.setName(d.getDisplayName());
            } else if (FREE_DISK_TO_DATA_SIZE_RATIO_METRIC_NAME.equals(d.getName())) {
                measurementDefinitionIds.add(d.getId());
                freeSpaveDataRatioAlertCondition.setMeasurementDefinition(d);
                freeSpaveDataRatioAlertCondition.setName(d.getDisplayName());
            }
        }

        newTemplate.addCondition(dataDiskUsedAlertCondition);
        newTemplate.addCondition(totalDiskUsedAlertCondition);
        newTemplate.addCondition(freeSpaveDataRatioAlertCondition);

        AlertDampening dampener = new AlertDampening(AlertDampening.Category.PARTIAL_COUNT);
        dampener.setPeriod(15);
        dampener.setPeriodUnits(TimeUnits.MINUTES);
        dampener.setValue(10);
        newTemplate.setAlertDampening(dampener);

        int newTemplateId = alertTemplateManager.createAlertTemplate(subjectManager.getOverlord(), newTemplate,
                resourceType.getId());

        // additionally, we want to ensure that the metric is enabled and collecting at a more frequent interval than
        // is set by default.
        MeasurementScheduleManagerLocal measurementManager = LookupUtil.getMeasurementScheduleManager();
        measurementManager.updateDefaultCollectionIntervalAndEnablementForMeasurementDefinitions(
                subjectManager.getOverlord(),
                ArrayUtils.toPrimitive(
                        measurementDefinitionIds.toArray(new Integer[measurementDefinitionIds.size()])),
                60000L, true, true);

        return newTemplateId;
    }

    private int injectStorageNodeSnapshotFailureTemplate(ResourceType resourceType) {
        AlertTemplateManagerLocal alertTemplateManager = LookupUtil.getAlertTemplateManager();
        SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();

        AlertDefinition newTemplate = new AlertDefinition();
        newTemplate.setName(storageNodeSnapshotFailureTemplate.getName());
        newTemplate.setResourceType(resourceType);
        newTemplate.setPriority(AlertPriority.MEDIUM);
        newTemplate.setConditionExpression(BooleanExpression.ANY);
        newTemplate.setDescription(storageNodeSnapshotFailureTemplate.getDescription());
        newTemplate.setRecoveryId(0);
        newTemplate.setEnabled(true);

        AlertCondition snapshotFailureCondition = new AlertCondition();
        snapshotFailureCondition.setCategory(AlertConditionCategory.CONTROL);
        snapshotFailureCondition.setName(TAKE_SNAPSHOT_OPERATION_NAME);
        snapshotFailureCondition.setOption(OperationRequestStatus.FAILURE.name());
        newTemplate.addCondition(snapshotFailureCondition);

        AlertDampening dampener = new AlertDampening(AlertDampening.Category.NONE);
        newTemplate.setAlertDampening(dampener);

        int newTemplateId = alertTemplateManager.createAlertTemplate(subjectManager.getOverlord(), newTemplate,
                resourceType.getId());

        return newTemplateId;
    }

    private int injectStorageNodeMaintenanceOperationsFailureTemplate(ResourceType resourceType) {
        AlertTemplateManagerLocal alertTemplateManager = LookupUtil.getAlertTemplateManager();
        SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();

        AlertDefinition newTemplate = new AlertDefinition();
        newTemplate.setName(storageNodeMaintenanceOperationsFailureTemplate.getName());
        newTemplate.setResourceType(resourceType);
        newTemplate.setPriority(AlertPriority.MEDIUM);
        newTemplate.setConditionExpression(BooleanExpression.ANY);
        newTemplate.setDescription(storageNodeMaintenanceOperationsFailureTemplate.getDescription());
        newTemplate.setRecoveryId(0);
        newTemplate.setEnabled(true);

        for (String operation : MAINTENANCE_OPERATIONS) {
            AlertCondition snapshotFailureCondition = new AlertCondition();
            snapshotFailureCondition.setCategory(AlertConditionCategory.CONTROL);
            snapshotFailureCondition.setName(operation);
            snapshotFailureCondition.setOption(OperationRequestStatus.FAILURE.name());
            newTemplate.addCondition(snapshotFailureCondition);
        }

        AlertDampening dampener = new AlertDampening(AlertDampening.Category.NONE);
        newTemplate.setAlertDampening(dampener);

        int newTemplateId = alertTemplateManager.createAlertTemplate(subjectManager.getOverlord(), newTemplate,
                resourceType.getId());

        return newTemplateId;
    }

    private static class InjectedTemplate {
        static public final String FIELD_PLUGIN_NAME = "plugin";
        static public final String FIELD_RESOURCE_TYPE_NAME = "type";
        static public final String FIELD_NAME = "name";
        static public final String FIELD_DESCRIPTION = "description";

        private String pluginName;
        private String resourceTypeName;
        private String name;
        private String description;

        public InjectedTemplate(String pluginName, String resourceTypeName, String name, String description) {
            super();
            this.pluginName = pluginName;
            this.resourceTypeName = resourceTypeName;
            this.name = name;
            this.description = description;
        }

        public String getPluginName() {
            return pluginName;
        }

        public String getResourceTypeName() {
            return resourceTypeName;
        }

        public String getName() {
            return name;
        }

        public String getDescription() {
            return description;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            result = prime * result + ((pluginName == null) ? 0 : pluginName.hashCode());
            result = prime * result + ((resourceTypeName == null) ? 0 : resourceTypeName.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            InjectedTemplate other = (InjectedTemplate) obj;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            if (pluginName == null) {
                if (other.pluginName != null)
                    return false;
            } else if (!pluginName.equals(other.pluginName))
                return false;
            if (resourceTypeName == null) {
                if (other.resourceTypeName != null)
                    return false;
            } else if (!resourceTypeName.equals(other.resourceTypeName))
                return false;
            return true;
        }

        @Override
        public String toString() {
            return "InjectedAlertDef [pluginName=" + pluginName + ", resourceTypeName=" + resourceTypeName
                    + ", name=" + name + "]";
        }
    }

}