modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java | 91 +++++++++- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java | 21 ++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java | 22 ++ modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java | 2 modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java | 26 +- modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml | 4 6 files changed, 147 insertions(+), 19 deletions(-)
New commits: commit 524d1b66879fa6d20788505e1c43c0e046e06e48 Author: Stefan Negrea snegrea@redhat.com Date: Fri Jul 12 00:58:48 2013 -0500
Initial implementation for fetching all the alerts triggered for Storage Nodes resource and sub-sources.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java index 9d073ee..fa51fe1 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerBean.java @@ -28,8 +28,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Queue;
import javax.ejb.EJB; import javax.ejb.Stateless; @@ -43,6 +45,7 @@ import org.quartz.JobDataMap; import org.quartz.SimpleTrigger; import org.quartz.Trigger;
+import org.rhq.core.domain.alert.Alert; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.cloud.Server; @@ -51,6 +54,7 @@ import org.rhq.core.domain.cloud.StorageNode.OperationMode; import org.rhq.core.domain.cloud.StorageNodeLoadComposite; import org.rhq.core.domain.common.JobTrigger; import org.rhq.core.domain.configuration.Configuration; +import org.rhq.core.domain.criteria.AlertCriteria; import org.rhq.core.domain.criteria.ResourceGroupCriteria; import org.rhq.core.domain.criteria.StorageNodeCriteria; import org.rhq.core.domain.measurement.MeasurementAggregate; @@ -59,8 +63,11 @@ import org.rhq.core.domain.operation.bean.GroupOperationSchedule; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.group.ResourceGroup; +import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; +import org.rhq.core.domain.util.PageOrdering; import org.rhq.enterprise.server.RHQConstants; +import org.rhq.enterprise.server.alert.AlertManagerLocal; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.authz.RequiredPermission; import org.rhq.enterprise.server.authz.RequiredPermissions; @@ -110,6 +117,9 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN @EJB private OperationManagerLocal operationManager;
+ @EJB + private AlertManagerLocal alertManager; + @Override public void linkResource(Resource resource) { List<StorageNode> storageNodes = this.getStorageNodes(); @@ -427,7 +437,7 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN } entityManager.flush(); } - + private StorageNodeLoadComposite.MeasurementAggregateWithUnits getMeasurementAggregateWithUnits(Subject subject, int schedId, MeasurementUnits units, long beginTime, long endTime) { MeasurementAggregate measurementAggregate = measurementManager.getAggregate(subject, schedId, beginTime, @@ -472,4 +482,81 @@ public class StorageNodeManagerBean implements StorageNodeManagerLocal, StorageN
operationManager.scheduleGroupOperation(subjectManager.getOverlord(), schedule); } -} + + @Override + public PageList<Alert> findNotAcknowledgedStorageNodeAlerts(Subject subject) { + return findStorageNodeAlerts(subject, false); + } + + @Override + public PageList<Alert> findAllStorageNodeAlerts(Subject subject) { + return findStorageNodeAlerts(subject, true); + } + + /** + * Find the set of alerts related to Storage Node resources and sub-resources. + * + * @param subject subject + * @param allAlerts if [true] then return all alerts; if [false] then return only alerts that are not acknowledged + * @return alerts + */ + private PageList<Alert> findStorageNodeAlerts(Subject subject, boolean allAlerts) { + Integer[] resouceIdsWithAlertDefinitions = findResourcesWithAlertDefinitions(); + PageList<Alert> alerts = new PageList<Alert>(); + + if( resouceIdsWithAlertDefinitions != null && resouceIdsWithAlertDefinitions.length != 0 ){ + AlertCriteria criteria = new AlertCriteria(); + criteria.setPageControl(PageControl.getUnlimitedInstance()); + criteria.addFilterResourceIds(resouceIdsWithAlertDefinitions); + criteria.addSortCtime(PageOrdering.DESC); + + alerts = alertManager.findAlertsByCriteria(subject, criteria); + + if (!allAlerts) { + //select on alerts that are not acknowledge + PageList<Alert> trimmedAlerts = new PageList<Alert>(); + for (Alert alert : alerts) { + if (alert.getAcknowledgeTime() == null || alert.getAcknowledgeTime() <= 0) { + trimmedAlerts.add(alert); + } + } + + alerts = trimmedAlerts; + } + } + + return alerts; + } + + /** + * Return resource Ids for all resources and sub-resources of Storage Nodes that + * have alert definitions. This will be used by the resource criteria to find + * all alerts triggered for storage nodes. + * + * @return + */ + private Integer[] findResourcesWithAlertDefinitions() { + List<Integer> resourceIdsWithAlertDefinitions = new ArrayList<Integer>(); + List<StorageNode> test2 = getStorageNodes(); + + Queue<Resource> unvisitedResources = new LinkedList<Resource>(); + for (StorageNode node : test2) { + if (node.getResource() != null) { + unvisitedResources.add(node.getResource()); + } + } + + while(!unvisitedResources.isEmpty()){ + Resource resource = unvisitedResources.poll(); + if (resource.getAlertDefinitions() != null) { + resourceIdsWithAlertDefinitions.add(resource.getId()); + } + + for(Resource child: resource.getChildResources()){ + unvisitedResources.add(child); + } + } + + return resourceIdsWithAlertDefinitions.toArray(new Integer[resourceIdsWithAlertDefinitions.size()]); + } +} \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java index 5c3f092..a9b2514 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerLocal.java @@ -22,6 +22,7 @@ import java.util.List;
import javax.ejb.Local;
+import org.rhq.core.domain.alert.Alert; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNodeLoadComposite; @@ -65,13 +66,29 @@ public interface StorageNodeManagerLocal { * @return list of nodes */ PageList<StorageNode> findStorageNodesByCriteria(Subject subject, StorageNodeCriteria criteria); - + + /** + * Fetches the list of Storage Node related alerts that have not yet been acknowledged. + * + * @param subject subject + * @return storage nodes alerts not acknowledged + */ + PageList<Alert> findNotAcknowledgedStorageNodeAlerts(Subject subject); + + /** + * Fetches all the Storage Node related alerts. + * + * @param subject subject + * @return all storage nodes alerts + */ + PageList<Alert> findAllStorageNodeAlerts(Subject subject); + /** * <p>Prepares the node for subsequent upgrade.</p> * <p> CAUTION: this method will set the RHQ server to maintenance mode, RHQ storage flushes all the data to disk * and backup of all the keyspaces is created</p> * <p>the subject needs to have <code>MANAGE_SETTINGS</code> and <code>MANAGE_INVENTORY</code> permissions.</p> - * + * * @param subject caller * @param storageNode storage node on which the prepareForUpgrade operation should be run */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java index d4c9f78..72432db 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/StorageNodeManagerRemote.java @@ -20,6 +20,7 @@ package org.rhq.enterprise.server.cloud;
import javax.ejb.Remote;
+import org.rhq.core.domain.alert.Alert; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.cloud.StorageNodeLoadComposite; @@ -28,7 +29,7 @@ import org.rhq.core.domain.util.PageList;
/** * Remote interface to the manager responsible for creating and managing storage nodes. - * + * * @author Jirka Kremser */ @Remote @@ -36,9 +37,9 @@ public interface StorageNodeManagerRemote {
/** * <p>Returns the summary of load of the storage node.</p> - * + * * <p>the subject needs to have <code>MANAGE_SETTINGS</code> permissions.</p> - * + * * @param subject user that must have proper permissions * @param node storage node entity (it can be a new object, but the id should be set properly) * @param beginTime the start time @@ -58,4 +59,19 @@ public interface StorageNodeManagerRemote { */ PageList<StorageNode> findStorageNodesByCriteria(Subject subject, StorageNodeCriteria criteria);
+ /** + * Fetches the list of Storage Node related alerts that have not yet been acknowledged. + * + * @param subject subject + * @return storage nodes alerts not acknowledged + */ + PageList<Alert> findNotAcknowledgedStorageNodeAlerts(Subject subject); + + /** + * Fetches all the Storage Node related alerts. + * + * @param subject subject + * @return all storage nodes alerts + */ + PageList<Alert> findAllStorageNodeAlerts(Subject subject); }
commit 4674c9c66fef570a0abb3961205056fed3e75097 Author: Stefan Negrea snegrea@redhat.com Date: Thu Jul 11 14:58:52 2013 -0500
Update the calculation for the percentage of disk space used. The percentage now represents the amount of disk used by the Cassandra data files.
diff --git a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java index dcfdc37..8995ec0 100644 --- a/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java +++ b/modules/enterprise/server/plugins/alertdef-rhq/src/main/java/org/rhq/enterprise/server/plugins/alertdef/AlertDefinitionServerPluginComponent.java @@ -300,7 +300,7 @@ public class AlertDefinitionServerPluginComponent implements ServerPluginCompone AlertCondition ac = new AlertCondition(); ac.setCategory(AlertConditionCategory.THRESHOLD); ac.setComparator(">"); - ac.setThreshold(0.75D); + ac.setThreshold(0.5D);
List<Integer> measurementDefinitionIds = new ArrayList<Integer>(1); for (MeasurementDefinition d : resourceType.getMetricDefinitions()) { diff --git a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java index 7281f9b..e5a2283 100644 --- a/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java +++ b/modules/plugins/cassandra/src/main/java/org/rhq/plugins/cassandra/StorageServiceComponent.java @@ -60,6 +60,8 @@ public class StorageServiceComponent extends ComplexConfigurationResourceCompone private static final String OWNERSHIP_METRIC_NAME = "Ownership"; private static final String PARTITION_DISK_USED_PERCENTAGE_METRIC_NAME = "Calculated.PartitionDiskUsedPercentage"; private static final String DATA_FILE_LOCATIONS_NAME = "AllDataFileLocations"; + private static final String LOAD_NAME = "Load"; + private Log log = LogFactory.getLog(StorageServiceComponent.class); private InetAddress host;
@@ -178,23 +180,30 @@ public class StorageServiceComponent extends ComplexConfigurationResourceCompone } break; } else if (PARTITION_DISK_USED_PERCENTAGE_METRIC_NAME.equals(request.getName())) { - EmsAttribute attribute = bean.getAttribute(DATA_FILE_LOCATIONS_NAME); - Object valueObject = attribute.refresh(); - if (valueObject instanceof String[]) { + + + EmsAttribute loadAttribute = bean.getAttribute(LOAD_NAME); + Object loadValue = loadAttribute.refresh(); + + EmsAttribute dataFileLocationAttribute = bean.getAttribute(DATA_FILE_LOCATIONS_NAME); + Object dataFileLocationValue = dataFileLocationAttribute.refresh(); + + if (loadValue != null && dataFileLocationValue != null && dataFileLocationValue instanceof String[]) { //Please visit for details: https://issues.apache.org/jira/browse/CASSANDRA-2749 //The average usage of all partitions with the data will be reported. //Cassandra selects the partition with most free space for SStable flush and compaction. - report.addData(new MeasurementDataNumeric(request, - getPartitionDiskUsedPercentage((String[]) valueObject))); + double load = Double.parseDouble(loadValue.toString()); + + report.addData(new MeasurementDataNumeric(request, getPartitionDiskUsedPercentage(load, + (String[]) dataFileLocationValue))); } } } }
- private double getPartitionDiskUsedPercentage(String[] paths) { + private double getPartitionDiskUsedPercentage(double dataSize, String[] paths) { List<String> visitedMountPoints = new ArrayList<String>(); long totalDiskSpace = 0; - long totalUsedDiskSpace = 0;
for (String path : paths) { try { @@ -202,7 +211,6 @@ public class StorageServiceComponent extends ComplexConfigurationResourceCompone if (!visitedMountPoints.contains(fileSystemInfo.getMountPoint())) { visitedMountPoints.add(fileSystemInfo.getMountPoint()); totalDiskSpace += fileSystemInfo.getFileSystemUsage().getTotal(); - totalUsedDiskSpace += fileSystemInfo.getFileSystemUsage().getUsed(); } } catch (Exception e) { log.error("Unable to determine file system usage information for data file location " + path, e); @@ -210,7 +218,7 @@ public class StorageServiceComponent extends ComplexConfigurationResourceCompone }
if (totalDiskSpace != 0) { - double rawPercentage = ((double) totalUsedDiskSpace) / ((double) totalDiskSpace); + double rawPercentage = dataSize / ((double) totalDiskSpace); return Math.round(rawPercentage * 100.0) / 100.0; }
diff --git a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml index 3aa701b..e6bc1da 100644 --- a/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml +++ b/modules/plugins/cassandra/src/main/resources/META-INF/rhq-plugin.xml @@ -187,8 +187,8 @@ </operation>
<metric property="CurrentGenerationNumber" dataType="trait" displayType="summary" description="Current generation number"/> - <metric property="Calculated.PartitionDiskUsedPercentage" dataType="measurement" units="percentage" displayType="summary" description="Percentage of total disk space used for the partition that contains the data files. - If multiple data locations are specified then this will report the average utilization accross all the partitions."/> + <metric property="Calculated.PartitionDiskUsedPercentage" displayName="Data File Disk Used Percentage" dataType="measurement" units="percentage" displayType="summary" description="Percentage of disk space used by the data files. If multiple data locations are specified then this will report + the average utilization accross all the partitions that contain data files."/> <metric property="ExceptionCount" measurementType="trendsup" dataType="measurement" displayType="summary" description="Exception Count"/> <metric property="Initialized" dataType="trait" displayType="summary" description="Initialized"/> <metric property="Joined" dataType="trait" displayType="summary" description="Joined"/>