summaryrefslogtreecommitdiffstats
path: root/src/com.gluster.storage.management.server
diff options
context:
space:
mode:
authorShireesh Anjal <shireesh@gluster.com>2011-07-12 23:16:54 +0530
committerShireesh Anjal <shireesh@gluster.com>2011-07-18 00:02:42 +0530
commit4290f5519fb7480df6c5919583efc1f7feebf4b3 (patch)
tree5930ba1eb58235ec12b897c300f7fd7bef9694d1 /src/com.gluster.storage.management.server
parent194d5787da03f843a4eb81f304d6f30057bb5be2 (diff)
Story #38 - CPU Usage graph
Diffstat (limited to 'src/com.gluster.storage.management.server')
-rw-r--r--src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml18
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java45
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java160
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java39
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java106
5 files changed, 315 insertions, 53 deletions
diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml
index 7c20d6c7..405c4e40 100644
--- a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml
+++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml
@@ -81,14 +81,14 @@
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-
+
<security-constraint>
- <web-resource-collection>
- <web-resource-name>Gluster Management Gateway</web-resource-name>
- <url-pattern>/*</url-pattern>
- </web-resource-collection>
- <user-data-constraint>
- <transport-guarantee>CONFIDENTIAL</transport-guarantee>
- </user-data-constraint>
-</security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Gluster Management Gateway</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
</web-app>
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
new file mode 100644
index 00000000..4cd7f4f9
--- /dev/null
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.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<Exception> {
+
+ /* (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/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java
index a5f366a2..09391841 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
@@ -18,15 +18,21 @@
*******************************************************************************/
package com.gluster.storage.management.server.resources.v1_0;
-import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FSTYPE;
+import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME;
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_TYPE;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DISKS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_SERVERS;
+import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_STATISTICS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS;
+import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_CPU;
+import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_NETWORK;
+import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_MEMORY;
import java.util.ArrayList;
import java.util.List;
@@ -39,6 +45,7 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -49,14 +56,15 @@ 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.model.ServerStats;
import com.gluster.storage.management.core.model.GlusterServer;
import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS;
import com.gluster.storage.management.core.response.GlusterServerListResponse;
+import com.gluster.storage.management.core.response.ServerNameListResponse;
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.GlusterUtil;
import com.gluster.storage.management.server.utils.SshUtil;
import com.sun.jersey.api.core.InjectParam;
import com.sun.jersey.spi.resource.Singleton;
@@ -92,17 +100,44 @@ public class GlusterServersResource extends AbstractServersResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
- public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) {
- return getGlusterServers(clusterName, MediaType.APPLICATION_JSON);
+ public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
+ @QueryParam(QUERY_PARAM_DETAILS) Boolean details) {
+ return getGlusterServers(clusterName, MediaType.APPLICATION_JSON, details);
}
@GET
@Produces(MediaType.APPLICATION_XML)
- public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) {
- return getGlusterServers(clusterName, MediaType.APPLICATION_XML);
+ public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
+ @QueryParam(QUERY_PARAM_DETAILS) Boolean details) {
+ return getGlusterServers(clusterName, MediaType.APPLICATION_XML, details);
}
+
+ private List<GlusterServer> getGlusterServers(String clusterName, boolean fetchDetails) {
+ List<GlusterServer> glusterServers;
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
+ if (onlineServer == null) {
+ throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
+ }
- public Response getGlusterServers(String clusterName, String mediaType) {
+ try {
+ glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails);
+ } catch (ConnectionException e) {
+ // online server has gone offline! try with a different one.
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
+ if (onlineServer == null) {
+ throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
+ }
+ glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails);
+ }
+ return glusterServers;
+ }
+
+ private Response getGlusterServers(String clusterName, String mediaType, Boolean fetchDetails) {
+ if(fetchDetails == null) {
+ // by default, fetch the server details
+ fetchDetails = true;
+ }
+
List<GlusterServer> glusterServers = new ArrayList<GlusterServer>();
if (clusterName == null || clusterName.isEmpty()) {
@@ -118,37 +153,30 @@ public class GlusterServersResource extends AbstractServersResource {
return okResponse(new GlusterServerListResponse(glusterServers), mediaType);
}
- GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
- if (onlineServer == null) {
- return errorResponse("No online servers found in cluster [" + clusterName + "]");
- }
-
try {
- glusterServers = getGlusterServers(clusterName, onlineServer);
- } catch (ConnectionException e) {
- // online server has gone offline! try with a different one.
- onlineServer = clusterService.getNewOnlineServer(clusterName);
- if (onlineServer == null) {
- return errorResponse("No online servers found in cluster [" + clusterName + "]");
- }
- try {
- glusterServers = getGlusterServers(clusterName, onlineServer);
- } catch (Exception e1) {
- return errorResponse(e1.getMessage());
- }
+ glusterServers = getGlusterServers(clusterName, fetchDetails);
} catch (Exception e) {
return errorResponse(e.getMessage());
}
-
- String errMsg = fetchDetailsOfServers(glusterServers, onlineServer);
- if (!errMsg.isEmpty()) {
- return errorResponse("Couldn't fetch details for server(s): " + errMsg);
+
+ if(fetchDetails) {
+ return okResponse(new GlusterServerListResponse(glusterServers), mediaType);
+ } else {
+ // no details to be fetched. Return list of server names.
+ return okResponse(new ServerNameListResponse(getServerNames(glusterServers)), mediaType);
}
+ }
+
- return okResponse(new GlusterServerListResponse(glusterServers), mediaType);
+ private List<String> getServerNames(List<GlusterServer> glusterServers) {
+ List<String> serverNames = new ArrayList<String>();
+ for(GlusterServer server : glusterServers) {
+ serverNames.add(server.getName());
+ }
+ return serverNames;
}
- public String fetchDetailsOfServers(List<GlusterServer> glusterServers, GlusterServer onlineServer) {
+ private String fetchDetailsOfServers(List<GlusterServer> glusterServers, GlusterServer onlineServer) {
String errMsg = "";
for (GlusterServer server : glusterServers) {
@@ -161,7 +189,7 @@ public class GlusterServersResource extends AbstractServersResource {
return errMsg;
}
- public List<GlusterServer> getGlusterServers(String clusterName, GlusterServer onlineServer) {
+ private List<GlusterServer> getGlusterServers(String clusterName, GlusterServer onlineServer, boolean fetchDetails) {
List<GlusterServer> glusterServers;
try {
glusterServers = glusterUtil.getGlusterServers(onlineServer);
@@ -174,11 +202,18 @@ public class GlusterServersResource extends AbstractServersResource {
glusterServers = glusterUtil.getGlusterServers(onlineServer);
}
+
+ if (fetchDetails) {
+ String errMsg = fetchDetailsOfServers(glusterServers, onlineServer);
+ if (!errMsg.isEmpty()) {
+ throw new GlusterRuntimeException("Couldn't fetch details for server(s): " + errMsg);
+ }
+ }
return glusterServers;
}
@GET
- @Path("{serverName}")
+ @Path("{" + PATH_PARAM_SERVER_NAME + "}")
@Produces(MediaType.APPLICATION_XML)
public Response getGlusterServerXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
@PathParam(PATH_PARAM_SERVER_NAME) String serverName) {
@@ -186,7 +221,7 @@ public class GlusterServersResource extends AbstractServersResource {
}
@GET
- @Path("{serverName}")
+ @Path("{" + PATH_PARAM_SERVER_NAME + "}")
@Produces(MediaType.APPLICATION_JSON)
public Response getGlusterServerJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
@PathParam(PATH_PARAM_SERVER_NAME) String serverName) {
@@ -428,20 +463,57 @@ public class GlusterServersResource extends AbstractServersResource {
return errorResponse(e.getMessage());
}
}
+
+ @GET
+ @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);
+ }
- private void setGlusterUtil(GlusterUtil glusterUtil) {
- this.glusterUtil = glusterUtil;
+ @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);
}
- public static void main(String[] args) {
- GlusterServersResource glusterServersResource = new GlusterServersResource();
- GlusterUtil glusterUtil = new GlusterUtil();
- glusterUtil.setSshUtil(new SshUtil());
- glusterServersResource.setGlusterUtil(glusterUtil);
- // System.out.println(glusterServersResource.getServerDetails("127.0.0.1").size());
+ @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);
+ }
- // To add a server
- // GlusterServerResponse response = glusterServersResource.addServer("my-server");
- // System.out.println(response.getData().getName());
+ @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);
+ }
+
+ private Response getAggregaredPerformanceData(String clusterName, String type, 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 + "]");
+ }
+ }
+
+ private Response getPerformanceData(String serverName, String type, String mediaType) {
+ 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);
+ } else if(type.equals(STATISTICS_TYPE_MEMORY)) {
+ return okResponse(serverUtil.fetchCPUUsageData(serverName), mediaType);
+ } else {
+ return badRequestResponse("Server Statistics for [" + type + "] not supported! 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/resources/v1_0/ValidationExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java
new file mode 100644
index 00000000..cab6cc62
--- /dev/null
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ValidationExceptionMapper.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.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<GlusterValidationException> {
+
+ /* (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/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java
index ae4bc919..55be59b4 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
@@ -22,6 +22,8 @@ package com.gluster.storage.management.server.utils;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
import java.util.List;
import javax.servlet.ServletContext;
@@ -29,12 +31,15 @@ import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
+import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
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.Status;
import com.gluster.storage.management.core.response.GenericResponse;
@@ -48,6 +53,8 @@ public class ServerUtil {
@Autowired
private SshUtil sshUtil;
+
+ private static final Logger logger = Logger.getLogger(ServerUtil.class);
private static final String SCRIPT_DIR = "scripts";
private static final String SCRIPT_COMMAND = "python";
@@ -216,4 +223,103 @@ public class ServerUtil {
public Status getDiskForDir(String serverName, String brickDir) {
return (Status) executeOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class);
}
+
+ public ServerStats fetchCPUUsageData(String serverName) {
+ 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>NaN</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(String serverName : serverNames) {
+ try {
+ ServerStats stats = fetchCPUUsageData(serverName);
+ if(removeOnlineServer) {
+ serverNames.remove(serverName);
+ }
+ } 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 Object 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) {
+ int[][] dataCount = new int[aggregatedStats.getMetadata().getRowCount()][aggregatedStats.getMetadata()
+ .getLegend().size()];
+
+ for (String serverName : serverNames) {
+ ServerStats serverStats;
+ try {
+ serverStats = fetchCPUUsageData(serverName);
+ } catch(Exception e) {
+ // server might be offline - continue with next one
+ logger.warn("Couldn't fetch CPU stats from server [" + serverName + "]!", e);
+ continue;
+ }
+ List<ServerStatsRow> serverStatsRows = addServerStats(serverStats, aggregatedStats, 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]);
+ }
+ }
+ }
+
+ /**
+ *
+ * @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");
+ System.out.println(stats.getMetadata().getLegend());
+ }
}