diff options
| author | Selvasundaram <selvam@gluster.com> | 2011-07-25 14:54:50 +0530 |
|---|---|---|
| committer | Selvasundaram <selvam@gluster.com> | 2011-07-25 14:54:50 +0530 |
| commit | 0662fff71691bfcb0e667d7ffb4f9e057c2860be (patch) | |
| tree | a21ffe346d8f76bf7919299bfc72241fd80c7eda | |
| parent | f887ca2e1b69874117ce930771f837a6776bd94d (diff) | |
| parent | a2a52d53ee2e0dd32b993c112200cfd1c927aafa (diff) | |
Merge branch 'master' of github.com:gluster/console
15 files changed, 602 insertions, 224 deletions
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java index 8be5beac..ee29c353 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterServersClient.java @@ -85,15 +85,24 @@ public class GlusterServersClient extends AbstractClient { deleteSubResource(serverName); } - public ServerStats getCPUStats(String serverName) { + public ServerStats getCpuStats(String serverName, String period) { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add(RESTConstants.QUERY_PARAM_TYPE, RESTConstants.STATISTICS_TYPE_CPU); + queryParams.add(RESTConstants.QUERY_PARAM_PERIOD, period); return fetchSubResource(serverName + "/" + RESTConstants.RESOURCE_STATISTICS, queryParams, ServerStats.class); } - public ServerStats getAggregatedCPUStats() { + public ServerStats getAggregatedCpuStats(String period) { MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); queryParams.add(RESTConstants.QUERY_PARAM_TYPE, RESTConstants.STATISTICS_TYPE_CPU); + queryParams.add(RESTConstants.QUERY_PARAM_PERIOD, period); + return fetchSubResource(RESTConstants.RESOURCE_STATISTICS, queryParams, ServerStats.class); + } + + public ServerStats getAggregatedNetworkStats(String period) { + MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl(); + queryParams.add(RESTConstants.QUERY_PARAM_TYPE, RESTConstants.STATISTICS_TYPE_NETWORK); + queryParams.add(RESTConstants.QUERY_PARAM_PERIOD, period); return fetchSubResource(RESTConstants.RESOURCE_STATISTICS, queryParams, ServerStats.class); } } diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java index d4b0e43a..edf3bbe4 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java @@ -100,6 +100,8 @@ public class RESTConstants { public static final String QUERY_PARAM_SERVER_NAME = "serverName"; public static final String QUERY_PARAM_DETAILS = "details"; public static final String QUERY_PARAM_TYPE = "type"; + public static final String QUERY_PARAM_PERIOD = "period"; + public static final String QUERY_PARAM_INTERFACE = "interface"; public static final String STATISTICS_TYPE_CPU = "cpu"; public static final String STATISTICS_TYPE_NETWORK = "network"; diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java index 58faef02..67aeeeda 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Cluster.java @@ -30,6 +30,8 @@ public class Cluster extends Entity { List<Volume> volumes = new ArrayList<Volume>(); List<TaskInfo> taskInfoList = new ArrayList<TaskInfo>(); List<Alert> alerts = new ArrayList<Alert>(); + ServerStats aggregatedCpuStats; + ServerStats aggregatedNetworkStats; public Cluster() { } @@ -175,4 +177,20 @@ public class Cluster extends Entity { } return null; } + + public ServerStats getAggregatedCpuStats() { + return aggregatedCpuStats; + } + + public void setAggregatedCpuStats(ServerStats aggregatedCpuStats) { + this.aggregatedCpuStats = aggregatedCpuStats; + } + + public ServerStats getAggregatedNetworkStats() { + return aggregatedNetworkStats; + } + + public void setAggregatedNetworkStats(ServerStats aggregatedNetworkStats) { + this.aggregatedNetworkStats = aggregatedNetworkStats; + } } diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterDataModelManager.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterDataModelManager.java index 8c5c540c..14086260 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterDataModelManager.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/GlusterDataModelManager.java @@ -26,6 +26,7 @@ import java.util.Set; import org.apache.log4j.Logger; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.preference.IPreferenceStore; import com.gluster.storage.management.client.DiscoveredServersClient; import com.gluster.storage.management.client.GlusterServersClient; @@ -33,6 +34,7 @@ import com.gluster.storage.management.client.TasksClient; import com.gluster.storage.management.client.VolumesClient; import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; import com.gluster.storage.management.core.model.Alert; +import com.gluster.storage.management.core.model.Alert.ALERT_TYPES; import com.gluster.storage.management.core.model.Brick; import com.gluster.storage.management.core.model.Cluster; import com.gluster.storage.management.core.model.ClusterListener; @@ -57,6 +59,7 @@ import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; import com.gluster.storage.management.core.model.VolumeOptionInfo; import com.gluster.storage.management.core.utils.GlusterCoreUtil; +import com.gluster.storage.management.gui.preferences.PreferenceConstants; public class GlusterDataModelManager { private static GlusterDataModelManager instance = new GlusterDataModelManager(); @@ -117,6 +120,16 @@ public class GlusterDataModelManager { volumeChanged(oldVolume, newVolume); } } + + private boolean isCancelled(IProgressMonitor monitor) { + if(monitor.isCanceled()) { + monitor.setTaskName("Data sync cancelled!"); + monitor.done(); + return true; + } else { + return false; + } + } public GlusterDataModel fetchModel(IProgressMonitor monitor) { synchronized (syncInProgress) { @@ -133,23 +146,46 @@ public class GlusterDataModelManager { Cluster cluster = new Cluster(clusterName, model); model.addCluster(cluster); - monitor.beginTask("Data Sync", 4); + monitor.beginTask("Data Sync", 6); monitor.setTaskName("Syncing servers..."); initializeGlusterServers(cluster); monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } monitor.setTaskName("Syncing volumes..."); initializeVolumes(cluster); monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } monitor.setTaskName("Syncing discovered servers..."); initializeAutoDiscoveredServers(cluster); monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } monitor.setTaskName("Syncing tasks..."); initializeTasks(cluster); monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } + + monitor.setTaskName("Syncing aggregated CPU stats..."); + initializeAggregatedCpuStats(cluster); + monitor.worked(1); + if(isCancelled(monitor)) { + return model; + } + + monitor.setTaskName("Syncing aggregated Network stats..."); + initializeAggregatedNetworkStats(cluster); + monitor.worked(1); monitor.done(); return model; @@ -390,12 +426,26 @@ public class GlusterDataModelManager { this.volumeOptionsDefaults = new VolumesClient(clusterName).getVolumeOptionsDefaults(); } - public void initializeTasks(Cluster cluster) { + private void initializeTasks(Cluster cluster) { List<TaskInfo> taskInfoList = new TasksClient(cluster.getName()).getAllTasks(); //List<TaskInfo> taskInfoList = getDummyTasks(); cluster.setTaskInfoList(taskInfoList); } + private void initializeAggregatedCpuStats(Cluster cluster) { + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_CHART_PERIOD); + + cluster.setAggregatedCpuStats(new GlusterServersClient().getAggregatedCpuStats(cpuStatsPeriod)); + } + + private void initializeAggregatedNetworkStats(Cluster cluster) { + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_CHART_PERIOD); + + cluster.setAggregatedNetworkStats(new GlusterServersClient().getAggregatedNetworkStats(networkStatsPeriod)); + } + private List<TaskInfo> getDummyTasks() { List<TaskInfo> taskInfoList = new ArrayList<TaskInfo>(); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ChartsPreferencePage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ChartsPreferencePage.java index e1a54081..3dd636f1 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ChartsPreferencePage.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/preferences/ChartsPreferencePage.java @@ -25,7 +25,6 @@ import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; /** - * @author root * */ public class ChartsPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ChartViewerComposite.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ChartViewerComposite.java index f7ebd0ec..f2735380 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ChartViewerComposite.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/utils/ChartViewerComposite.java @@ -213,7 +213,7 @@ public final class ChartViewerComposite extends Composite implements PaintListen DateTimeDataElement dtde1 = DateTimeDataElementImpl.create(timestamps[0]); xAxisPrimary.getScale().setMax(dtde); xAxisPrimary.getScale().setStep((dtde.getValue() - dtde1.getValue())/ 10); - xAxisPrimary.getScale().setMajorGridsStepNumber(timestamps.length / 10); + xAxisPrimary.getScale().setMajorGridsStepNumber(timestamps.length > 10 ? timestamps.length / 10 : 1); //xAxisPrimary.getMajorGrid().setTickStyle(TickStyle.ABOVE_LITERAL); xAxisPrimary.getMajorGrid().getTickAttributes().setVisible(false); xAxisPrimary.getMajorGrid().setLineAttributes(LineAttributesImpl.create(ColorDefinitionImpl.GREY(), LineStyle.SOLID_LITERAL, 1)); diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java index 8f2288ec..51b8f4da 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/ClusterSummaryView.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.birt.chart.util.CDateTime; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.graphics.Image; @@ -53,9 +54,11 @@ import com.gluster.storage.management.core.model.ServerStats; import com.gluster.storage.management.core.model.ServerStatsRow; import com.gluster.storage.management.core.model.TaskInfo; import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.Activator; import com.gluster.storage.management.gui.GlusterDataModelManager; import com.gluster.storage.management.gui.IImageKeys; import com.gluster.storage.management.gui.actions.IActionConstants; +import com.gluster.storage.management.gui.preferences.PreferenceConstants; import com.gluster.storage.management.gui.utils.ChartViewerComposite; import com.gluster.storage.management.gui.utils.GUIHelper; import com.ibm.icu.util.Calendar; @@ -239,7 +242,6 @@ public class ClusterSummaryView extends ViewPart { createDiskSpaceSection(); createCPUUsageSection(); createNetworkUsageSection(); - //createMemoryUsageSection(); createActionsSection(); createAlertsSection(); createRunningTasksSection(); @@ -247,31 +249,24 @@ public class ClusterSummaryView extends ViewPart { parent.layout(); // IMP: lays out the form properly } - private void createCPUUsageSection() { - ServerStats stats; - try { - stats = new GlusterServersClient().getAggregatedCPUStats(); - } catch(Exception e) { + private void createAreaChartSection(ServerStats stats, String sectionTitle, int dataColumnIndex, String unit) { + Composite section = guiHelper.createSection(form, toolkit, sectionTitle, null, 1, false); + + List<Calendar> timestamps = new ArrayList<Calendar>(); + List<Double> data = new ArrayList<Double>(); + extractChartData(stats, timestamps, data, dataColumnIndex); + + if(timestamps.size() == 0) { + toolkit.createLabel(section, "Server statistics not available!\n Please check if all services are running properly on the cluster servers."); return; } - - Composite section = guiHelper.createSection(form, toolkit, "CPU Usage (aggregated)", null, 1, false); + if (cluster.getServers().size() == 0) { toolkit.createLabel(section, "This section will be populated after at least\none server is added to the storage cloud."); return; } - List<Calendar> timestamps = new ArrayList<Calendar>(); - List<Double> data = new ArrayList<Double>(); - for(ServerStatsRow row : stats.getRows()) { - // in case of CPU usage, there are three elements in usage data: user, system and total. we use total. - Double cpuUsage = row.getUsageData().get(2); - if(!cpuUsage.isNaN()) { - timestamps.add(new CDateTime(row.getTimestamp() * 1000)); - data.add(cpuUsage); - } - } - createLineChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), "%"); + createLineChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit); // Calendar[] timestamps = new Calendar[] { new CDateTime(1000l*1310468100), new CDateTime(1000l*1310468400), new CDateTime(1000l*1310468700), // new CDateTime(1000l*1310469000), new CDateTime(1000l*1310469300), new CDateTime(1000l*1310469600), new CDateTime(1000l*1310469900), @@ -285,25 +280,24 @@ public class ClusterSummaryView extends ViewPart { createChartLinks(section, 4); } + private void createCPUUsageSection() { + // in case of CPU usage, there are three elements in usage data: user, system and total. we use total. + createAreaChartSection(cluster.getAggregatedCpuStats(), "CPU Usage (Aggregated)", 2, "%"); + } + + private void extractChartData(ServerStats stats, List<Calendar> timestamps, List<Double> data, int dataColumnIndex) { + for(ServerStatsRow row : stats.getRows()) { + Double cpuUsage = row.getUsageData().get(dataColumnIndex); + if(!cpuUsage.isNaN()) { + timestamps.add(new CDateTime(row.getTimestamp() * 1000)); + data.add(cpuUsage); + } + } + } + private void createNetworkUsageSection() { - Composite section = guiHelper.createSection(form, toolkit, "Network Usage (Aggregated)", null, 1, false); - //toolkit.createLabel(section, "Historical Network Usage graph will be displayed here."); - - Calendar[] timestamps = new Calendar[] { new CDateTime(1000l*1310468100), new CDateTime(1000l*1310468400), new CDateTime(1000l*1310468700), - new CDateTime(1000l*1310469000), new CDateTime(1000l*1310469300), new CDateTime(1000l*1310469600), new CDateTime(1000l*1310469900), - new CDateTime(1000l*1310470200), new CDateTime(1000l*1310470500), new CDateTime(1000l*1310470800), new CDateTime(1000l*1310471100), - new CDateTime(1000l*1310471400), new CDateTime(1000l*1310471700), new CDateTime(1000l*1310472000), new CDateTime(1000l*1310472300), - new CDateTime(1000l*1310472600), new CDateTime(1000l*1310472900), new CDateTime(1000l*1310473200), new CDateTime(1000l*1310473500), - new CDateTime(1000l*1310473800) }; -// Date[] timestamps = new Date[] { new Date(1310468100), new Date(1310468400), new Date(1310468700), -// new Date(1310469000), new Date(1310469300), new Date(1310469600), new Date(1310469900), -// new Date(1310470200), new Date(1310470500), new Date(1310470800), new Date(1310471100), -// new Date(1310471400), new Date(1310471700), new Date(1310472000), new Date(1310472300), -// new Date(1310472600), new Date(1310472900), new Date(1310473200), new Date(1310473500), -// new Date(1310473800) }; - Double[] values = new Double[] { 32d, 31.23d, 27.92d, 48.69d, 58.62d, 49.11d, 72.43d, 69.31d, 87.39d, 78.46d, 60.44d, 56.28d, 33.51d, 27.53d, 12.21, 10d, 21.43d, 36.45d, 34.86d, 35.27d }; - createLineChart(section, timestamps, values, "KiB/s"); - createChartLinks(section, 4); + // in case of network usage, there are three elements in usage data: received, transmitted and total. we use total. + createAreaChartSection(cluster.getAggregatedNetworkStats(), "Network Usage (Aggregated)", 2, "KiB/s"); } private void createRunningTasksSection() { diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java index 498c9fe0..dfbafa70 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/GlusterServerSummaryView.java @@ -23,8 +23,10 @@ package com.gluster.storage.management.gui.views; import java.util.ArrayList; import java.util.List; +import org.apache.log4j.Logger; import org.eclipse.birt.chart.util.CDateTime; import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.TableViewer; @@ -46,15 +48,20 @@ import org.eclipse.ui.forms.widgets.Hyperlink; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.part.ViewPart; +import com.gluster.storage.management.client.GlusterServersClient; import com.gluster.storage.management.core.model.ClusterListener; import com.gluster.storage.management.core.model.DefaultClusterListener; import com.gluster.storage.management.core.model.Event; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; import com.gluster.storage.management.core.utils.NumberUtil; +import com.gluster.storage.management.gui.Activator; import com.gluster.storage.management.gui.GlusterDataModelManager; import com.gluster.storage.management.gui.IImageKeys; import com.gluster.storage.management.gui.NetworkInterfaceTableLabelProvider; +import com.gluster.storage.management.gui.preferences.PreferenceConstants; import com.gluster.storage.management.gui.toolbar.GlusterToolbarManager; import com.gluster.storage.management.gui.utils.ChartViewerComposite; import com.gluster.storage.management.gui.utils.GUIHelper; @@ -69,6 +76,7 @@ public class GlusterServerSummaryView extends ViewPart { private GlusterServer server; private ClusterListener serverChangedListener; private static final int CHART_WIDTH = 350; + private static final Logger logger = Logger.getLogger(GlusterServerSummaryView.class); public enum NETWORK_INTERFACE_TABLE_COLUMN_INDICES { INTERFACE, MODEL, SPEED, IP_ADDRESS, NETMASK, GATEWAY @@ -154,34 +162,55 @@ public class GlusterServerSummaryView extends ViewPart { interfaceCombo.select(0); } - - private void createCPUUsageSection() { - Composite section = guiHelper.createSection(form, toolkit, "CPU Usage", null, 1, false); - //toolkit.createLabel(section, "Historical CPU Usage graph aggregated across\nall servers will be displayed here."); + private void extractChartData(ServerStats stats, List<Calendar> timestamps, List<Double> data, int dataColumnIndex) { + for(ServerStatsRow row : stats.getRows()) { + Double cpuUsage = row.getUsageData().get(dataColumnIndex); + if(!cpuUsage.isNaN()) { + timestamps.add(new CDateTime(row.getTimestamp() * 1000)); + data.add(cpuUsage); + } + } + } - Calendar[] timestamps = new Calendar[] { new CDateTime(1000l*1310468100), new CDateTime(1000l*1310468400), new CDateTime(1000l*1310468700), - new CDateTime(1000l*1310469000), new CDateTime(1000l*1310469300), new CDateTime(1000l*1310469600), new CDateTime(1000l*1310469900), - new CDateTime(1000l*1310470200), new CDateTime(1000l*1310470500), new CDateTime(1000l*1310470800), new CDateTime(1000l*1310471100), - new CDateTime(1000l*1310471400), new CDateTime(1000l*1310471700), new CDateTime(1000l*1310472000), new CDateTime(1000l*1310472300), - new CDateTime(1000l*1310472600), new CDateTime(1000l*1310472900), new CDateTime(1000l*1310473200), new CDateTime(1000l*1310473500), - new CDateTime(1000l*1310473800) }; - //Double[] values = new Double[] { 10d, 11.23d, 17.92d, 18.69d, 78.62d, 89.11d, 92.43d, 20.31d, 19.63d, 18.46d, 10.44d, 16.28d, 13.51d, 17.53d, 12.21, 20d, 40d, 10d, 90d, 40d }; - Double[] values = new Double[] { 10d, 11.23d, 17.92d, 18.69d, 78.62d, 89.11d, 92.43d, 89.31d, 57.39d, 18.46d, 10.44d, 16.28d, 13.51d, 17.53d, 12.21, 20d, 21.43d, 16.45d, 14.86d, 15.27d }; - createLineChart(section, timestamps, values, "%"); + private void createAreaChartSection(ServerStats stats, String sectionTitle, int dataColumnIndex, String unit) { + List<Calendar> timestamps = new ArrayList<Calendar>(); + List<Double> data = new ArrayList<Double>(); + extractChartData(stats, timestamps, data, dataColumnIndex); -// ServerStats stats = new GlusterServersClient().getAggregatedCPUStats(); -// List<Calendar> timestamps = new ArrayList<Calendar>(); -// List<Double> data = new ArrayList<Double>(); -// for(ServerStatsRow row : stats.getRows()) { -// timestamps.add(new CDateTime(row.getTimestamp() * 1000)); -// // in case of CPU usage, there are three elements in usage data: user, system and total. we use total. -// data.add(row.getUsageData().get(2)); -// } + if(timestamps.size() == 0) { + // Log a message saying no CPU stats available + return; + } + + Composite section = guiHelper.createSection(form, toolkit, sectionTitle, null, 1, false); + createLineChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit); + +// Calendar[] timestamps = new Calendar[] { new CDateTime(1000l*1310468100), new CDateTime(1000l*1310468400), new CDateTime(1000l*1310468700), +// new CDateTime(1000l*1310469000), new CDateTime(1000l*1310469300), new CDateTime(1000l*1310469600), new CDateTime(1000l*1310469900), +// new CDateTime(1000l*1310470200), new CDateTime(1000l*1310470500), new CDateTime(1000l*1310470800), new CDateTime(1000l*1310471100), +// new CDateTime(1000l*1310471400), new CDateTime(1000l*1310471700), new CDateTime(1000l*1310472000), new CDateTime(1000l*1310472300), +// new CDateTime(1000l*1310472600), new CDateTime(1000l*1310472900), new CDateTime(1000l*1310473200), new CDateTime(1000l*1310473500), +// new CDateTime(1000l*1310473800) }; // -// createLineChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0])); +// Double[] values = new Double[] { 10d, 11.23d, 17.92d, 18.69d, 78.62d, 89.11d, 92.43d, 89.31d, 57.39d, 18.46d, 10.44d, 16.28d, 13.51d, 17.53d, 12.21, 20d, 21.43d, 16.45d, 14.86d, 15.27d }; +// createLineChart(section, timestamps, values, "%"); createChartLinks(section, 4); } + private void createCPUUsageSection() { + IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); + String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_CHART_PERIOD); + + try { + ServerStats stats = new GlusterServersClient().getCpuStats(server.getName(), cpuStatsPeriod); + // in case of CPU usage, there are three elements in usage data: user, system and total. we use total. + createAreaChartSection(stats, "CPU Usage", 2, "%"); + } catch(Exception e) { + logger.error("Couldn't fetch CPU usage statistics for server [" + server.getName() + "]", e); + return; + } + } + private Composite createChartLinks(Composite section, int columnCount) { GridLayout layout = new org.eclipse.swt.layout.GridLayout(columnCount, false); layout.marginBottom = 0; diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java index 28cf419d..e3332648 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java @@ -24,6 +24,8 @@ import static com.gluster.storage.management.core.constants.RESTConstants.PATH_P import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_DISK_NAME; import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_SERVER_NAME; import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DETAILS; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_INTERFACE; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_PERIOD; import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TYPE; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DISKS; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; @@ -56,6 +58,7 @@ import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.constants.RESTConstants; import com.gluster.storage.management.core.exceptions.ConnectionException; import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.Server.SERVER_STATUS; import com.gluster.storage.management.core.model.TaskStatus; @@ -65,7 +68,11 @@ import com.gluster.storage.management.server.data.ClusterInfo; import com.gluster.storage.management.server.data.ServerInfo; import com.gluster.storage.management.server.services.ClusterService; import com.gluster.storage.management.server.tasks.InitializeDiskTask; +import com.gluster.storage.management.server.utils.CpuStatsFactory; +import com.gluster.storage.management.server.utils.MemoryStatsFactory; +import com.gluster.storage.management.server.utils.NetworkStatsFactory; import com.gluster.storage.management.server.utils.SshUtil; +import com.gluster.storage.management.server.utils.StatsFactory; import com.sun.jersey.api.core.InjectParam; import com.sun.jersey.spi.resource.Singleton; @@ -87,7 +94,16 @@ public class GlusterServersResource extends AbstractServersResource { @Autowired private SshUtil sshUtil; + + @Autowired + private CpuStatsFactory cpuStatsFactory; + @Autowired + private MemoryStatsFactory memoryStatsFactory; + + @Autowired + private NetworkStatsFactory networkStatsFactory; + protected void fetchServerDetails(GlusterServer server) { try { server.setStatus(SERVER_STATUS.ONLINE); @@ -471,51 +487,54 @@ public class GlusterServersResource extends AbstractServersResource { @Produces(MediaType.APPLICATION_XML) @Path(RESOURCE_STATISTICS) public Response getAggregatedPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_TYPE) String type) { - return getAggregaredPerformanceData(clusterName, type, MediaType.APPLICATION_XML); + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { + return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_XML); } @GET @Produces(MediaType.APPLICATION_JSON) @Path(RESOURCE_STATISTICS) public Response getAggregaredPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_TYPE) String type) { - return getAggregaredPerformanceData(clusterName, type, MediaType.APPLICATION_JSON); + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { + return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_JSON); } @GET @Produces(MediaType.APPLICATION_XML) @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) - public Response getPerformanceDataXML(@PathParam(PATH_PARAM_SERVER_NAME) String serverName, @QueryParam(QUERY_PARAM_TYPE) String type) { - return getPerformanceData(serverName, type, MediaType.APPLICATION_XML); + public Response getPerformanceDataXML(@PathParam(PATH_PARAM_SERVER_NAME) String serverName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, + @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { + return getPerformanceData(serverName, type, period, networkInterface, MediaType.APPLICATION_XML); } @GET @Produces(MediaType.APPLICATION_JSON) @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) - public Response getPerformanceDataJSON(@PathParam(PATH_PARAM_SERVER_NAME) String serverName, @QueryParam(QUERY_PARAM_TYPE) String type) { - return getPerformanceData(serverName, type, MediaType.APPLICATION_JSON); + public Response getPerformanceDataJSON(@PathParam(PATH_PARAM_SERVER_NAME) String serverName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, + @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { + return getPerformanceData(serverName, type, period, networkInterface, MediaType.APPLICATION_JSON); } - private Response getAggregaredPerformanceData(String clusterName, String type, String mediaType) { + private Response getAggregaredPerformanceData(String clusterName, String type, String period, String mediaType) { List<String> serverNames = getServerNames(getGlusterServers(clusterName, false)); - if(type.equals(STATISTICS_TYPE_CPU)) { - return okResponse(serverUtil.fetchAggregatedCPUStats(serverNames), mediaType); - } else { - return badRequestResponse("Server Statistics for [" + type + "] not supported! Valid values are [" - + STATISTICS_TYPE_CPU + ", " + STATISTICS_TYPE_NETWORK + ", " + STATISTICS_TYPE_MEMORY + "]"); - } + return okResponse(getStatsFactory(type).fetchAggregatedStats(serverNames, period), mediaType); } - private Response getPerformanceData(String serverName, String type, String mediaType) { + private Response getPerformanceData(String serverName, String type, String period, String networkInterface, String mediaType) { + return okResponse(getStatsFactory(type).fetchStats(serverName, period, networkInterface), mediaType); + } + + private StatsFactory getStatsFactory(String type) { if(type.equals(STATISTICS_TYPE_CPU)) { - return okResponse(serverUtil.fetchCPUUsageData(serverName), mediaType); - } else if(type.equals(STATISTICS_TYPE_NETWORK)) { - return okResponse(serverUtil.fetchCPUUsageData(serverName), mediaType); + return cpuStatsFactory; } else if(type.equals(STATISTICS_TYPE_MEMORY)) { - return okResponse(serverUtil.fetchCPUUsageData(serverName), mediaType); + return memoryStatsFactory; + } else if(type.equals(STATISTICS_TYPE_NETWORK)) { + return networkStatsFactory; } else { - return badRequestResponse("Server Statistics for [" + type + "] not supported! Valid values are [" + throw new GlusterValidationException("Invalid server statistics type [" + type + "]. Valid values are [" + STATISTICS_TYPE_CPU + ", " + STATISTICS_TYPE_NETWORK + ", " + STATISTICS_TYPE_MEMORY + "]"); } } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/AbstractStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/AbstractStatsFactory.java new file mode 100644 index 00000000..820cc542 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/AbstractStatsFactory.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.server.utils; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; +import com.gluster.storage.management.core.model.Status; + +/** + * + */ +@Component +public abstract class AbstractStatsFactory implements StatsFactory { + @Autowired + protected ServerUtil serverUtil; + + private Logger logger = Logger.getLogger(AbstractStatsFactory.class); + + protected ServerStats getFirstOnlineServerStats(List<String> serverNames, String period, + boolean removeServerOnError, boolean removeOnlineServer) { + for(int i = serverNames.size() - 1; i >= 0; i--) { + String serverName = serverNames.get(i); + try { + ServerStats stats = fetchStats(serverName, period); + if(removeOnlineServer) { + serverNames.remove(serverName); + } + return stats; + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch CPU stats from server [" + serverName + "]!", e); + if(removeServerOnError) { + serverNames.remove(serverName); + } + continue; + } + } + throw new GlusterRuntimeException("All servers offline!"); + } + + protected void aggregateStats(List<String> serverNames, ServerStats aggregatedStats, String period) { + if(serverNames.isEmpty()) { + return; + } + + int rowCount = aggregatedStats.getMetadata().getRowCount(); + int columnCount = aggregatedStats.getMetadata().getLegend().size(); + int[][] dataCount = initDataCountArray(rowCount, columnCount); + + for (String serverName : serverNames) { + try { + // fetch the stats and add to aggregated stats + addServerStats(fetchStats(serverName, period), aggregatedStats, dataCount); + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch CPU stats from server [" + serverName + "]!", e); + continue; + } + } + + averageAggregatedStats(aggregatedStats, dataCount); + } + + /** + * + * @param statsToBeAdded + * @param targetStats + * @param dataCount Each element of this matrix will be incremented for every valid element added + * @return + */ + protected List<ServerStatsRow> addServerStats(ServerStats statsToBeAdded, ServerStats targetStats, int[][] dataCount) { + List<ServerStatsRow> serverStatsRows = statsToBeAdded.getRows(); + for (int rowNum = 0; rowNum < serverStatsRows.size() + && rowNum < targetStats.getMetadata().getRowCount(); rowNum++) { + ServerStatsRow row = serverStatsRows.get(rowNum); + List<Double> rowData = row.getUsageData(); + + List<Double> aggregatedStatsRowData = targetStats.getRows().get(rowNum).getUsageData(); + for(int i = 1; i < targetStats.getMetadata().getLegend().size(); i++) { + // Add the data + Double data = rowData.get(i); + if(!data.isNaN()) { + // data is available. add it. + aggregatedStatsRowData.set(i, aggregatedStatsRowData.get(i) + data); + // increment record count. this will be used for calculating average of aggregated data. + dataCount[rowNum][i]++; + } + } + } + return serverStatsRows; + } + + protected void averageAggregatedStats(ServerStats aggregatedStats, int[][] dataCount) { + List<ServerStatsRow> rows = aggregatedStats.getRows(); + for(int rowNum = 0; rowNum < rows.size(); rowNum++) { + List<Double> data = rows.get(rowNum).getUsageData(); + for(int columnNum = 0; columnNum < data.size(); columnNum++) { + data.set(columnNum, data.get(columnNum) / dataCount[rowNum][columnNum]); + } + } + } + + protected int[][] initDataCountArray(int rowCount, int columnCount) { + int[][] dataCount = new int[rowCount][columnCount]; + // initialize all data counts to 1 + for(int rowNum = 0; rowNum < rowCount; rowNum++) { + for(int columnNum = 0; columnNum < columnCount; columnNum++) { + dataCount[rowNum][columnNum] = 1; + } + } + return dataCount; + } + + @Override + public ServerStats fetchAggregatedStats(List<String> serverNames, String period) { + if(serverNames == null || serverNames.size() == 0) { + throw new GlusterRuntimeException("No server names passed to fetchAggregaredCPUStats!"); + } + + ServerStats firstServerStats = getFirstOnlineServerStats(serverNames, period, true, true); + + ServerStats aggregatedStats = new ServerStats(firstServerStats); + aggregateStats(serverNames, aggregatedStats, period); + return aggregatedStats; + } + + @Override + public ServerStats fetchStats(String serverName, String period, String...args) { + String argsStr = ""; + for (String arg : args) { + if(arg != null) { + argsStr += " " + arg; + } + } + Object output = serverUtil.executeOnServer(true, serverName, getStatsScriptName() + argsStr + " " + period, ServerStats.class); + //String cpuUsageData = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <xport> <meta> <start>1310468100</start> <step>300</step> <end>1310471700</end> <rows>13</rows> <columns>3</columns> <legend> <entry>user</entry> <entry>system</entry> <entry>total</entry> </legend> </meta> <data> <row><t>1310468100</t><v>2.23802952e-1</v><v>4.3747778209e-01</v><v>6.6128073384e-01</v></row> <row><t>1310468400</t><v>2.3387347338e-01</v><v>4.4642717442e-01</v><v>6.8030064780e-01</v></row> <row><t>1310468700</t><v>5.5043873220e+00</v><v>6.2462376636e+00</v><v>1.1750624986e+01</v></row> <row><t>1310469000</t><v>2.4350593653e+01</v><v>2.6214585217e+01</v><v>5.0565178869e+01</v></row> <row><t>1310469300</t><v>4.0786489953e+01</v><v>4.6784713828e+01</v><v>8.7571203781e+01</v></row> <row><t>1310469600</t><v>4.1459955508e+01</v><v>5.2546309044e+01</v><v>9.4006264551e+01</v></row> <row><t>1310469900</t><v>4.2312286165e+01</v><v>5.2390588332e+01</v><v>9.4702874497e+01</v></row> <row><t>1310470200</t><v>4.2603794982e+01</v><v>5.1598861493e+01</v><v>9.4202656475e+01</v></row> <row><t>1310470500</t><v>3.8238751290e+01</v><v>4.5312089966e+01</v><v>8.3550841256e+01</v></row> <row><t>1310470800</t><v>1.7949961224e+01</v><v>2.1282058418e+01</v><v>3.9232019642e+01</v></row> <row><t>1310471100</t><v>1.2330371421e-01</v><v>4.6347832868e-01</v><v>5.8678204289e-01</v></row> <row><t>1310471400</t><v>1.6313260492e-01</v><v>5.4088119561e-01</v><v>7.0401380052e-01</v></row> <row><t>1310471700</t><v>NaN</v><v>NaN</v><v>NaN</v></row> </data> </xport>"; + //Object output = unmarshal(ServerStats.class, cpuUsageData, false); + if(output instanceof Status) { + throw new GlusterRuntimeException(((Status)output).toString()); + } + return (ServerStats) output; + } + + public abstract String getStatsScriptName(); +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/CpuStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/CpuStatsFactory.java new file mode 100644 index 00000000..27e271e5 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/CpuStatsFactory.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.server.utils; + +import org.springframework.stereotype.Component; + +/** + * + */ +@Component +public class CpuStatsFactory extends AbstractStatsFactory { + + private static final String CPU_STATS_SCRIPT = "get_rrd_cpu_details.py"; + + @Override + public String getStatsScriptName() { + return CPU_STATS_SCRIPT; + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/MemoryStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/MemoryStatsFactory.java new file mode 100644 index 00000000..65f4e44e --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/MemoryStatsFactory.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.server.utils; + +import org.springframework.stereotype.Component; + +/** + * + */ +@Component +public class MemoryStatsFactory extends AbstractStatsFactory { + + private static final String MEM_STATS_SCRIPT = "get_rrd_mem_details.py"; + + @Override + public String getStatsScriptName() { + return MEM_STATS_SCRIPT; + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/NetworkStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/NetworkStatsFactory.java new file mode 100644 index 00000000..96bb0c65 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/NetworkStatsFactory.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.server.utils; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerStats; + +/** + * + */ +@Component +public class NetworkStatsFactory extends AbstractStatsFactory { + private static final Logger logger = Logger.getLogger(NetworkStatsFactory.class); + private static final String NETWORK_STATS_SCRIPT = "get_rrd_net_details.py"; + private int[][] dataCount; + + @Override + public String getStatsScriptName() { + return NETWORK_STATS_SCRIPT; + } + + @Override + protected ServerStats getFirstOnlineServerStats(List<String> serverNames, String period, + boolean removeServerOnError, boolean removeOnlineServer) { + ServerStats firstOnlineServerStats = null; + for(int i = serverNames.size() - 1; i >= 0; i--) { + String serverName = serverNames.get(i); + Server server = new Server(serverName); + serverUtil.fetchServerDetails(server); + try { + for(NetworkInterface networkInterface : server.getNetworkInterfaces()) { + ServerStats stats = fetchStats(serverName, period, networkInterface.getName()); + if(firstOnlineServerStats == null) { + firstOnlineServerStats = stats; + int rowCount = firstOnlineServerStats.getMetadata().getRowCount(); + int columnCount = firstOnlineServerStats.getMetadata().getLegend().size(); + dataCount = initDataCountArray(rowCount, columnCount); + } else { + addServerStats(stats, firstOnlineServerStats, dataCount); + } + } + + if(removeOnlineServer) { + serverNames.remove(serverName); + } + return firstOnlineServerStats; + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); + if(removeServerOnError) { + serverNames.remove(serverName); + } + continue; + } + } + throw new GlusterRuntimeException("All servers offline!"); + } + + protected void aggregateStats(List<String> serverNames, ServerStats aggregatedStats, String period) { + if(serverNames.isEmpty()) { + return; + } + + for (String serverName : serverNames) { + try { + Server server = new Server(serverName); + serverUtil.fetchServerDetails(server); + + for (NetworkInterface networkInterface : server.getNetworkInterfaces()) { + // fetch the stats and add to aggregated stats + addServerStats(fetchStats(serverName, period, networkInterface.getName()), aggregatedStats, dataCount); + } + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch Network stats from server [" + serverName + "]!", e); + continue; + } + } + + averageAggregatedStats(aggregatedStats, dataCount); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java index 871a2e9d..e4d37ad8 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java @@ -23,8 +23,6 @@ package com.gluster.storage.management.server.utils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; import java.util.List; import javax.servlet.ServletContext; @@ -40,9 +38,9 @@ import org.springframework.stereotype.Component; import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.exceptions.ConnectionException; import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.ServerStatsRow; -import com.gluster.storage.management.core.model.ServerStats; import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.response.GenericResponse; import com.gluster.storage.management.core.utils.ProcessResult; @@ -226,140 +224,24 @@ public class ServerUtil { return (Status) executeOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class); } - public ServerStats fetchCPUUsageData(String serverName) { - Object output = executeOnServer(true, serverName, "get_rrd_cpu_details.py 1d", ServerStats.class); - //String cpuUsageData = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <xport> <meta> <start>1310468100</start> <step>300</step> <end>1310471700</end> <rows>13</rows> <columns>3</columns> <legend> <entry>user</entry> <entry>system</entry> <entry>total</entry> </legend> </meta> <data> <row><t>1310468100</t><v>2.23802952e-1</v><v>4.3747778209e-01</v><v>6.6128073384e-01</v></row> <row><t>1310468400</t><v>2.3387347338e-01</v><v>4.4642717442e-01</v><v>6.8030064780e-01</v></row> <row><t>1310468700</t><v>5.5043873220e+00</v><v>6.2462376636e+00</v><v>1.1750624986e+01</v></row> <row><t>1310469000</t><v>2.4350593653e+01</v><v>2.6214585217e+01</v><v>5.0565178869e+01</v></row> <row><t>1310469300</t><v>4.0786489953e+01</v><v>4.6784713828e+01</v><v>8.7571203781e+01</v></row> <row><t>1310469600</t><v>4.1459955508e+01</v><v>5.2546309044e+01</v><v>9.4006264551e+01</v></row> <row><t>1310469900</t><v>4.2312286165e+01</v><v>5.2390588332e+01</v><v>9.4702874497e+01</v></row> <row><t>1310470200</t><v>4.2603794982e+01</v><v>5.1598861493e+01</v><v>9.4202656475e+01</v></row> <row><t>1310470500</t><v>3.8238751290e+01</v><v>4.5312089966e+01</v><v>8.3550841256e+01</v></row> <row><t>1310470800</t><v>1.7949961224e+01</v><v>2.1282058418e+01</v><v>3.9232019642e+01</v></row> <row><t>1310471100</t><v>1.2330371421e-01</v><v>4.6347832868e-01</v><v>5.8678204289e-01</v></row> <row><t>1310471400</t><v>1.6313260492e-01</v><v>5.4088119561e-01</v><v>7.0401380052e-01</v></row> <row><t>1310471700</t><v>NaN</v><v>NaN</v><v>NaN</v></row> </data> </xport>"; - //Object output = unmarshal(ServerStats.class, cpuUsageData, false); - if(output instanceof Status) { - throw new GlusterRuntimeException(((Status)output).toString()); - } - return (ServerStats) output; - } - - private ServerStats getFirstOnlineServerCPUStats(List<String> serverNames, boolean removeServerOnError, boolean removeOnlineServer) { - for(int i = serverNames.size() - 1; i >= 0; i--) { - String serverName = serverNames.get(i); - try { - ServerStats stats = fetchCPUUsageData(serverName); - if(removeOnlineServer) { - serverNames.remove(serverName); - } - return stats; - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch CPU stats from server [" + serverName + "]!", e); - if(removeServerOnError) { - serverNames.remove(serverName); - } - continue; - } - } - throw new GlusterRuntimeException("All servers offline!"); - } - - public ServerStats fetchAggregatedCPUStats(List<String> serverNames) { - if(serverNames == null || serverNames.size() == 0) { - throw new GlusterRuntimeException("No server names passed to fetchAggregaredCPUUsageData!"); - } - - ServerStats firstServerStats = getFirstOnlineServerCPUStats(serverNames, true, true); - - ServerStats aggregatedStats = new ServerStats(firstServerStats); - aggregateCPUStats(serverNames, aggregatedStats); - return aggregatedStats; - } - - private void aggregateCPUStats(List<String> serverNames, ServerStats aggregatedStats) { - if(serverNames.isEmpty()) { - return; - } - - int rowCount = aggregatedStats.getMetadata().getRowCount(); - int columnCount = aggregatedStats.getMetadata().getLegend().size(); - int[][] dataCount = initDataCountArray(rowCount, columnCount); - - for (String serverName : serverNames) { - try { - // fetch the stats and add to aggregated stats - addServerStats(fetchCPUUsageData(serverName), aggregatedStats, dataCount); - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch CPU stats from server [" + serverName + "]!", e); - continue; - } - } - - averageAggregatedStats(aggregatedStats, dataCount); - } - - private void averageAggregatedStats(ServerStats aggregatedStats, int[][] dataCount) { - List<ServerStatsRow> rows = aggregatedStats.getRows(); - for(int rowNum = 0; rowNum < rows.size(); rowNum++) { - List<Double> data = rows.get(rowNum).getUsageData(); - for(int columnNum = 0; columnNum < data.size(); columnNum++) { - data.set(columnNum, data.get(columnNum) / dataCount[rowNum][columnNum]); - } - } - } - - private int[][] initDataCountArray(int rowCount, int columnCount) { - int[][] dataCount = new int[rowCount][columnCount]; - // initialize all data counts to 1 - for(int rowNum = 0; rowNum < rowCount; rowNum++) { - for(int columnNum = 0; columnNum < columnCount; columnNum++) { - dataCount[rowNum][columnNum] = 1; - } - } - return dataCount; - } - - /** - * - * @param statsToBeAdded - * @param targetStats - * @param dataCount Each element of this matrix will be incremented for every valid element added - * @return - */ - private List<ServerStatsRow> addServerStats(ServerStats statsToBeAdded, ServerStats targetStats, int[][] dataCount) { - List<ServerStatsRow> serverStatsRows = statsToBeAdded.getRows(); - for (int rowNum = 0; rowNum < serverStatsRows.size() - && rowNum < targetStats.getMetadata().getRowCount(); rowNum++) { - ServerStatsRow row = serverStatsRows.get(rowNum); - List<Double> rowData = row.getUsageData(); - - List<Double> aggregatedStatsRowData = targetStats.getRows().get(rowNum).getUsageData(); - for(int i = 1; i < targetStats.getMetadata().getLegend().size(); i++) { - // Add the data - Double data = rowData.get(i); - if(!data.isNaN()) { - // data is available. add it. - aggregatedStatsRowData.set(i, aggregatedStatsRowData.get(i) + data); - // increment record count. this will be used for calculating average of aggregated data. - dataCount[rowNum][i]++; - } - } - } - return serverStatsRows; - } - public static void main(String[] args) { - ServerStats stats = new ServerUtil().fetchCPUUsageData("s1"); - for(ServerStatsRow row : stats.getRows()) { - System.out.println(row.getUsageData().get(2)); - } - JAXBContext context; - try { - context = JAXBContext.newInstance(ServerStats.class); - Marshaller m = context.createMarshaller(); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - m.marshal(stats, out); - ServerStats stats1 = (ServerStats)new ServerUtil().unmarshal(ServerStats.class, out.toString(), false); - for(ServerStatsRow row : stats1.getRows()) { - System.out.println(row.getUsageData().get(2)); - } - } catch (JAXBException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } +// ServerStats stats = new ServerUtil().fetchCPUUsageData("s1", "1d"); +// for(ServerStatsRow row : stats.getRows()) { +// System.out.println(row.getUsageData().get(2)); +// } +// JAXBContext context; +// try { +// context = JAXBContext.newInstance(ServerStats.class); +// Marshaller m = context.createMarshaller(); +// ByteArrayOutputStream out = new ByteArrayOutputStream(); +// m.marshal(stats, out); +// ServerStats stats1 = (ServerStats)new ServerUtil().unmarshal(ServerStats.class, out.toString(), false); +// for(ServerStatsRow row : stats1.getRows()) { +// System.out.println(row.getUsageData().get(2)); +// } +// } catch (JAXBException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } } } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/StatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/StatsFactory.java new file mode 100644 index 00000000..85487602 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/StatsFactory.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console 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 Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.server.utils; + +import java.util.List; + +import com.gluster.storage.management.core.model.ServerStats; + +/** + * + */ +public interface StatsFactory { + public ServerStats fetchStats(String serverName, String period, String...args); + public ServerStats fetchAggregatedStats(List<String> serverName, String period); +} |
