From d4776431b2681fc8692fd74644e255883b17dc0e Mon Sep 17 00:00:00 2001 From: Selvasundaram Date: Tue, 26 Jul 2011 16:51:05 +0530 Subject: Export key errors - bug fix --- .../storage/management/client/AbstractClient.java | 12 ++- .../storage/management/core/utils/FileUtil.java | 17 +++-- .../server/resources/v1_0/AbstractResource.java | 7 -- .../resources/v1_0/GenericExceptionMapper.java | 45 ----------- .../server/resources/v1_0/KeysResource.java | 88 +++++++++++----------- 5 files changed, 64 insertions(+), 105 deletions(-) delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java index 20582835..a45c2c2d 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/AbstractClient.java @@ -167,8 +167,18 @@ public abstract class AbstractClient { } protected void downloadResource(WebResource res, String filePath) { - ClientResponse response = res.header(HTTP_HEADER_AUTH, authHeader).accept(MediaType.APPLICATION_OCTET_STREAM) + ClientResponse response = null; + try { + response = res.header(HTTP_HEADER_AUTH, authHeader).accept(MediaType.APPLICATION_OCTET_STREAM) .get(ClientResponse.class); + if (response.getStatus() >= 300) { + throw new GlusterRuntimeException(response.getEntity(String.class)); + } + } catch (Exception e1) { + logger.error("Error in downloading resource [" + res.toString() + "]", e1); + throw createGlusterException(e1); + } + try { if (!response.hasEntity()) { throw new GlusterRuntimeException("No entity in response!"); diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java index d10dfee5..a0d90634 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/FileUtil.java @@ -39,12 +39,17 @@ public class FileUtil { } } - public static byte[] readFileAsByteArray(File file) throws FileNotFoundException, IOException { - FileInputStream fileInputStream = new FileInputStream(file); - byte[] data = new byte[fileInputStream.available()]; - fileInputStream.read(data); - fileInputStream.close(); - return data; + public static byte[] readFileAsByteArray(File file) { + try { + FileInputStream fileInputStream = new FileInputStream(file); + byte[] data = new byte[fileInputStream.available()]; + fileInputStream.read(data); + fileInputStream.close(); + return data; + } catch (Exception e) { + throw new GlusterRuntimeException("Exception while reading file [" + file.getName() + "]: " + + e.getMessage(), e); + } } public static void createTextFile(String fileName, String contents) { diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java index c28c0da0..a9eb4874 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java @@ -19,21 +19,14 @@ package com.gluster.storage.management.server.resources.v1_0; import java.net.URI; -import java.util.ArrayList; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.UriInfo; -import com.gluster.storage.management.core.constants.RESTConstants; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.response.VolumeListResponse; - /** * */ diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java deleted file mode 100644 index 4cd7f4f9..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources.v1_0; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -import com.gluster.storage.management.core.exceptions.GlusterValidationException; - -@Provider -public class GenericExceptionMapper implements ExceptionMapper { - - /* (non-Javadoc) - * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) - */ - @Override - public Response toResponse(Exception exception) { - ResponseBuilder builder; - if (exception instanceof GlusterValidationException) { - builder = Response.status(Response.Status.BAD_REQUEST); - } else { - builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR); - } - return builder.entity(exception.getMessage()).type(MediaType.TEXT_PLAIN).build(); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java index af64af47..90656cc6 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java @@ -35,11 +35,12 @@ import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; +import org.apache.log4j.Logger; + import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; import com.gluster.storage.management.core.utils.FileUtil; import com.gluster.storage.management.core.utils.ProcessResult; @@ -49,31 +50,27 @@ import com.sun.jersey.multipart.FormDataParam; @Path(RESOURCE_PATH_KEYS) public class KeysResource extends AbstractResource { - ProcessUtil processUtil = new ProcessUtil(); + private static final Logger logger = Logger.getLogger(KeysResource.class); + private ProcessUtil processUtil = new ProcessUtil(); @GET @Produces(MediaType.APPLICATION_OCTET_STREAM) public Response exportSshkeys() { - try { - StreamingOutput output = new StreamingOutput() { - - @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - try { - File archiveFile = new File(createSskKeyZipFile()); - output.write(FileUtil.readFileAsByteArray(archiveFile)); - archiveFile.delete(); - } catch (Exception e) { - output.write(("Exception while archiving SSH Key files : " + e.getMessage()).getBytes()); - } - } - }; - return streamingOutputResponse(output); - } catch (Exception e) { - return errorResponse("Exporting SSH keys failed! [" + e.getMessage() + "]"); - } + File archiveFile = new File(createSskKeyZipFile()); + byte[] data = FileUtil.readFileAsByteArray(archiveFile); + archiveFile.delete(); + return streamingOutputResponse(createStreamingOutput(data)); } + private StreamingOutput createStreamingOutput(final byte[] data) { + return new StreamingOutput() { + @Override + public void write(OutputStream output) throws IOException { + output.write(data); + } + }; + } + private String createSskKeyZipFile() { String targetDir = System.getProperty("java.io.tmpdir"); String zipFile = targetDir + "ssh-keys.tar"; @@ -108,8 +105,11 @@ public class KeysResource extends AbstractResource { } // To remove the copied key files - processUtil.executeCommand("rm", "-f", targetPubKeyFile, targetPubKeyFile); // Ignore the errors if any - + try { + processUtil.executeCommand("rm", "-f", targetPemFile, targetPubKeyFile); // Ignore the errors if any + } catch (Exception e) { + logger.warn(e.toString()); + } return zipFile; } @@ -118,36 +118,32 @@ public class KeysResource extends AbstractResource { public Response importSshKeys(@FormDataParam("file") InputStream uploadedInputStream) { File uploadedFile = new File(System.getProperty("java.io.tmpdir") + File.separator + "keys.tar"); String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); - try { - writeToFile(uploadedInputStream, uploadedFile.getAbsolutePath()); - // To backup existing SSH pem and public keys - if (SshUtil.PEM_FILE.isFile()) { - if (!SshUtil.PEM_FILE.renameTo(new File(SshUtil.PEM_FILE.getAbsolutePath() + "-" + timestamp))) { - throw new GlusterRuntimeException("Unable to backup pem key!"); - } - } + writeToFile(uploadedInputStream, uploadedFile.getAbsolutePath()); - if (SshUtil.PUBLIC_KEY_FILE.isFile()) { - if (!SshUtil.PUBLIC_KEY_FILE.renameTo(new File(SshUtil.PUBLIC_KEY_FILE.getAbsolutePath() + "-" - + timestamp))) { - throw new GlusterRuntimeException("Unable to backup public key!"); - } + // To backup existing SSH pem and public keys, if exist. + if (SshUtil.PEM_FILE.isFile()) { + if (!SshUtil.PEM_FILE.renameTo(new File(SshUtil.PEM_FILE.getAbsolutePath() + "-" + timestamp))) { + throw new GlusterRuntimeException("Unable to backup pem key!"); } - // Extract SSH pem and public key files. - ProcessResult output = processUtil.executeCommand("tar", "xvf", uploadedFile.getName(), "-C", - SshUtil.SSH_AUTHORIZED_KEYS_DIR); - uploadedFile.delete(); - if (output.isSuccess()) { - return createdResponse("SSH Key imported successfully"); - } else { - return errorResponse(output.getOutput()); + } + + if (SshUtil.PUBLIC_KEY_FILE.isFile()) { + if (!SshUtil.PUBLIC_KEY_FILE + .renameTo(new File(SshUtil.PUBLIC_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { + throw new GlusterRuntimeException("Unable to backup public key!"); } - } catch (Exception e) { - return errorResponse(e.getMessage()); } + // Extract SSH pem and public key files. + ProcessResult output = processUtil.executeCommand("tar", "xvf", uploadedFile.getName(), "-C", + SshUtil.SSH_AUTHORIZED_KEYS_DIR); + uploadedFile.delete(); + if (!output.isSuccess()) { + throw new GlusterRuntimeException(output.getOutput()); + } + return createdResponse("SSH Key imported successfully"); } - + // save uploaded file to the file (with path) private void writeToFile(InputStream inputStream, String toFile) { try { -- cgit From f6108ac5ebbb956e7a7ed5736a6755bbc843ee4b Mon Sep 17 00:00:00 2001 From: Selvasundaram Date: Tue, 26 Jul 2011 17:32:51 +0530 Subject: Volume download logs REST services enhanced --- .../storage/management/core/model/Volume.java | 10 ++++ .../management/gui/views/VolumeSummaryView.java | 9 +-- .../server/resources/v1_0/AbstractResource.java | 11 ++++ .../server/resources/v1_0/KeysResource.java | 10 ---- .../server/resources/v1_0/VolumesResource.java | 67 +++++----------------- 5 files changed, 36 insertions(+), 71 deletions(-) diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java index 9255414c..f224bd5a 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/Volume.java @@ -189,6 +189,16 @@ public class Volume extends Entity { public void setAccessControlList(String accessControlList) { setOption(OPTION_AUTH_ALLOW, accessControlList); } + + @XmlTransient + public boolean isNfsEnabled() { + String nfsDisabled = options.get(OPTION_NFS_DISABLE); + if(nfsDisabled == null || nfsDisabled.equalsIgnoreCase(GlusterConstants.ON)) { + return false; + } else { + return true; + } + } @XmlElement(name="options") public VolumeOptions getOptions() { diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java index 73d3cdf5..16607bff 100644 --- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java +++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/VolumeSummaryView.java @@ -96,9 +96,7 @@ public class VolumeSummaryView extends ViewPart { public void volumeChanged(Volume volume, Event event) { updateVolumeStatusLabel(); populateAccessControlText(); - Boolean isNFSExported = (volume.getOptions().getOption(Volume.OPTION_NFS_DISABLE).getValue() - .equals(GlusterConstants.OFF) ? true : false); - changeNFSStatus(isNFSExported); + changeNFSStatus(volume.isNfsEnabled()); toolbarManager.updateToolbar(volume); } }; @@ -395,10 +393,7 @@ public class VolumeSummaryView extends ViewPart { createCheckbox(nasProtocolsComposite, "Gluster", true, false); - boolean isNFSEnabled = (volume.getOptions().getOption(Volume.OPTION_NFS_DISABLE).getValue() - .equalsIgnoreCase(GlusterConstants.ON)) ? false : true; - - nfsCheckBox = createCheckbox(nasProtocolsComposite, "NFS", isNFSEnabled, true); + nfsCheckBox = createCheckbox(nasProtocolsComposite, "NFS", volume.isNfsEnabled(), true); nfsCheckBox.addSelectionListener(new SelectionAdapter() { @Override diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java index a9eb4874..21b95877 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java @@ -18,6 +18,8 @@ *******************************************************************************/ package com.gluster.storage.management.server.resources.v1_0; +import java.io.IOException; +import java.io.OutputStream; import java.net.URI; import javax.ws.rs.core.Context; @@ -163,4 +165,13 @@ public class AbstractResource { protected Response streamingOutputResponse(StreamingOutput output) { return Response.ok(output).type(MediaType.APPLICATION_OCTET_STREAM).build(); } + + protected StreamingOutput createStreamingOutput(final byte[] data) { + return new StreamingOutput() { + @Override + public void write(OutputStream output) throws IOException { + output.write(data); + } + }; + } } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java index 90656cc6..f04fc5da 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java @@ -37,7 +37,6 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; import org.apache.log4j.Logger; @@ -61,15 +60,6 @@ public class KeysResource extends AbstractResource { archiveFile.delete(); return streamingOutputResponse(createStreamingOutput(data)); } - - private StreamingOutput createStreamingOutput(final byte[] data) { - return new StreamingOutput() { - @Override - public void write(OutputStream output) throws IOException { - output.write(data); - } - }; - } private String createSskKeyZipFile() { String targetDir = System.getProperty("java.io.tmpdir"); diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java index fb3923fc..1d0963eb 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java @@ -59,8 +59,6 @@ import static com.gluster.storage.management.core.constants.RESTConstants.TASK_S import static com.gluster.storage.management.core.constants.RESTConstants.TASK_STOP; import java.io.File; -import java.io.IOException; -import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -77,10 +75,10 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; + +import org.apache.log4j.Logger; import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.constants.RESTConstants; @@ -114,6 +112,7 @@ import com.sun.jersey.spi.resource.Singleton; public class VolumesResource extends AbstractResource { private static final String VOLUME_DIRECTORY_CLEANUP_SCRIPT = "clear_volume_directory.py"; private static final String VOLUME_BRICK_LOG_SCRIPT = "get_volume_brick_log.py"; + private static final Logger logger = Logger.getLogger(VolumesResource.class); @InjectParam private ServerUtil serverUtil; @@ -687,30 +686,20 @@ public class VolumesResource extends AbstractResource { if (clusterService.getCluster(clusterName) == null) { return notFoundResponse("Cluster [" + clusterName + "] not found!"); } - + try { final Volume volume = getVolume(clusterName, volumeName); - StreamingOutput output = new StreamingOutput() { - - @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - try { - File archiveFile = new File(downloadLogs(volume)); - output.write(FileUtil.readFileAsByteArray(archiveFile)); - archiveFile.delete(); - } catch (Exception e) { - // TODO: Log the exception - e.printStackTrace(); - String errMsg = "Exception while downloading/archiving volume log files : " + e.getMessage(); - output.write(errMsg.getBytes()); - } - } - }; - return streamingOutputResponse(output); - } catch(Exception e) { - return errorResponse("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]!"); + File archiveFile = new File(downloadLogs(volume)); + byte[] data = FileUtil.readFileAsByteArray(archiveFile); + archiveFile.delete(); + return streamingOutputResponse(createStreamingOutput(data)); + } catch (Exception e) { + logger.error("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]! [" + + e.getStackTrace() + "]"); + throw (GlusterRuntimeException) e; } } + private String downloadLogs(Volume volume) { // create temporary directory @@ -996,34 +985,4 @@ public class VolumesResource extends AbstractResource { taskResource.getTask(taskId).stop(); } - - public static void main(String[] args) throws ClassNotFoundException { - VolumesResource vr = new VolumesResource(); - // VolumeListResponse response = vr.getAllVolumes(); - // for (Volume volume : response.getVolumes()) { - // System.out.println("\nName:" + volume.getName() + "\nType: " + volume.getVolumeTypeStr() + "\nStatus: " - // + volume.getStatusStr()); - // } - // Volume volume = new Volume(); - // volume.setName("vol3"); - // volume.setTransportType(TRANSPORT_TYPE.ETHERNET); - // List disks = new ArrayList(); - // disks.add("192.168.1.210:sdb"); - // volume.addDisks(disks); - // volume.setAccessControlList("192.168.*"); - // // Status status = vr.createVolume(volume); - // // System.out.println(status.getMessage()); - // Form form = new Form(); - // form.add("volumeName", volume.getName()); - // form.add(RESTConstants.FORM_PARAM_DELETE_OPTION, 1); - // Status status = vr.deleteVolume("Vol2", true); - // System.out.println("Code : " + status.getCode()); - // System.out.println("Message " + status.getMessage()); - - // vr.removeBricks("testCluster", "test", "192.168.1.210:sdb", true); - - String taskId = vr.migrateBrickStart("myGluster", "students", "devserver1:/export/sdc/students", - "devserver2:/export/sdb/students", true); - - } } -- cgit From 78b66abd6bc3fd4d5966ad72c2acd86ccb32d4e4 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 26 Jul 2011 17:35:11 +0530 Subject: Added function to get average cpu usage and fixed bug in getCpuUsageAvg() function --- .../src/Utils.py | 49 ++++++++++------------ .../src/get_server_details.py | 2 +- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/com.gluster.storage.management.server.scripts/src/Utils.py b/src/com.gluster.storage.management.server.scripts/src/Utils.py index fe2816d0..3408c14a 100644 --- a/src/com.gluster.storage.management.server.scripts/src/Utils.py +++ b/src/com.gluster.storage.management.server.scripts/src/Utils.py @@ -386,41 +386,36 @@ def getCpuUsage(): result[fields[0]] = tuple(data) return result +def _getCpuStatList(): + try: + fp = open("/proc/stat") + cpuStatList = map(float, fp.readline().split()[1:]) + fp.close() + return cpuStatList + except IOError, e: + Utils.log("Failed to open /proc/stat: %s" % str(e)) + return None + +def getCpuUsageAvg(): + st1 = _getCpuStatList() + time.sleep(2) + st2 = _getCpuStatList() + if not (st1 and st2): + return None + delta = [st2[i] - st1[i] for i in range(len(st1))] + cpuPercent = sum(delta[:3]) / delta[3] * 100.0 + return str('%.4f' % cpuPercent) def getLoadavg(): - """-> 5-tuple containing the following numbers in order: - - 1-minute load average (float) - - 5-minute load average (float) - - 15-minute load average (float) - - Number of threads/processes currently executing (<= number of - CPUs) (int) - - Number of threads/processes that exist on the system (int) - - The PID of the most recently-created process on the system (int) - """ try: loadavgstr = open('/proc/loadavg', 'r').readline().strip() except IOError: syslog.syslog(syslog.LOG_ERR, "failed to find cpu load") return None - data = loadavgstr.split() - avg1, avg5, avg15 = map(float, data[:3]) - threads_and_procs_running, threads_and_procs_total = map(int, - data[3].split('/')) - most_recent_pid = int(data[4]) - ncpus = 1 - final_avg = "" - if hasattr(os, "sysconf"): - if os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): - # Linux - ncpus = os.sysconf("SC_NPROCESSORS_ONLN") - if isinstance(ncpus, int) and ncpus > 0: - final_avg = "%.4f" % (1.0 * avg1 / ncpus) - - # Future return everything when needed - # Commenting this for the time being - # avg5, avg15, threads_and_procs_running, threads_and_procs_total, most_recent_pid - return final_avg + data = map(float, loadavgstr.split()[1:]) + # returns 1 minute load average + return data[0] def getInfinibandPortStatus(): diff --git a/src/com.gluster.storage.management.server.scripts/src/get_server_details.py b/src/com.gluster.storage.management.server.scripts/src/get_server_details.py index cda1518b..9c3da741 100755 --- a/src/com.gluster.storage.management.server.scripts/src/get_server_details.py +++ b/src/com.gluster.storage.management.server.scripts/src/get_server_details.py @@ -30,7 +30,7 @@ from optparse import OptionParser def getServerDetails(listall): serverName = socket.gethostname() meminfo = getMeminfo() - cpu = 100 * float(getLoadavg()) + cpu = getCpuUsageAvg() nameServerList, domain, searchDomain = readResolvConfFile() if not domain: domain = [None] -- cgit From 6038c29da2928448bfe30a6ac6f35f89c7be42ff Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Tue, 26 Jul 2011 12:48:55 +0530 Subject: Story #38 - CPU Usage graph --- .../management/core/model/ClusterListener.java | 2 + .../core/model/DefaultClusterListener.java | 5 ++ .../management/gui/GlusterDataModelManager.java | 9 +++ .../gui/preferences/ChartsPreferencePage.java | 21 ++--- .../management/gui/utils/ChartViewerComposite.java | 79 ++++++++----------- .../management/gui/views/ClusterSummaryView.java | 90 ++++++++++++++++------ .../gui/views/GlusterServerSummaryView.java | 2 +- .../resources/v1_0/GlusterExceptionMapper.java | 39 ---------- .../resources/v1_0/GlusterServersResource.java | 18 +++++ .../resources/v1_0/ValidationExceptionMapper.java | 39 ---------- .../server/utils/NetworkStatsFactory.java | 18 +++++ 11 files changed, 159 insertions(+), 163 deletions(-) delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterExceptionMapper.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java index 2a4a9920..355483e7 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java @@ -52,4 +52,6 @@ public interface ClusterListener { public void alertRemoved(Alert alert); public void alertUpdated(Alert alert); + + public void aggregatedStatsChanged(); } diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java index e72ff3e5..6a3c5dae 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java @@ -110,4 +110,9 @@ public class DefaultClusterListener implements ClusterListener { public void alertUpdated(Alert alert) { modelChanged(); } + + @Override + public void aggregatedStatsChanged() { + modelChanged(); + } } 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 33132c64..afc0e7aa 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 @@ -201,8 +201,17 @@ public class GlusterDataModelManager { updateDiscoveredServers(model); updateTasks(model); updateAlerts(model); + updateServerStatistics(model); } + private void updateServerStatistics(GlusterDataModel newModel) { + model.getCluster().setAggregatedCpuStats(newModel.getCluster().getAggregatedCpuStats()); + model.getCluster().setAggregatedNetworkStats(newModel.getCluster().getAggregatedNetworkStats()); + for(ClusterListener listener : listeners) { + listener.aggregatedStatsChanged(); + } + } + private void updateAlerts(GlusterDataModel newModel) { List oldAlerts = model.getCluster().getAlerts(); List newAlerts = newModel.getCluster().getAlerts(); 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 2d16fcd2..850407d1 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 @@ -20,28 +20,20 @@ package com.gluster.storage.management.gui.preferences; import org.eclipse.jface.preference.ComboFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; -import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; +import com.gluster.storage.management.gui.Activator; + /** * */ public class ChartsPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { public ChartsPreferencePage() { - } - - public ChartsPreferencePage(int style) { - super(style); - } - - public ChartsPreferencePage(String title, int style) { - super(title, style); - } - - public ChartsPreferencePage(String title, ImageDescriptor image, int style) { - super(title, image, style); + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("Gluster Management Console"); } /* (non-Javadoc) @@ -57,8 +49,7 @@ public class ChartsPreferencePage extends FieldEditorPreferencePage implements I @Override protected void createFieldEditors() { String[][] entryNamesAndValues = new String[][] { - { "1d", "1d" }, { "1w", "1w" }, { "1m", "1m" }, { "1y", "1y" } }; - //{ "1 day", "1d" }, { "1 week", "1w" }, { "1 month", "1m" }, { "1 year", "1y" } }; + { "1 day", "1d" }, { "1 week", "1w" }, { "1 month", "1m" }, { "1 year", "1y" } }; addField(new ComboFieldEditor(PreferenceConstants.P_CPU_CHART_PERIOD, "CPU Usage chart period", entryNamesAndValues, getFieldEditorParent())); addField(new ComboFieldEditor(PreferenceConstants.P_MEM_CHART_PERIOD, "Memory Usage chart period", entryNamesAndValues, 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 30982096..95f0277c 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 @@ -18,8 +18,6 @@ *******************************************************************************/ package com.gluster.storage.management.gui.utils; -import java.lang.reflect.InvocationTargetException; -import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; @@ -30,7 +28,6 @@ import org.eclipse.birt.chart.exception.ChartException; import org.eclipse.birt.chart.factory.GeneratedChartState; import org.eclipse.birt.chart.factory.Generator; import org.eclipse.birt.chart.model.Chart; -import org.eclipse.birt.chart.model.ChartWithAxes; import org.eclipse.birt.chart.model.ChartWithoutAxes; import org.eclipse.birt.chart.model.attribute.Anchor; import org.eclipse.birt.chart.model.attribute.AxisType; @@ -39,7 +36,6 @@ import org.eclipse.birt.chart.model.attribute.ChartDimension; import org.eclipse.birt.chart.model.attribute.FontDefinition; import org.eclipse.birt.chart.model.attribute.LineAttributes; import org.eclipse.birt.chart.model.attribute.LineStyle; -import org.eclipse.birt.chart.model.attribute.NumberFormatSpecifier; import org.eclipse.birt.chart.model.attribute.TickStyle; import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl; import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl; @@ -72,16 +68,6 @@ import org.eclipse.birt.chart.model.type.impl.AreaSeriesImpl; import org.eclipse.birt.chart.model.type.impl.PieSeriesImpl; import org.eclipse.birt.core.framework.PlatformConfig; import org.eclipse.core.runtime.Platform; -import org.eclipse.emf.common.notify.Adapter; -import org.eclipse.emf.common.notify.Notification; -import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.common.util.TreeIterator; -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EOperation; -import org.eclipse.emf.ecore.EReference; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.PaintEvent; @@ -92,7 +78,6 @@ import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.ULocale; /** * @@ -139,12 +124,13 @@ public final class ChartViewerComposite extends Composite implements PaintListen * @param values * Values of each category in the pie chart Constructs a pie * chart viewer composite for given categories and values + * @param maxValue */ - public ChartViewerComposite(Composite parent, int style, Calendar[] categories, Double[] values, String unit, String timestampFormat) { + public ChartViewerComposite(Composite parent, int style, Calendar[] categories, Double[] values, String unit, String timestampFormat, double maxValue) { super(parent, style); init(); - createSingleAreaChart(categories, values, unit, timestampFormat); + createSingleAreaChart(categories, values, unit, timestampFormat, maxValue); addPaintListener(this); } @@ -170,17 +156,18 @@ public final class ChartViewerComposite extends Composite implements PaintListen }); } - private void createSingleAreaChart(Calendar[] timestamps, Double[] values, String unit, String timestampFormat) { - createAreaChart(timestamps, new Double[][] {values}, unit, timestampFormat); + private void createSingleAreaChart(Calendar[] timestamps, Double[] values, String unit, String timestampFormat, double maxValue) { + createAreaChart(timestamps, new Double[][] {values}, unit, timestampFormat, maxValue); } /** * Creates a line chart model as a reference implementation + * @param maxValue * * @return An instance of the simulated runtime chart model (containing * filled datasets) */ - private final void createAreaChart(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat) { + private final void createAreaChart(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat, double maxValue) { chart = ChartWithAxesImpl.create(); // Plot chart.getBlock().setBackground(ColorDefinitionImpl.WHITE()); @@ -206,12 +193,12 @@ public final class ChartViewerComposite extends Composite implements PaintListen lg.getOutline( ).setVisible( false ); lg.setAnchor( Anchor.NORTH_LITERAL ); - updateDataSet(timestamps, values, unit, timestampFormat); + updateDataSet(timestamps, values, unit, timestampFormat, maxValue); } - private void updateDataSet(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat) { + private void updateDataSet(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat, double maxValue) { Axis xAxisPrimary = setupXAxis(timestamps, timestampFormat); - Axis yAxisPrimary = setupYAxis(unit, xAxisPrimary); + Axis yAxisPrimary = setupYAxis(unit, xAxisPrimary, maxValue); configureXSeries(timestamps, xAxisPrimary); configureYSeries(values, yAxisPrimary); } @@ -253,9 +240,11 @@ public final class ChartViewerComposite extends Composite implements PaintListen sdX.getSeries().add(seCategory); } - private Axis setupYAxis(final String unit, Axis xAxisPrimary) { + private Axis setupYAxis(final String unit, Axis xAxisPrimary, double maxValue) { Axis yAxisPrimary = ((ChartWithAxesImpl)chart).getPrimaryOrthogonalAxis(xAxisPrimary); - yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(100)); + if(maxValue > 0) { + yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(maxValue)); + } yAxisPrimary.getScale().setMin(NumberDataElementImpl.create(0)); yAxisPrimary.setGapWidth(0); yAxisPrimary.getScale().setStep(20); @@ -396,26 +385,26 @@ public final class ChartViewerComposite extends Composite implements PaintListen } } - public void chartRefresh(Calendar[] timestamps, Double[][] values, String unit, String timestampFormat) - { - if ( !isDisposed( ) ) - { - final Generator gr = Generator.instance( ); - updateDataSet( timestamps, values, unit, timestampFormat); - - // Refresh - try - { - gr.refresh( generatedChartState ); - } - catch ( ChartException ex ) - { - // TODO: log the exception - ex.printStackTrace( ); - } - redraw( ); - } - } +// public void chartRefresh(Calendar[] timestamps, Double[][] values, String unit, String timestampFormat) +// { +// if ( !isDisposed( ) ) +// { +// final Generator gr = Generator.instance( ); +// updateDataSet( timestamps, values, unit, timestampFormat); +// +// // Refresh +// try +// { +// gr.refresh( generatedChartState ); +// } +// catch ( ChartException ex ) +// { +// // TODO: log the exception +// ex.printStackTrace( ); +// } +// redraw( ); +// } +// } /* * (non-Javadoc) 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 40b0491d..e022e949 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 @@ -47,6 +47,8 @@ import com.gluster.storage.management.client.GlusterServersClient; import com.gluster.storage.management.core.constants.GlusterConstants; import com.gluster.storage.management.core.model.Alert; import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; import com.gluster.storage.management.core.model.EntityGroup; import com.gluster.storage.management.core.model.GlusterDataModel; import com.gluster.storage.management.core.model.GlusterServer; @@ -74,7 +76,11 @@ public class ClusterSummaryView extends ViewPart { private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); private ScrolledForm form; private Cluster cluster; + private Composite cpuChartSection; + private Composite networkChartSection; private GlusterDataModel model = GlusterDataModelManager.getInstance().getModel(); + private ClusterListener clusterListener; + private static final IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); private static final int CHART_WIDTH = 350; /* @@ -89,6 +95,28 @@ public class ClusterSummaryView extends ViewPart { } setPartName("Summary"); createSections(parent); + + clusterListener = new DefaultClusterListener() { + @Override + public void aggregatedStatsChanged() { + super.aggregatedStatsChanged(); + refreshCharts(); + } + }; + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } + + private void refreshCharts() { + String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_CHART_PERIOD); + String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_CHART_PERIOD); + refreshChartSection(cpuChartSection, cluster.getAggregatedCpuStats(), cpuStatsPeriod, "%", 100, 4, new CpuChartPeriodLinkListener(cpuStatsPeriod)); + refreshChartSection(networkChartSection, cluster.getAggregatedNetworkStats(), networkStatsPeriod, "KiB/s", -1, 4, new NetworkChartPeriodLinkListener(networkStatsPeriod)); } private int getServerCountByStatus(Cluster cluster, SERVER_STATUS status) { @@ -145,6 +173,7 @@ public class ClusterSummaryView extends ViewPart { protected String statsPeriod; protected String unit; protected int columnCount; + protected double maxValue; public String getStatsPeriod() { return this.statsPeriod; @@ -154,10 +183,11 @@ public class ClusterSummaryView extends ViewPart { this.statsPeriod = statsPeriod; } - public ChartPeriodLinkListener(String statsPeriod, String unit, int columnCount) { + public ChartPeriodLinkListener(String statsPeriod, String unit, double maxValue, int columnCount) { this.statsPeriod = statsPeriod; this.unit = unit; this.columnCount = columnCount; + this.maxValue = maxValue; } @Override @@ -165,16 +195,8 @@ public class ClusterSummaryView extends ViewPart { super.linkActivated(e); //GlusterDataModelManager.getInstance().initializeAlerts(cluster); Composite section = ((Hyperlink)e.getSource()).getParent().getParent(); - for(Control control : section.getChildren()) { - control.dispose(); - } - List timestamps = new ArrayList(); - List data = new ArrayList(); ServerStats stats = fetchStats(); - extractChartData(stats, timestamps, data, 2); - createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, getTimestampFormatForPeriod(statsPeriod)); - createChartLinks(section, columnCount, this); - section.layout(); + refreshChartSection(section, stats, statsPeriod, unit, maxValue, columnCount, this); } public abstract ChartPeriodLinkListener getInstance(String statsPeriod); @@ -187,8 +209,8 @@ public class ClusterSummaryView extends ViewPart { super(statsPeriod); } - private CpuChartPeriodLinkListener(String statsPeriod, String unit, int columnCount) { - super(statsPeriod, unit, columnCount); + private CpuChartPeriodLinkListener(String statsPeriod, String unit, double maxValue, int columnCount) { + super(statsPeriod, unit, maxValue, columnCount); } @Override @@ -200,7 +222,7 @@ public class ClusterSummaryView extends ViewPart { @Override public ChartPeriodLinkListener getInstance(String statsPeriod) { - return new CpuChartPeriodLinkListener(statsPeriod, "%", 4); + return new CpuChartPeriodLinkListener(statsPeriod, "%", 100, 4); } } @@ -209,8 +231,8 @@ public class ClusterSummaryView extends ViewPart { super(statsPeriod); } - private NetworkChartPeriodLinkListener(String statsPeriod, String unit, int columnCount) { - super(statsPeriod, unit, columnCount); + private NetworkChartPeriodLinkListener(String statsPeriod, String unit, double maxValue, int columnCount) { + super(statsPeriod, unit, maxValue, columnCount); } @Override @@ -222,7 +244,7 @@ public class ClusterSummaryView extends ViewPart { @Override public ChartPeriodLinkListener getInstance(String statsPeriod) { - return new NetworkChartPeriodLinkListener(statsPeriod, "KiB/s", 4); + return new NetworkChartPeriodLinkListener(statsPeriod, "KiB/s", -1d, 4); } } @@ -253,8 +275,8 @@ public class ClusterSummaryView extends ViewPart { } } - private ChartViewerComposite createAreaChart(Composite section, Calendar timestamps[], Double values[], String unit, String timestampFormat) { - ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, timestampFormat); + private ChartViewerComposite createAreaChart(Composite section, Calendar timestamps[], Double values[], String unit, String timestampFormat, double maxValue) { + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, timestampFormat, maxValue); GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); data.widthHint = CHART_WIDTH; data.heightHint = 250; @@ -345,7 +367,7 @@ public class ClusterSummaryView extends ViewPart { parent.layout(); // IMP: lays out the form properly } - private void createAreaChartSection(ServerStats stats, String sectionTitle, int dataColumnIndex, String unit, String timestampFormat, ChartPeriodLinkListener listener) { + private Composite createAreaChartSection(ServerStats stats, String sectionTitle, int dataColumnIndex, String unit, String timestampFormat, ChartPeriodLinkListener listener, double maxValue) { Composite section = guiHelper.createSection(form, toolkit, sectionTitle, null, 1, false); List timestamps = new ArrayList(); @@ -353,17 +375,22 @@ public class ClusterSummaryView extends ViewPart { 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; + return null; + } + + if(stats == null) { + toolkit.createLabel(section, "Server statistics not available. Try after some time!"); + return null; } extractChartData(stats, timestamps, data, dataColumnIndex); if(timestamps.size() == 0) { toolkit.createLabel(section, "Server statistics not available!\n Check if all services are running properly on the cluster servers."); - return; + return null; } - createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, timestampFormat); + createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, timestampFormat, maxValue); // 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), @@ -375,6 +402,7 @@ public class ClusterSummaryView extends ViewPart { // 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, listener); + return section; } private void createCPUUsageSection() { @@ -382,7 +410,7 @@ public class ClusterSummaryView extends ViewPart { String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_CHART_PERIOD); // 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, "%", getTimestampFormatForPeriod(cpuStatsPeriod), new CpuChartPeriodLinkListener(cpuStatsPeriod)); + cpuChartSection = createAreaChartSection(cluster.getAggregatedCpuStats(), "CPU Usage (Aggregated)", 2, "%", getTimestampFormatForPeriod(cpuStatsPeriod), new CpuChartPeriodLinkListener(cpuStatsPeriod), 100); } private String getTimestampFormatForPeriod(String statsPeriod) { @@ -410,7 +438,7 @@ public class ClusterSummaryView extends ViewPart { String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_CHART_PERIOD); // 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", getTimestampFormatForPeriod(networkStatsPeriod), new NetworkChartPeriodLinkListener(networkStatsPeriod)); + networkChartSection = createAreaChartSection(cluster.getAggregatedNetworkStats(), "Network Usage (Aggregated)", 2, "KiB/s", getTimestampFormatForPeriod(networkStatsPeriod), new NetworkChartPeriodLinkListener(networkStatsPeriod), -1); } private void createRunningTasksSection() { @@ -453,4 +481,18 @@ public class ClusterSummaryView extends ViewPart { form.setFocus(); } } + + private void refreshChartSection(Composite section, ServerStats stats, String statsPeriod, String unit, double maxValue, int columnCount, ChartPeriodLinkListener linkListener) { + for(Control control : section.getChildren()) { + if(! control.isDisposed()) { + control.dispose(); + } + } + List timestamps = new ArrayList(); + List data = new ArrayList(); + extractChartData(stats, timestamps, data, 2); + createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, getTimestampFormatForPeriod(statsPeriod), maxValue); + createChartLinks(section, columnCount, linkListener); + section.layout(); + } } 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 e7ef1648..492b51f3 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 @@ -116,7 +116,7 @@ public class GlusterServerSummaryView extends ViewPart { } private void createAreaChart(Composite section, Calendar timestamps[], Double values[], String unit) { - ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, "HH:mm"); + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, "HH:mm", 100); GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); data.widthHint = CHART_WIDTH; data.heightHint = 250; diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterExceptionMapper.java deleted file mode 100644 index 99089eb7..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterExceptionMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources.v1_0; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; - -@Provider -public class GlusterExceptionMapper implements ExceptionMapper { - - /* (non-Javadoc) - * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) - */ - @Override - public Response toResponse(GlusterRuntimeException exception) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(exception.getMessage()) - .type(MediaType.TEXT_PLAIN).build(); - } -} 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 1b2bb41e..9693ace9 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 @@ -522,6 +522,14 @@ public class GlusterServersResource extends AbstractServersResource { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } + + if (type == null || type.isEmpty()) { + throw new GlusterValidationException("Statistics type name must not be empty!"); + } + + if (period == null || period.isEmpty()) { + throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); + } ClusterInfo cluster = clusterService.getCluster(clusterName); if (cluster == null) { @@ -541,9 +549,19 @@ public class GlusterServersResource extends AbstractServersResource { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } + if (serverName == null || serverName.isEmpty()) { throw new GlusterValidationException("Server name must not be empty!"); } + + if (type == null || type.isEmpty()) { + throw new GlusterValidationException("Statistics type name must not be empty!"); + } + + if (period == null || period.isEmpty()) { + throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); + } + return okResponse(getStatsFactory(type).fetchStats(serverName, period, networkInterface), mediaType); } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java deleted file mode 100644 index cab6cc62..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources.v1_0; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -import com.gluster.storage.management.core.exceptions.GlusterValidationException; - -@Provider -public class ValidationExceptionMapper implements ExceptionMapper { - - /* (non-Javadoc) - * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) - */ - @Override - public Response toResponse(GlusterValidationException exception) { - return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()) - .type(MediaType.TEXT_PLAIN).build(); - } -} 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 index 96bb0c65..2a50d598 100644 --- 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 @@ -27,6 +27,7 @@ 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; +import com.gluster.storage.management.core.model.ServerStatsRow; /** * @@ -102,4 +103,21 @@ public class NetworkStatsFactory extends AbstractStatsFactory { averageAggregatedStats(aggregatedStats, dataCount); } + + @Override + public ServerStats fetchStats(String serverName, String period, String... args) { + ServerStats stats = super.fetchStats(serverName, period, args); + + // the data returned by rrd contains "bytes" transferred in the given time step. Update the stats object to represent KiB/s + int step = stats.getMetadata().getStep(); + for(ServerStatsRow row : stats.getRows()) { + List data = row.getUsageData(); + for (int i = 0; i < data.size(); i++) { + Double val = data.get(i); + data.set(i, val / 1024 / step); + } + } + + return stats; + } } -- cgit From 17d81f5f32a577023a456315daadb5d4544d57c5 Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Tue, 26 Jul 2011 12:48:55 +0530 Subject: Story #38 - CPU Usage graph --- .../management/core/model/ClusterListener.java | 2 + .../core/model/DefaultClusterListener.java | 5 ++ .../management/gui/GlusterDataModelManager.java | 9 ++ .../gui/preferences/ChartsPreferencePage.java | 21 ++--- .../management/gui/utils/ChartViewerComposite.java | 79 ++++++++--------- .../management/gui/views/ClusterSummaryView.java | 98 ++++++++++++++++------ .../gui/views/GlusterServerSummaryView.java | 2 +- .../resources/v1_0/GlusterExceptionMapper.java | 39 --------- .../resources/v1_0/GlusterServersResource.java | 18 ++++ .../resources/v1_0/ValidationExceptionMapper.java | 39 --------- .../server/utils/NetworkStatsFactory.java | 18 ++++ 11 files changed, 165 insertions(+), 165 deletions(-) delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterExceptionMapper.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java index 2a4a9920..355483e7 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/ClusterListener.java @@ -52,4 +52,6 @@ public interface ClusterListener { public void alertRemoved(Alert alert); public void alertUpdated(Alert alert); + + public void aggregatedStatsChanged(); } diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java index e72ff3e5..6a3c5dae 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/DefaultClusterListener.java @@ -110,4 +110,9 @@ public class DefaultClusterListener implements ClusterListener { public void alertUpdated(Alert alert) { modelChanged(); } + + @Override + public void aggregatedStatsChanged() { + modelChanged(); + } } 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 33132c64..afc0e7aa 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 @@ -201,8 +201,17 @@ public class GlusterDataModelManager { updateDiscoveredServers(model); updateTasks(model); updateAlerts(model); + updateServerStatistics(model); } + private void updateServerStatistics(GlusterDataModel newModel) { + model.getCluster().setAggregatedCpuStats(newModel.getCluster().getAggregatedCpuStats()); + model.getCluster().setAggregatedNetworkStats(newModel.getCluster().getAggregatedNetworkStats()); + for(ClusterListener listener : listeners) { + listener.aggregatedStatsChanged(); + } + } + private void updateAlerts(GlusterDataModel newModel) { List oldAlerts = model.getCluster().getAlerts(); List newAlerts = newModel.getCluster().getAlerts(); 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 2d16fcd2..850407d1 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 @@ -20,28 +20,20 @@ package com.gluster.storage.management.gui.preferences; import org.eclipse.jface.preference.ComboFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; -import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; +import com.gluster.storage.management.gui.Activator; + /** * */ public class ChartsPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { public ChartsPreferencePage() { - } - - public ChartsPreferencePage(int style) { - super(style); - } - - public ChartsPreferencePage(String title, int style) { - super(title, style); - } - - public ChartsPreferencePage(String title, ImageDescriptor image, int style) { - super(title, image, style); + super(GRID); + setPreferenceStore(Activator.getDefault().getPreferenceStore()); + setDescription("Gluster Management Console"); } /* (non-Javadoc) @@ -57,8 +49,7 @@ public class ChartsPreferencePage extends FieldEditorPreferencePage implements I @Override protected void createFieldEditors() { String[][] entryNamesAndValues = new String[][] { - { "1d", "1d" }, { "1w", "1w" }, { "1m", "1m" }, { "1y", "1y" } }; - //{ "1 day", "1d" }, { "1 week", "1w" }, { "1 month", "1m" }, { "1 year", "1y" } }; + { "1 day", "1d" }, { "1 week", "1w" }, { "1 month", "1m" }, { "1 year", "1y" } }; addField(new ComboFieldEditor(PreferenceConstants.P_CPU_CHART_PERIOD, "CPU Usage chart period", entryNamesAndValues, getFieldEditorParent())); addField(new ComboFieldEditor(PreferenceConstants.P_MEM_CHART_PERIOD, "Memory Usage chart period", entryNamesAndValues, 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 30982096..95f0277c 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 @@ -18,8 +18,6 @@ *******************************************************************************/ package com.gluster.storage.management.gui.utils; -import java.lang.reflect.InvocationTargetException; -import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; @@ -30,7 +28,6 @@ import org.eclipse.birt.chart.exception.ChartException; import org.eclipse.birt.chart.factory.GeneratedChartState; import org.eclipse.birt.chart.factory.Generator; import org.eclipse.birt.chart.model.Chart; -import org.eclipse.birt.chart.model.ChartWithAxes; import org.eclipse.birt.chart.model.ChartWithoutAxes; import org.eclipse.birt.chart.model.attribute.Anchor; import org.eclipse.birt.chart.model.attribute.AxisType; @@ -39,7 +36,6 @@ import org.eclipse.birt.chart.model.attribute.ChartDimension; import org.eclipse.birt.chart.model.attribute.FontDefinition; import org.eclipse.birt.chart.model.attribute.LineAttributes; import org.eclipse.birt.chart.model.attribute.LineStyle; -import org.eclipse.birt.chart.model.attribute.NumberFormatSpecifier; import org.eclipse.birt.chart.model.attribute.TickStyle; import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl; import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl; @@ -72,16 +68,6 @@ import org.eclipse.birt.chart.model.type.impl.AreaSeriesImpl; import org.eclipse.birt.chart.model.type.impl.PieSeriesImpl; import org.eclipse.birt.core.framework.PlatformConfig; import org.eclipse.core.runtime.Platform; -import org.eclipse.emf.common.notify.Adapter; -import org.eclipse.emf.common.notify.Notification; -import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.common.util.TreeIterator; -import org.eclipse.emf.ecore.EClass; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EOperation; -import org.eclipse.emf.ecore.EReference; -import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.PaintEvent; @@ -92,7 +78,6 @@ import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import com.ibm.icu.util.Calendar; -import com.ibm.icu.util.ULocale; /** * @@ -139,12 +124,13 @@ public final class ChartViewerComposite extends Composite implements PaintListen * @param values * Values of each category in the pie chart Constructs a pie * chart viewer composite for given categories and values + * @param maxValue */ - public ChartViewerComposite(Composite parent, int style, Calendar[] categories, Double[] values, String unit, String timestampFormat) { + public ChartViewerComposite(Composite parent, int style, Calendar[] categories, Double[] values, String unit, String timestampFormat, double maxValue) { super(parent, style); init(); - createSingleAreaChart(categories, values, unit, timestampFormat); + createSingleAreaChart(categories, values, unit, timestampFormat, maxValue); addPaintListener(this); } @@ -170,17 +156,18 @@ public final class ChartViewerComposite extends Composite implements PaintListen }); } - private void createSingleAreaChart(Calendar[] timestamps, Double[] values, String unit, String timestampFormat) { - createAreaChart(timestamps, new Double[][] {values}, unit, timestampFormat); + private void createSingleAreaChart(Calendar[] timestamps, Double[] values, String unit, String timestampFormat, double maxValue) { + createAreaChart(timestamps, new Double[][] {values}, unit, timestampFormat, maxValue); } /** * Creates a line chart model as a reference implementation + * @param maxValue * * @return An instance of the simulated runtime chart model (containing * filled datasets) */ - private final void createAreaChart(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat) { + private final void createAreaChart(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat, double maxValue) { chart = ChartWithAxesImpl.create(); // Plot chart.getBlock().setBackground(ColorDefinitionImpl.WHITE()); @@ -206,12 +193,12 @@ public final class ChartViewerComposite extends Composite implements PaintListen lg.getOutline( ).setVisible( false ); lg.setAnchor( Anchor.NORTH_LITERAL ); - updateDataSet(timestamps, values, unit, timestampFormat); + updateDataSet(timestamps, values, unit, timestampFormat, maxValue); } - private void updateDataSet(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat) { + private void updateDataSet(Calendar[] timestamps, Double[][] values, final String unit, final String timestampFormat, double maxValue) { Axis xAxisPrimary = setupXAxis(timestamps, timestampFormat); - Axis yAxisPrimary = setupYAxis(unit, xAxisPrimary); + Axis yAxisPrimary = setupYAxis(unit, xAxisPrimary, maxValue); configureXSeries(timestamps, xAxisPrimary); configureYSeries(values, yAxisPrimary); } @@ -253,9 +240,11 @@ public final class ChartViewerComposite extends Composite implements PaintListen sdX.getSeries().add(seCategory); } - private Axis setupYAxis(final String unit, Axis xAxisPrimary) { + private Axis setupYAxis(final String unit, Axis xAxisPrimary, double maxValue) { Axis yAxisPrimary = ((ChartWithAxesImpl)chart).getPrimaryOrthogonalAxis(xAxisPrimary); - yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(100)); + if(maxValue > 0) { + yAxisPrimary.getScale().setMax(NumberDataElementImpl.create(maxValue)); + } yAxisPrimary.getScale().setMin(NumberDataElementImpl.create(0)); yAxisPrimary.setGapWidth(0); yAxisPrimary.getScale().setStep(20); @@ -396,26 +385,26 @@ public final class ChartViewerComposite extends Composite implements PaintListen } } - public void chartRefresh(Calendar[] timestamps, Double[][] values, String unit, String timestampFormat) - { - if ( !isDisposed( ) ) - { - final Generator gr = Generator.instance( ); - updateDataSet( timestamps, values, unit, timestampFormat); - - // Refresh - try - { - gr.refresh( generatedChartState ); - } - catch ( ChartException ex ) - { - // TODO: log the exception - ex.printStackTrace( ); - } - redraw( ); - } - } +// public void chartRefresh(Calendar[] timestamps, Double[][] values, String unit, String timestampFormat) +// { +// if ( !isDisposed( ) ) +// { +// final Generator gr = Generator.instance( ); +// updateDataSet( timestamps, values, unit, timestampFormat); +// +// // Refresh +// try +// { +// gr.refresh( generatedChartState ); +// } +// catch ( ChartException ex ) +// { +// // TODO: log the exception +// ex.printStackTrace( ); +// } +// redraw( ); +// } +// } /* * (non-Javadoc) 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 40b0491d..b67cca30 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 @@ -47,6 +47,8 @@ import com.gluster.storage.management.client.GlusterServersClient; import com.gluster.storage.management.core.constants.GlusterConstants; import com.gluster.storage.management.core.model.Alert; import com.gluster.storage.management.core.model.Cluster; +import com.gluster.storage.management.core.model.ClusterListener; +import com.gluster.storage.management.core.model.DefaultClusterListener; import com.gluster.storage.management.core.model.EntityGroup; import com.gluster.storage.management.core.model.GlusterDataModel; import com.gluster.storage.management.core.model.GlusterServer; @@ -74,7 +76,11 @@ public class ClusterSummaryView extends ViewPart { private final FormToolkit toolkit = new FormToolkit(Display.getCurrent()); private ScrolledForm form; private Cluster cluster; + private Composite cpuChartSection; + private Composite networkChartSection; private GlusterDataModel model = GlusterDataModelManager.getInstance().getModel(); + private ClusterListener clusterListener; + private static final IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); private static final int CHART_WIDTH = 350; /* @@ -89,6 +95,28 @@ public class ClusterSummaryView extends ViewPart { } setPartName("Summary"); createSections(parent); + + clusterListener = new DefaultClusterListener() { + @Override + public void aggregatedStatsChanged() { + super.aggregatedStatsChanged(); + refreshCharts(); + } + }; + GlusterDataModelManager.getInstance().addClusterListener(clusterListener); + } + + @Override + public void dispose() { + super.dispose(); + GlusterDataModelManager.getInstance().removeClusterListener(clusterListener); + } + + private void refreshCharts() { + String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_CHART_PERIOD); + String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_CHART_PERIOD); + refreshChartSection(cpuChartSection, cluster.getAggregatedCpuStats(), cpuStatsPeriod, "%", 100, 4, new CpuChartPeriodLinkListener(cpuStatsPeriod)); + refreshChartSection(networkChartSection, cluster.getAggregatedNetworkStats(), networkStatsPeriod, "KiB/s", -1, 4, new NetworkChartPeriodLinkListener(networkStatsPeriod)); } private int getServerCountByStatus(Cluster cluster, SERVER_STATUS status) { @@ -145,6 +173,7 @@ public class ClusterSummaryView extends ViewPart { protected String statsPeriod; protected String unit; protected int columnCount; + protected double maxValue; public String getStatsPeriod() { return this.statsPeriod; @@ -154,10 +183,11 @@ public class ClusterSummaryView extends ViewPart { this.statsPeriod = statsPeriod; } - public ChartPeriodLinkListener(String statsPeriod, String unit, int columnCount) { + public ChartPeriodLinkListener(String statsPeriod, String unit, double maxValue, int columnCount) { this.statsPeriod = statsPeriod; this.unit = unit; this.columnCount = columnCount; + this.maxValue = maxValue; } @Override @@ -165,16 +195,8 @@ public class ClusterSummaryView extends ViewPart { super.linkActivated(e); //GlusterDataModelManager.getInstance().initializeAlerts(cluster); Composite section = ((Hyperlink)e.getSource()).getParent().getParent(); - for(Control control : section.getChildren()) { - control.dispose(); - } - List timestamps = new ArrayList(); - List data = new ArrayList(); ServerStats stats = fetchStats(); - extractChartData(stats, timestamps, data, 2); - createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, getTimestampFormatForPeriod(statsPeriod)); - createChartLinks(section, columnCount, this); - section.layout(); + refreshChartSection(section, stats, statsPeriod, unit, maxValue, columnCount, this); } public abstract ChartPeriodLinkListener getInstance(String statsPeriod); @@ -187,20 +209,22 @@ public class ClusterSummaryView extends ViewPart { super(statsPeriod); } - private CpuChartPeriodLinkListener(String statsPeriod, String unit, int columnCount) { - super(statsPeriod, unit, columnCount); + private CpuChartPeriodLinkListener(String statsPeriod, String unit, double maxValue, int columnCount) { + super(statsPeriod, unit, maxValue, columnCount); } @Override protected ServerStats fetchStats() { IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); preferenceStore.setValue(PreferenceConstants.P_CPU_CHART_PERIOD, statsPeriod); - return new GlusterServersClient().getAggregatedCpuStats(statsPeriod); + ServerStats stats = new GlusterServersClient().getAggregatedCpuStats(statsPeriod); + cluster.setAggregatedCpuStats(stats); + return stats; } @Override public ChartPeriodLinkListener getInstance(String statsPeriod) { - return new CpuChartPeriodLinkListener(statsPeriod, "%", 4); + return new CpuChartPeriodLinkListener(statsPeriod, "%", 100, 4); } } @@ -209,20 +233,22 @@ public class ClusterSummaryView extends ViewPart { super(statsPeriod); } - private NetworkChartPeriodLinkListener(String statsPeriod, String unit, int columnCount) { - super(statsPeriod, unit, columnCount); + private NetworkChartPeriodLinkListener(String statsPeriod, String unit, double maxValue, int columnCount) { + super(statsPeriod, unit, maxValue, columnCount); } @Override protected ServerStats fetchStats() { IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore(); preferenceStore.setValue(PreferenceConstants.P_NETWORK_CHART_PERIOD, statsPeriod); - return new GlusterServersClient().getAggregatedNetworkStats(statsPeriod); + ServerStats stats = new GlusterServersClient().getAggregatedNetworkStats(statsPeriod); + cluster.setAggregatedNetworkStats(stats); + return stats; } @Override public ChartPeriodLinkListener getInstance(String statsPeriod) { - return new NetworkChartPeriodLinkListener(statsPeriod, "KiB/s", 4); + return new NetworkChartPeriodLinkListener(statsPeriod, "KiB/s", -1d, 4); } } @@ -253,8 +279,8 @@ public class ClusterSummaryView extends ViewPart { } } - private ChartViewerComposite createAreaChart(Composite section, Calendar timestamps[], Double values[], String unit, String timestampFormat) { - ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, timestampFormat); + private ChartViewerComposite createAreaChart(Composite section, Calendar timestamps[], Double values[], String unit, String timestampFormat, double maxValue) { + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, timestampFormat, maxValue); GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); data.widthHint = CHART_WIDTH; data.heightHint = 250; @@ -345,7 +371,7 @@ public class ClusterSummaryView extends ViewPart { parent.layout(); // IMP: lays out the form properly } - private void createAreaChartSection(ServerStats stats, String sectionTitle, int dataColumnIndex, String unit, String timestampFormat, ChartPeriodLinkListener listener) { + private Composite createAreaChartSection(ServerStats stats, String sectionTitle, int dataColumnIndex, String unit, String timestampFormat, ChartPeriodLinkListener listener, double maxValue) { Composite section = guiHelper.createSection(form, toolkit, sectionTitle, null, 1, false); List timestamps = new ArrayList(); @@ -353,17 +379,22 @@ public class ClusterSummaryView extends ViewPart { 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; + return null; + } + + if(stats == null) { + toolkit.createLabel(section, "Server statistics not available. Try after some time!"); + return null; } extractChartData(stats, timestamps, data, dataColumnIndex); if(timestamps.size() == 0) { toolkit.createLabel(section, "Server statistics not available!\n Check if all services are running properly on the cluster servers."); - return; + return null; } - createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, timestampFormat); + createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, timestampFormat, maxValue); // 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), @@ -375,6 +406,7 @@ public class ClusterSummaryView extends ViewPart { // 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, listener); + return section; } private void createCPUUsageSection() { @@ -382,7 +414,7 @@ public class ClusterSummaryView extends ViewPart { String cpuStatsPeriod = preferenceStore.getString(PreferenceConstants.P_CPU_CHART_PERIOD); // 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, "%", getTimestampFormatForPeriod(cpuStatsPeriod), new CpuChartPeriodLinkListener(cpuStatsPeriod)); + cpuChartSection = createAreaChartSection(cluster.getAggregatedCpuStats(), "CPU Usage (Aggregated)", 2, "%", getTimestampFormatForPeriod(cpuStatsPeriod), new CpuChartPeriodLinkListener(cpuStatsPeriod), 100); } private String getTimestampFormatForPeriod(String statsPeriod) { @@ -410,7 +442,7 @@ public class ClusterSummaryView extends ViewPart { String networkStatsPeriod = preferenceStore.getString(PreferenceConstants.P_NETWORK_CHART_PERIOD); // 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", getTimestampFormatForPeriod(networkStatsPeriod), new NetworkChartPeriodLinkListener(networkStatsPeriod)); + networkChartSection = createAreaChartSection(cluster.getAggregatedNetworkStats(), "Network Usage (Aggregated)", 2, "KiB/s", getTimestampFormatForPeriod(networkStatsPeriod), new NetworkChartPeriodLinkListener(networkStatsPeriod), -1); } private void createRunningTasksSection() { @@ -453,4 +485,18 @@ public class ClusterSummaryView extends ViewPart { form.setFocus(); } } + + private void refreshChartSection(Composite section, ServerStats stats, String statsPeriod, String unit, double maxValue, int columnCount, ChartPeriodLinkListener linkListener) { + for(Control control : section.getChildren()) { + if(! control.isDisposed()) { + control.dispose(); + } + } + List timestamps = new ArrayList(); + List data = new ArrayList(); + extractChartData(stats, timestamps, data, 2); + createAreaChart(section, timestamps.toArray(new Calendar[0]), data.toArray(new Double[0]), unit, getTimestampFormatForPeriod(statsPeriod), maxValue); + createChartLinks(section, columnCount, linkListener); + section.layout(); + } } 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 e7ef1648..492b51f3 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 @@ -116,7 +116,7 @@ public class GlusterServerSummaryView extends ViewPart { } private void createAreaChart(Composite section, Calendar timestamps[], Double values[], String unit) { - ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, "HH:mm"); + ChartViewerComposite chartViewerComposite = new ChartViewerComposite(section, SWT.NONE, timestamps, values, unit, "HH:mm", 100); GridData data = new GridData(SWT.FILL, SWT.FILL, false, false); data.widthHint = CHART_WIDTH; data.heightHint = 250; diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterExceptionMapper.java deleted file mode 100644 index 99089eb7..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterExceptionMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources.v1_0; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; - -@Provider -public class GlusterExceptionMapper implements ExceptionMapper { - - /* (non-Javadoc) - * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) - */ - @Override - public Response toResponse(GlusterRuntimeException exception) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(exception.getMessage()) - .type(MediaType.TEXT_PLAIN).build(); - } -} 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 1b2bb41e..9693ace9 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 @@ -522,6 +522,14 @@ public class GlusterServersResource extends AbstractServersResource { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } + + if (type == null || type.isEmpty()) { + throw new GlusterValidationException("Statistics type name must not be empty!"); + } + + if (period == null || period.isEmpty()) { + throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); + } ClusterInfo cluster = clusterService.getCluster(clusterName); if (cluster == null) { @@ -541,9 +549,19 @@ public class GlusterServersResource extends AbstractServersResource { if (clusterName == null || clusterName.isEmpty()) { throw new GlusterValidationException("Cluster name must not be empty!"); } + if (serverName == null || serverName.isEmpty()) { throw new GlusterValidationException("Server name must not be empty!"); } + + if (type == null || type.isEmpty()) { + throw new GlusterValidationException("Statistics type name must not be empty!"); + } + + if (period == null || period.isEmpty()) { + throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); + } + return okResponse(getStatsFactory(type).fetchStats(serverName, period, networkInterface), mediaType); } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java deleted file mode 100644 index cab6cc62..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources.v1_0; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -import com.gluster.storage.management.core.exceptions.GlusterValidationException; - -@Provider -public class ValidationExceptionMapper implements ExceptionMapper { - - /* (non-Javadoc) - * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) - */ - @Override - public Response toResponse(GlusterValidationException exception) { - return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()) - .type(MediaType.TEXT_PLAIN).build(); - } -} 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 index 96bb0c65..2a50d598 100644 --- 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 @@ -27,6 +27,7 @@ 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; +import com.gluster.storage.management.core.model.ServerStatsRow; /** * @@ -102,4 +103,21 @@ public class NetworkStatsFactory extends AbstractStatsFactory { averageAggregatedStats(aggregatedStats, dataCount); } + + @Override + public ServerStats fetchStats(String serverName, String period, String... args) { + ServerStats stats = super.fetchStats(serverName, period, args); + + // the data returned by rrd contains "bytes" transferred in the given time step. Update the stats object to represent KiB/s + int step = stats.getMetadata().getStep(); + for(ServerStatsRow row : stats.getRows()) { + List data = row.getUsageData(); + for (int i = 0; i < data.size(); i++) { + Double val = data.get(i); + data.set(i, val / 1024 / step); + } + } + + return stats; + } } -- cgit