summaryrefslogtreecommitdiffstats
path: root/src/com.gluster.storage.management.gateway
diff options
context:
space:
mode:
authorSelvasundaram <selvam@gluster.com>2011-08-19 20:36:23 +0530
committerSelvasundaram <selvam@gluster.com>2011-08-19 20:36:23 +0530
commita0629a6d156f5f660c420ca4844361506f8b4a51 (patch)
treea83bcb64591360601c4602abfb6844b02cbd6bb2 /src/com.gluster.storage.management.gateway
parent6428f0db1ef50d9a27a40d07e8a1208263da48d1 (diff)
parente206fd77a7df5b9ee13b34f48dd3f78b119da460 (diff)
Merge branch 'master' of github.com:gluster/console
Diffstat (limited to 'src/com.gluster.storage.management.gateway')
-rw-r--r--src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java4
-rw-r--r--src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java4
-rw-r--r--src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java16
-rw-r--r--src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java54
-rw-r--r--src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java95
-rw-r--r--src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java3
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);
}