diff options
author | Selvasundaram <selvam@gluster.com> | 2011-08-19 20:36:23 +0530 |
---|---|---|
committer | Selvasundaram <selvam@gluster.com> | 2011-08-19 20:36:23 +0530 |
commit | a0629a6d156f5f660c420ca4844361506f8b4a51 (patch) | |
tree | a83bcb64591360601c4602abfb6844b02cbd6bb2 /src/com.gluster.storage.management.gateway | |
parent | 6428f0db1ef50d9a27a40d07e8a1208263da48d1 (diff) | |
parent | e206fd77a7df5b9ee13b34f48dd3f78b119da460 (diff) |
Merge branch 'master' of github.com:gluster/console
Diffstat (limited to 'src/com.gluster.storage.management.gateway')
6 files changed, 150 insertions, 26 deletions
diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java index 508a3029..3403bf57 100644 --- a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java @@ -54,8 +54,8 @@ public class VolumeOptionsDefaults { * @return list of volume option information objects */ public List<VolumeOptionInfo> getDefaults(String clusterName) { - // return getVolumeOptionsInfo(clusterName); - return getVolumeOptionsInfo(); + return getVolumeOptionsInfo(clusterName); + // return getVolumeOptionsInfo(); } diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java index e028cadc..e119cd83 100644 --- a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java @@ -282,8 +282,6 @@ public class VolumesResource extends AbstractResource { @Path(RESOURCE_DEFAULT_OPTIONS) @Produces(MediaType.APPLICATION_XML) public VolumeOptionInfoListResponse getDefaultOptionsXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - // TODO: Fetch all volume options with their default values from GlusterFS - // whenever such a CLI command is made available in GlusterFS return new VolumeOptionInfoListResponse(Status.STATUS_SUCCESS, volumeOptionsDefaults.getDefaults(clusterName)); } @@ -291,8 +289,6 @@ public class VolumesResource extends AbstractResource { @Path(RESOURCE_DEFAULT_OPTIONS) @Produces(MediaType.APPLICATION_JSON) public VolumeOptionInfoListResponse getDefaultOptionsJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - // TODO: Fetch all volume options with their default values from GlusterFS - // whenever such a CLI command is made available in GlusterFS return new VolumeOptionInfoListResponse(Status.STATUS_SUCCESS, volumeOptionsDefaults.getDefaults(clusterName)); } diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java index d9c12f25..d5167e21 100644 --- a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java @@ -69,20 +69,16 @@ public abstract class AbstractStatsFactory implements StatsFactory { int columnCount = aggregatedStats.getMetadata().getLegend().size(); int[][] dataCount = initDataCountArray(rowCount, columnCount); - for (String serverName : serverNames) { - try { - // fetch the stats and add to aggregated stats - addServerStats(fetchStats(serverName, period), aggregatedStats, dataCount); - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch performance stats from server [" + serverName + "]!", e); - continue; - } + List<ServerStats> allStats = serverUtil.executeScriptOnServers(serverNames, getStatsScriptName() + " " + period, ServerStats.class, false); + + for (ServerStats stats : allStats) { + // add to aggregated stats + addServerStats(stats, aggregatedStats, dataCount); } averageAggregatedStats(aggregatedStats, dataCount); } - + /** * * @param statsToBeAdded diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java index ee5eb050..efac10fb 100644 --- a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java @@ -18,6 +18,8 @@ *******************************************************************************/ package com.gluster.storage.management.gateway.utils; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.apache.log4j.Logger; @@ -28,6 +30,7 @@ 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; +import com.gluster.storage.management.core.utils.ProcessUtil; /** * @@ -85,23 +88,64 @@ public class NetworkStatsFactory extends AbstractStatsFactory { return; } - for (String serverName : serverNames) { + List<ServerStats> statsList = Collections.synchronizedList(new ArrayList<ServerStats>()); + try { + List<Thread> threads = createThreads(serverNames, period, statsList); + ProcessUtil.waitForThreads(threads); + for(ServerStats stats : statsList) { + addServerStats(stats, aggregatedStats, dataCount); + } + } catch (InterruptedException e) { + String errMsg = "Exception while aggregating network statistics on servers [" + serverNames + + "] for period [" + period + "]! Error: [" + e.getMessage() + "]"; + logger.error(errMsg, e); + throw new GlusterRuntimeException(errMsg, e); + } + + averageAggregatedStats(aggregatedStats, dataCount); + } + + private <T> List<Thread> createThreads(List<String> serverNames, String period, List<ServerStats> statsList) + throws InterruptedException { + List<Thread> threads = new ArrayList<Thread>(); + for (int i = serverNames.size()-1; i >= 0 ; i--) { + Thread thread = new NetworkStatsThread(serverNames.get(i), period, statsList); + threads.add(thread); + thread.start(); + if(i >= 5 && i % 5 == 0) { + // After every 5 servers, wait for 1 second so that we don't end up with too many running threads + Thread.sleep(1000); + } + } + return threads; + } + + public class NetworkStatsThread extends Thread { + private String serverName; + private String period; + private List<ServerStats> statsList; + + public NetworkStatsThread(String serverName, String period, List<ServerStats> statsList) { + this.serverName = serverName; + this.period = period; + this.statsList = statsList; + } + + @Override + public void run() { try { Server server = new Server(serverName); serverUtil.fetchServerDetails(server); for (NetworkInterface networkInterface : server.getNetworkInterfaces()) { // fetch the stats and add to aggregated stats - addServerStats(fetchStats(serverName, period, networkInterface.getName()), aggregatedStats, dataCount); + statsList.add(fetchStats(serverName, period, networkInterface.getName())); } } catch(Exception e) { // server might be offline - continue with next one logger.warn("Couldn't fetch Network stats from server [" + serverName + "]!", e); - continue; } } - - averageAggregatedStats(aggregatedStats, dataCount); } @Override diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java index 3b3724da..f762baf5 100644 --- a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java @@ -24,6 +24,7 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import javax.servlet.ServletContext; @@ -76,9 +77,7 @@ public class ServerUtil { command.add(SCRIPT_COMMAND); command.add(getScriptPath(scriptName)); command.addAll(arguments); - //TODO: Remove this debug log before moving to production - // logger.info("Executing script [" + command + "] on server gateway."); - return new ProcessUtil().executeCommand(runInForeground, command); + return ProcessUtil.executeCommand(runInForeground, command); } private String getScriptPath(String scriptName) { @@ -122,6 +121,94 @@ public class ServerUtil { } /** + * Executes given script on all given servers in parallel, collects the output in objects of given class, and + * returns a list of all returned objects. + * + * @param serverNames + * @param scriptWithArgs + * @param expectedClass + * @param failOnError + * If true, an exception will be thrown as soon as the script execution fails on any of the servers. If + * false, the exception will be caught and logged. Execution on all other servers will continue. + * @return + */ + public <T> List<T> executeScriptOnServers(List<String> serverNames, String scriptWithArgs, + Class<T> expectedClass, boolean failOnError) { + List<T> result = Collections.synchronizedList(new ArrayList<T>()); + try { + List<Thread> threads = createScriptExecutionThreads(serverNames, getRemoteScriptDir() + File.separator + + scriptWithArgs, expectedClass, result, failOnError); + ProcessUtil.waitForThreads(threads); + return result; + } catch (InterruptedException e) { + String errMsg = "Exception while executing script [" + scriptWithArgs + "] on servers [" + serverNames + "]! Error: [" + e.getMessage() + "]"; + logger.error(errMsg, e); + throw new GlusterRuntimeException(errMsg, e); + } + } + + /** + * Creates threads that will run in parallel and execute the given command on each of the given servers + * + * @param serverNames + * @param commandWithArgs + * @param expectedClass + * @param result + * @param failOnError + * If true, an exception will be thrown as soon as the script execution fails on any of the servers. If + * false, the exception will be caught and logged. Execution on all other servers will continue. + * @return + * @throws InterruptedException + */ + private <T> List<Thread> createScriptExecutionThreads(List<String> serverNames, String commandWithArgs, Class<T> expectedClass, List<T> result, + boolean failOnError) + throws InterruptedException { + List<Thread> threads = new ArrayList<Thread>(); + for (int i = serverNames.size()-1; i >= 0 ; i--) { + Thread thread = new RemoteExecutionThread<T>(serverNames.get(i), commandWithArgs, expectedClass, result, failOnError); + threads.add(thread); + thread.start(); + if(i >= 5 && i % 5 == 0) { + // After every 5 servers, wait for 1 second so that we don't end up with too many running threads + Thread.sleep(1000); + } + } + return threads; + } + + + public class RemoteExecutionThread<T> extends Thread { + private String serverName; + private String commandWithArgs; + private List<T> result; + private Class<T> expectedClass; + private boolean failOnError = false; + + public RemoteExecutionThread(String serverName, String commandWithArgs, Class<T> expectedClass, List<T> result, + boolean failOnError) { + this.serverName = serverName; + this.commandWithArgs = commandWithArgs; + this.result = result; + this.expectedClass = expectedClass; + this.failOnError = failOnError; + } + + @Override + public void run() { + try { + result.add(executeOnServer(true, serverName, commandWithArgs, expectedClass)); + } catch(Exception e) { + String errMsg = "Couldn't execute command [" + commandWithArgs + "] on [" + serverName + "]!"; + logger.error(errMsg, e); + if(failOnError) { + throw new GlusterRuntimeException(errMsg, e); + } + } + } + } + + + /** * Executes given script on given server. Since the remote server may contain multiple versions of backend, this * method will invoke the script present in directory of same version as the gateway. * @@ -137,8 +224,6 @@ public class ServerUtil { */ public <T> T executeScriptOnServer(boolean runInForeground, String serverName, String scriptWithArgs, Class<T> expectedClass) { - //TODO: Remove this debug log before moving to production - // logger.info("Executing script [" + scriptWithArgs + "] on server [" + serverName + "]"); return executeOnServer(runInForeground, serverName, getRemoteScriptDir() + File.separator + scriptWithArgs, expectedClass); } diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java index a5735cae..3399dc3b 100644 --- a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java @@ -334,6 +334,7 @@ public class SshUtil { * @return Result of remote execution */ public ProcessResult executeRemoteWithPassword(String serverName, String command) { + logger.info("Executing command [" + command + "] on server [" + serverName + "] with default password."); Connection conn = getConnectionWithPassword(serverName); ProcessResult result = executeCommand(conn, command); // we don't cache password based connections. hence the connection must be closed. @@ -366,8 +367,10 @@ public class SshUtil { */ public ProcessResult executeRemote(String serverName, String command) { try { + logger.info("Executing command [" + command + "] on server [" + serverName + "] with public key authentication"); return executeRemoteWithPubKey(serverName, command); } catch(ConnectionException e) { + logger.warn("Couldn't execute command with public key authentication, will try with default password.", e); // Couldn't connect with public key. Try with default password. return executeRemoteWithPassword(serverName, command); } |