summaryrefslogtreecommitdiffstats
path: root/src/com.gluster.storage.management.server
diff options
context:
space:
mode:
authorTim <timothyasir@gluster.com>2011-07-01 14:47:05 +0530
committerTim <timothyasir@gluster.com>2011-07-01 14:47:05 +0530
commit9cdc7095308011332392ddd040b34106ef3abd6a (patch)
treea4b6d72ef81611be53bf46f940cd8ff70eadbf15 /src/com.gluster.storage.management.server
parent19ed9b4866499d9c264c8db8fc616fb5a5e36ce3 (diff)
parent40d4024c47ca1e1e15e2500a5412791d364bd8b0 (diff)
Merge remote branch 'upstream/master'
Diffstat (limited to 'src/com.gluster.storage.management.server')
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java45
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java19
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java1
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java100
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java247
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java122
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java63
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java218
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java68
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java114
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java188
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java153
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java111
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java17
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java16
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java76
-rw-r--r--src/com.gluster.storage.management.server/src/log4j.properties7
-rw-r--r--src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml14
18 files changed, 1127 insertions, 452 deletions
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java
index ee65add0..feef8b3e 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java
@@ -65,21 +65,32 @@ public class AbstractResource {
* Creates a response with HTTP status code of 202 (accepted), also setting the location header to given location.
* This is typically done while triggering long running tasks
*
- * @param uriElements
- * URI Elements to be appended to the base URI
+ * @param locationURI
+ * URI to be appended to the base URI
* @return the {@link Response} object
*/
- protected Response acceptedResponse(Object...uriElements) {
- return Response.status(Status.ACCEPTED).location(createAbsoluteURI(uriElements)).build();
+ protected Response acceptedResponse(String locationURI) {
+ return Response.status(Status.ACCEPTED).location(createAbsoluteURI(locationURI)).build();
+ }
+
+ /**
+ * Creates a response with HTTP status code of 404 (not found), also setting the given message in the response body
+ *
+ * @param message
+ * Message to be set in the response body
+ * @return the {@link Response} object
+ */
+ protected Response notFoundResponse(String message) {
+ return Response.status(Status.NOT_FOUND).type(MediaType.TEXT_HTML).entity(message).build();
}
/**
* Creates a new URI that is relative to the <b>base URI</b> of the application
- * @param uriElements URI Elements to be appended to the base URI
+ * @param uriString URI String to be appended to the base URI
* @return newly created URI
*/
- private URI createAbsoluteURI(Object[] uriElements) {
- return uriInfo.getBaseUriBuilder().build(uriElements);
+ private URI createAbsoluteURI(String uriString) {
+ return uriInfo.getBaseUriBuilder().path(uriString).build();
}
/**
@@ -123,6 +134,15 @@ public class AbstractResource {
protected Response badRequestResponse(String errMessage) {
return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_HTML).entity(errMessage).build();
}
+
+ /**
+ * Creates a response with HTTP status code of 401 (unauthorized)
+ *
+ * @return the {@link Response} object
+ */
+ protected Response unauthorizedResponse() {
+ return Response.status(Status.UNAUTHORIZED).build();
+ }
/**
* Creates an OK response and sets the entity in the response body.
@@ -138,6 +158,17 @@ public class AbstractResource {
}
/**
+ * Creates an OK response without any entity in the response body.
+ *
+ * @param mediaType
+ * Media type to be set on the response
+ * @return the {@link Response} object
+ */
+ protected Response okResponse(String mediaType) {
+ return Response.ok().type(mediaType).build();
+ }
+
+ /**
* Creates a streaming output response and sets the given streaming output in the response. Typically used for
* "download" requests
*
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java
index 0bc0f061..dd6e2804 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java
@@ -20,9 +20,6 @@
*/
package com.gluster.storage.management.server.resources;
-import com.gluster.storage.management.core.exceptions.GlusterRuntimeException;
-import com.gluster.storage.management.core.model.Server;
-import com.gluster.storage.management.core.model.Status;
import com.gluster.storage.management.server.utils.GlusterUtil;
import com.gluster.storage.management.server.utils.ServerUtil;
import com.sun.jersey.api.core.InjectParam;
@@ -37,19 +34,5 @@ public class AbstractServersResource extends AbstractResource {
@InjectParam
protected GlusterUtil glusterUtil;
- /**
- * Fetch details of the given server. The server name must be populated in the object before calling this method.
- *
- * @param server
- * Server whose details are to be fetched
- */
- protected void fetchServerDetails(Server server) {
- // fetch standard server details like cpu, disk, memory details
- Object response = serverUtil.executeOnServer(true, server.getName(), "get_server_details.py --only-data-disks", Server.class);
- if (response instanceof Status) {
- // TODO: check if this happened because the server is not reachable, and if yes, set it's status as offline
- throw new GlusterRuntimeException(((Status)response).getMessage());
- }
- server.copyFrom((Server) response); // Update the details in <Server> object
- }
+ // TODO: Remove this class!
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java
index 2ce23a4e..4c834973 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java
@@ -106,7 +106,6 @@ public class ClustersResource extends AbstractResource {
return badRequestResponse("Server [" + knownServer + "] is already present in cluster ["
+ mappedCluster.getName() + "]!");
}
-
try {
clusterService.registerCluster(clusterName, knownServer);
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java
index aba88d82..283ab147 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java
@@ -18,6 +18,8 @@
*******************************************************************************/
package com.gluster.storage.management.server.resources;
+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.RESOURCE_PATH_DISCOVERED_SERVERS;
import java.util.ArrayList;
@@ -29,16 +31,13 @@ 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;
import org.springframework.stereotype.Component;
-import com.gluster.storage.management.core.constants.CoreConstants;
-import com.gluster.storage.management.core.model.Response;
import com.gluster.storage.management.core.model.Server;
-import com.gluster.storage.management.core.model.Status;
-import com.gluster.storage.management.core.response.GenericResponse;
import com.gluster.storage.management.core.response.ServerListResponse;
-import com.gluster.storage.management.core.response.StringListResponse;
+import com.gluster.storage.management.core.response.ServerNameListResponse;
import com.sun.jersey.spi.resource.Singleton;
@Component
@@ -67,57 +66,76 @@ public class DiscoveredServersResource extends AbstractServersResource {
@GET
@Produces(MediaType.APPLICATION_XML)
- @SuppressWarnings("rawtypes")
- public Response getDiscoveredServers(@QueryParam("details") Boolean getDetails) {
- if(getDetails != null && getDetails == true) {
- return getDiscoveredServerDetails();
+ public Response getDiscoveredServersXML(@QueryParam(QUERY_PARAM_DETAILS) Boolean details) {
+ return getDiscoveredServersResponse(details, MediaType.APPLICATION_XML);
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getDiscoveredServersJSON(@QueryParam(QUERY_PARAM_DETAILS) Boolean details) {
+ return getDiscoveredServersResponse(details, MediaType.APPLICATION_JSON);
+ }
+
+ private Response getDiscoveredServersResponse(Boolean details, String mediaType) {
+ if(details != null && details == true) {
+ try {
+ List<Server> discoveredServers = getDiscoveredServerDetails();
+ return okResponse(new ServerListResponse(discoveredServers), mediaType);
+ } catch(Exception e) {
+ return errorResponse(e.getMessage());
+ }
+ } else {
+ return okResponse(new ServerNameListResponse(getDiscoveredServerNames()), mediaType);
}
- return new StringListResponse(getDiscoveredServerNames());
}
- private ServerListResponse getDiscoveredServerDetails() {
+ private List<Server> getDiscoveredServerDetails() {
List<Server> discoveredServers = new ArrayList<Server>();
- List<String> serverNames = getDiscoveredServerNames();
- GenericResponse<Server> discoveredServerResponse;
- int errCount = 0;
- StringBuilder errMsg = new StringBuilder("Couldn't fetch details for server(s): ");
- for (String serverName : serverNames) {
- discoveredServerResponse = getDiscoveredServer(serverName);
- if (!discoveredServerResponse.getStatus().isSuccess()) {
- errMsg.append(CoreConstants.NEWLINE + serverName + " : " + discoveredServerResponse.getStatus());
- errCount++;
- } else {
- discoveredServers.add(discoveredServerResponse.getData());
+ for (String serverName : getDiscoveredServerNames()) {
+ try {
+ discoveredServers.add(getDiscoveredServer(serverName));
+ } catch(Exception e) {
+ // TODO: Log the exception
+ // continue with next discovered server
}
}
- Status status = null;
- if(errCount == 0) {
- status = new Status(Status.STATUS_CODE_SUCCESS, "Success");
- } else if(errCount == serverNames.size()) {
- status = new Status(Status.STATUS_CODE_FAILURE, errMsg.toString());
- } else {
- status = new Status(Status.STATUS_CODE_PART_SUCCESS, errMsg.toString());
- }
- return new ServerListResponse(status, discoveredServers);
+ return discoveredServers;
}
- @Path("/{serverName}")
+ @Path("{" + PATH_PARAM_SERVER_NAME + "}")
@GET
@Produces(MediaType.APPLICATION_XML)
- public GenericResponse<Server> getDiscoveredServer(@PathParam("serverName") String serverName) {
- Server server = new Server(serverName);
+ public Response getDiscoveredServerXML(@PathParam(PATH_PARAM_SERVER_NAME) String serverName) {
+ return getDiscoveredServerResponse(serverName, MediaType.APPLICATION_XML);
+ }
+
+ @Path("{" + PATH_PARAM_SERVER_NAME + "}")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getDiscoveredServerJSON(@PathParam(PATH_PARAM_SERVER_NAME) String serverName) {
+ return getDiscoveredServerResponse(serverName, MediaType.APPLICATION_JSON);
+ }
+
+ private Response getDiscoveredServerResponse(String serverName, String mediaType) {
+ if(serverName == null || serverName.isEmpty()) {
+ return badRequestResponse("Server name must not be empty!");
+ }
try {
- fetchServerDetails(server);
+ return okResponse(getDiscoveredServer(serverName), mediaType);
} catch (Exception e) {
- return new GenericResponse<Server>(new Status(e), null);
+ // TODO: Log the exception
+ return errorResponse(e.getMessage());
}
- return new GenericResponse<Server>(Status.STATUS_SUCCESS, server);
+ }
+
+ private Server getDiscoveredServer(String serverName) {
+ Server server = new Server(serverName);
+ serverUtil.fetchServerDetails(server);
+ return server;
}
public static void main(String[] args) {
- StringListResponse listResponse = (StringListResponse)new DiscoveredServersResource().getDiscoveredServers(false);
- for (String server : listResponse.getData()) {
- System.out.println(server);
- }
+ Response response = (Response)new DiscoveredServersResource().getDiscoveredServersXML(false);
+ System.out.println(response.getEntity());
}
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java
index 6e15e106..a9ef7fbb 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java
@@ -18,13 +18,14 @@
*******************************************************************************/
package com.gluster.storage.management.server.resources;
-import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_CLUSTER_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME;
-import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SOURCE;
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.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_TASKS;
import java.util.ArrayList;
import java.util.List;
@@ -33,6 +34,7 @@ import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -43,17 +45,16 @@ 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.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.GlusterServer;
import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS;
-import com.gluster.storage.management.core.model.Status;
import com.gluster.storage.management.core.response.GlusterServerListResponse;
-import com.gluster.storage.management.core.response.GlusterServerResponse;
-import com.gluster.storage.management.core.utils.LRUCache;
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;
@@ -65,128 +66,90 @@ import com.sun.jersey.spi.resource.Singleton;
public class GlusterServersResource extends AbstractServersResource {
public static final String HOSTNAMETAG = "hostname:";
- private LRUCache<String, GlusterServer> clusterServerCache = new LRUCache<String, GlusterServer>(3);
-
+
@InjectParam
private DiscoveredServersResource discoveredServersResource;
-
+
+ @InjectParam
+ private TasksResource taskResource;
+
@Autowired
private ClusterService clusterService;
-
+
@Autowired
private SshUtil sshUtil;
-
+
protected void fetchServerDetails(GlusterServer server) {
try {
server.setStatus(SERVER_STATUS.ONLINE);
- super.fetchServerDetails(server);
- } catch(ConnectionException e) {
+ serverUtil.fetchServerDetails(server);
+ } catch (ConnectionException e) {
server.setStatus(SERVER_STATUS.OFFLINE);
}
}
-
- public GlusterServer getOnlineServer(String clusterName) {
- return getOnlineServer(clusterName, "");
- }
-
- // uses cache
- public GlusterServer getOnlineServer(String clusterName, String exceptServerName) {
- GlusterServer server = clusterServerCache.get(clusterName);
- if(server != null && !server.getName().equals(exceptServerName)) {
- return server;
- }
-
- return getNewOnlineServer(clusterName, exceptServerName);
- }
- public GlusterServer getNewOnlineServer(String clusterName) {
- return getNewOnlineServer(clusterName, "");
- }
- // Doesn't use cache
- public GlusterServer getNewOnlineServer(String clusterName, String exceptServerName) {
- ClusterInfo cluster = clusterService.getCluster(clusterName);
- if(cluster == null) {
- return null;
- }
-
- for(ServerInfo serverInfo : cluster.getServers()) {
- GlusterServer server = new GlusterServer(serverInfo.getName());
- fetchServerDetails(server);
- if(server.isOnline() && !server.getName().equals(exceptServerName)) {
- // server is online. add it to cache and return
- clusterServerCache.put(clusterName, server);
- return server;
- }
- }
-
- // no online server found.
- return null;
- }
-
@GET
@Produces(MediaType.APPLICATION_JSON)
- public Response getGlusterServersJSON(
- @PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) {
+ public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) {
return getGlusterServers(clusterName, MediaType.APPLICATION_JSON);
}
@GET
@Produces(MediaType.APPLICATION_XML)
- public Response getGlusterServersXML(
- @PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) {
+ public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) {
return getGlusterServers(clusterName, MediaType.APPLICATION_XML);
}
public Response getGlusterServers(String clusterName, String mediaType) {
List<GlusterServer> glusterServers = new ArrayList<GlusterServer>();
-
+
if (clusterName == null || clusterName.isEmpty()) {
return badRequestResponse("Cluster name must not be empty!");
}
ClusterInfo cluster = clusterService.getCluster(clusterName);
if (cluster == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
- if(cluster.getServers().size() == 0) {
+ if (cluster.getServers().size() == 0) {
return okResponse(new GlusterServerListResponse(glusterServers), mediaType);
}
-
- GlusterServer onlineServer = getOnlineServer(clusterName);
+
+ 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) {
+ } catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
try {
glusterServers = getGlusterServers(clusterName, onlineServer);
- } catch(Exception e1) {
+ } catch (Exception e1) {
return errorResponse(e1.getMessage());
}
- } catch(Exception e) {
+ } catch (Exception e) {
return errorResponse(e.getMessage());
}
-
+
String errMsg = fetchDetailsOfServers(glusterServers, onlineServer);
- if(!errMsg.isEmpty()) {
+ if (!errMsg.isEmpty()) {
return errorResponse("Couldn't fetch details for server(s): " + errMsg);
}
-
+
return okResponse(new GlusterServerListResponse(glusterServers), mediaType);
}
public String fetchDetailsOfServers(List<GlusterServer> glusterServers, GlusterServer onlineServer) {
String errMsg = "";
-
+
for (GlusterServer server : glusterServers) {
if (server.getStatus() == SERVER_STATUS.ONLINE && !server.getName().equals(onlineServer.getName())) {
try {
@@ -203,13 +166,13 @@ public class GlusterServersResource extends AbstractServersResource {
List<GlusterServer> glusterServers;
try {
glusterServers = glusterUtil.getGlusterServers(onlineServer);
- } catch(ConnectionException e) {
+ } catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = getNewOnlineServer(clusterName);
- if(onlineServer == null) {
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
+ if (onlineServer == null) {
throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
}
-
+
glusterServers = glusterUtil.getGlusterServers(onlineServer);
}
return glusterServers;
@@ -218,8 +181,7 @@ public class GlusterServersResource extends AbstractServersResource {
@GET
@Path("{serverName}")
@Produces(MediaType.APPLICATION_XML)
- public Response getGlusterServerXML(
- @PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
+ public Response getGlusterServerXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
@PathParam(PATH_PARAM_SERVER_NAME) String serverName) {
return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_XML);
}
@@ -227,8 +189,7 @@ public class GlusterServersResource extends AbstractServersResource {
@GET
@Path("{serverName}")
@Produces(MediaType.APPLICATION_JSON)
- public Response getGlusterServerJSON(
- @PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
+ public Response getGlusterServerJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
@PathParam(PATH_PARAM_SERVER_NAME) String serverName) {
return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_JSON);
}
@@ -236,7 +197,7 @@ public class GlusterServersResource extends AbstractServersResource {
private Response getGlusterServerResponse(String clusterName, String serverName, String mediaType) {
try {
return okResponse(getGlusterServer(clusterName, serverName), mediaType);
- } catch(Exception e) {
+ } catch (Exception e) {
return errorResponse(e.getMessage());
}
}
@@ -255,93 +216,93 @@ public class GlusterServersResource extends AbstractServersResource {
throw new GlusterRuntimeException("Cluster [" + clusterName + "] not found!");
}
- GlusterServer onlineServer = getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
}
-
+
GlusterServer server = null;
try {
server = glusterUtil.getGlusterServer(onlineServer, serverName);
- } catch(ConnectionException e) {
+ } catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
}
server = glusterUtil.getGlusterServer(onlineServer, serverName);
}
-
- if(server.isOnline()) {
+
+ if (server.isOnline()) {
fetchServerDetails(server);
}
return server;
}
private void performAddServer(String clusterName, String serverName) {
- GlusterServer onlineServer = getOnlineServer(clusterName);
- if(onlineServer == null) {
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
+ if (onlineServer == null) {
throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]");
}
-
+
try {
glusterUtil.addServer(onlineServer.getName(), serverName);
- } catch(ConnectionException e) {
+ } catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = getNewOnlineServer(clusterName);
- if(onlineServer == null) {
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
+ if (onlineServer == null) {
throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]");
}
-
+
glusterUtil.addServer(serverName, onlineServer.getName());
}
}
-
+
@POST
public Response addServer(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
@FormParam(FORM_PARAM_SERVER_NAME) String serverName) {
- if(clusterName == null || clusterName.isEmpty()) {
+ if (clusterName == null || clusterName.isEmpty()) {
return badRequestResponse("Cluster name must not be empty!");
}
-
- if(serverName == null || serverName.isEmpty()) {
+
+ if (serverName == null || serverName.isEmpty()) {
return badRequestResponse("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!");
}
-
+
ClusterInfo cluster = clusterService.getCluster(clusterName);
if (cluster == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
-
+
boolean publicKeyInstalled = sshUtil.isPublicKeyInstalled(serverName);
- if(!publicKeyInstalled && !sshUtil.hasDefaultPassword(serverName)) {
+ if (!publicKeyInstalled && !sshUtil.hasDefaultPassword(serverName)) {
// public key not installed, default password doesn't work. return with error.
return errorResponse("Gluster Management Gateway uses the default password to set up keys on the server."
+ CoreConstants.NEWLINE + "However it seems that the password on server [" + serverName
+ "] has been changed manually." + CoreConstants.NEWLINE
+ "Please reset it back to the standard default password and try again.");
}
-
+
List<ServerInfo> servers = cluster.getServers();
- if(servers != null && !servers.isEmpty()) {
+ if (servers != null && !servers.isEmpty()) {
// cluster has at least one existing server, so that peer probe can be performed
try {
performAddServer(clusterName, serverName);
- } catch(Exception e) {
+ } catch (Exception e) {
return errorResponse(e.getMessage());
}
} else {
// this is the first server to be added to the cluster, which means no
// gluster CLI operation required. just add it to the cluster-server mapping
}
-
+
try {
// add the cluster-server mapping
clusterService.mapServerToCluster(clusterName, serverName);
} catch (Exception e) {
return errorResponse(e.getMessage());
}
-
+
// since the server is added to a cluster, it should not more be considered as a
// discovered server available to other clusters
discoveredServersResource.removeDiscoveredServer(serverName);
@@ -366,40 +327,39 @@ public class GlusterServersResource extends AbstractServersResource {
if (clusterName == null || clusterName.isEmpty()) {
return badRequestResponse("Cluster name must not be empty!");
}
-
- if(serverName == null || serverName.isEmpty()) {
+
+ if (serverName == null || serverName.isEmpty()) {
return badRequestResponse("Server name must not be empty!");
}
-
+
ClusterInfo cluster = clusterService.getCluster(clusterName);
- if(cluster == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ if (cluster == null) {
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
List<ServerInfo> servers = cluster.getServers();
- if(servers == null || servers.isEmpty() || !containsServer(servers, serverName)) {
- return badRequestResponse("Server [" + serverName + "] is not attached to cluster ["
- + clusterName + "]!");
+ if (servers == null || servers.isEmpty() || !containsServer(servers, serverName)) {
+ return badRequestResponse("Server [" + serverName + "] is not attached to cluster [" + clusterName + "]!");
}
-
- if(servers.size() == 1) {
+
+ if (servers.size() == 1) {
// Only one server mapped to the cluster, no "peer detach" required.
// remove the cached online server for this cluster if present
- clusterServerCache.remove(clusterName);
+ clusterService.removeOnlineServer(clusterName);
} else {
try {
removeServerFromCluster(clusterName, serverName);
- } catch(Exception e) {
+ } catch (Exception e) {
return errorResponse(e.getMessage());
}
- }
-
+ }
+
return noContentResponse();
}
-
+
private void removeServerFromCluster(String clusterName, String serverName) {
// get an online server that is not same as the server being removed
- GlusterServer onlineServer = getOnlineServer(clusterName, serverName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName, serverName);
if (onlineServer == null) {
throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]");
}
@@ -408,34 +368,63 @@ public class GlusterServersResource extends AbstractServersResource {
glusterUtil.removeServer(onlineServer.getName(), serverName);
} catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = getNewOnlineServer(clusterName, serverName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName, serverName);
if (onlineServer == null) {
throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]");
}
glusterUtil.removeServer(onlineServer.getName(), serverName);
}
-
- if(onlineServer.getName().equals(serverName)) {
+
+ if (onlineServer.getName().equals(serverName)) {
// since the cached server has been removed from the cluster, remove it from the cache
- clusterServerCache.remove(clusterName);
+ clusterService.removeOnlineServer(clusterName);
}
-
+
clusterService.unmapServerFromCluster(clusterName, serverName);
-
- // since the server is removed from the cluster, it is now available to be added to other clusters.
+
+ // since the server is removed from the cluster, it is now available to be added to other clusters.
// Hence add it back to the discovered servers list.
- discoveredServersResource.addDiscoveredServer(serverName);
+ discoveredServersResource.addDiscoveredServer(serverName);
}
private boolean containsServer(List<ServerInfo> servers, String serverName) {
- for(ServerInfo server : servers) {
- if(server.getName().toUpperCase().equals(serverName.toUpperCase())) {
+ for (ServerInfo server : servers) {
+ if (server.getName().toUpperCase().equals(serverName.toUpperCase())) {
return true;
}
}
return false;
}
+ @PUT
+ @Produces(MediaType.APPLICATION_XML)
+ @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_DISKS + "/{" + PATH_PARAM_DISK_NAME + "}")
+ public Response initializeDisk(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
+ @PathParam(PATH_PARAM_SERVER_NAME) String serverName, @PathParam(PATH_PARAM_DISK_NAME) String diskName) {
+
+ if (clusterName == null || clusterName.isEmpty()) {
+ return badRequestResponse("Cluster name must not be empty!");
+ }
+
+ if (serverName == null || serverName.isEmpty()) {
+ return badRequestResponse("Server name must not be empty!");
+ }
+
+ if (diskName == null || diskName.isEmpty()) {
+ return badRequestResponse("Disk name must not be empty!");
+ }
+
+ InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, diskName, serverName);
+ try {
+ initializeTask.start();
+ taskResource.addTask(initializeTask);
+ return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS
+ + "/" + initializeTask.getId());
+ } catch (ConnectionException e) {
+ return errorResponse(e.getMessage());
+ }
+ }
+
private void setGlusterUtil(GlusterUtil glusterUtil) {
this.glusterUtil = glusterUtil;
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java
index 4bf1c0cf..53122f11 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java
@@ -20,9 +20,9 @@
*/
package com.gluster.storage.management.server.resources;
+import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION;
import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_TASK_ID;
-import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS;
@@ -40,26 +40,25 @@ 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;
import com.gluster.storage.management.core.constants.RESTConstants;
import com.gluster.storage.management.core.exceptions.GlusterRuntimeException;
-import com.gluster.storage.management.core.model.Status;
-import com.gluster.storage.management.core.model.Task;
+import com.gluster.storage.management.core.exceptions.GlusterValidationException;
import com.gluster.storage.management.core.model.TaskInfo;
-import com.gluster.storage.management.core.response.TaskListResponse;
-import com.gluster.storage.management.core.response.TaskResponse;
+import com.gluster.storage.management.core.response.TaskInfoListResponse;
+import com.gluster.storage.management.server.tasks.Task;
import com.sun.jersey.spi.resource.Singleton;
@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_TASKS)
@Singleton
-public class TasksResource {
+public class TasksResource extends AbstractResource {
private Map<String, Task> tasksMap = new HashMap<String, Task>();
public TasksResource() {
}
-
- public void addTask(Task task) { // task should be one of MuigrateDiskTask, FormatDiskTask, etc
+ public void addTask(Task task) {
tasksMap.put(task.getId(), task);
}
@@ -70,18 +69,11 @@ public class TasksResource {
public List<TaskInfo> getAllTasksInfo() {
List<TaskInfo> allTasksInfo = new ArrayList<TaskInfo>();
for (Map.Entry<String, Task> entry : tasksMap.entrySet()) {
- allTasksInfo.add(entry.getValue().getTaskInfo());
+ checkTaskStatus(entry.getKey());
+ allTasksInfo.add(entry.getValue().getTaskInfo()); // TaskInfo with latest status
}
return allTasksInfo;
}
-
- public List<Task> getAllTasks() {
- List<Task> allTasks = new ArrayList<Task>();
- for (Map.Entry<String, Task> entry : tasksMap.entrySet()) {
- allTasks.add(entry.getValue());
- }
- return allTasks;
- }
public Task getTask(String taskId) {
for (Map.Entry<String, Task> entry : tasksMap.entrySet()) {
@@ -91,63 +83,93 @@ public class TasksResource {
}
return null;
}
-
+
@GET
@Produces(MediaType.APPLICATION_XML)
- public TaskListResponse getTasks() {
- TaskListResponse taskListResponse = new TaskListResponse();
+ public Response getTasks() {
+ try {
+ return okResponse(new TaskInfoListResponse(getAllTasksInfo()), MediaType.APPLICATION_XML);
+ } catch (GlusterRuntimeException e) {
+ return errorResponse(e.getMessage());
+ }
+ }
+
+ @GET
+ @Path("/{" + PATH_PARAM_TASK_ID + "}")
+ @Produces(MediaType.APPLICATION_XML)
+ public Response getTaskStatus( @PathParam(PATH_PARAM_TASK_ID) String taskId) {
try {
- taskListResponse.setData(getAllTasksInfo());
- taskListResponse.setStatus(new Status(Status.STATUS_CODE_SUCCESS, ""));
+ Task task = checkTaskStatus(taskId);
+ return okResponse(task.getTaskInfo(), MediaType.APPLICATION_XML);
} catch (GlusterRuntimeException e) {
- taskListResponse.setStatus(new Status(e));
+ return errorResponse(e.getMessage());
}
- return taskListResponse;
+ }
+
+ private Task checkTaskStatus(String taskId) {
+ Task task = getTask(taskId);
+ task.getTaskInfo().setStatus(task.checkStatus());
+ return task;
}
@PUT
@Path("/{" + PATH_PARAM_TASK_ID + "}")
@Produces(MediaType.APPLICATION_XML)
- public TaskResponse performTask(@PathParam(PATH_PARAM_TASK_ID) String taskId,
- @FormParam(FORM_PARAM_OPERATION) String taskOperation) {
+ public Response performTask(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
+ @PathParam(PATH_PARAM_TASK_ID) String taskId, @FormParam(FORM_PARAM_OPERATION) String taskOperation) {
Task task = getTask(taskId);
- TaskInfo taskInfo = null;
- TaskResponse taskResponse = new TaskResponse();
-
+
try {
if (taskOperation.equals(RESTConstants.TASK_RESUME)) {
- taskInfo = task.resume();
- }
- if (taskOperation.equals(RESTConstants.TASK_PAUSE)) {
- taskInfo = task.pause();
+ task.resume();
+ } else if (taskOperation.equals(RESTConstants.TASK_PAUSE)) {
+ task.pause();
+ } else if (taskOperation.equals(RESTConstants.TASK_STOP)) {
+ task.stop();
+ } else if (taskOperation.equals(RESTConstants.TASK_COMMIT)) {
+ task.commit();
}
- if (taskOperation.equals(RESTConstants.TASK_STOP)) {
- taskInfo = task.stop();
- }
- taskResponse.setData(taskInfo);
- taskResponse.setStatus(new Status(Status.STATUS_CODE_SUCCESS, ""));
+ return (Response) noContentResponse();
+ } catch(GlusterValidationException ve) {
+ return badRequestResponse(ve.getMessage());
} catch (GlusterRuntimeException e) {
- taskResponse.setStatus(new Status(e));
+ return errorResponse(e.getMessage());
}
- return taskResponse;
}
@DELETE
@Path("/{" + PATH_PARAM_TASK_ID + "}")
@Produces(MediaType.APPLICATION_XML)
- public TaskResponse deleteTask(@PathParam(PATH_PARAM_TASK_ID) String taskId,
+ public Response deleteTask(@PathParam(PATH_PARAM_TASK_ID) String taskId,
@QueryParam(FORM_PARAM_OPERATION) String taskOperation) {
- TaskResponse taskResponse = new TaskResponse();
Task task = getTask(taskId);
if (task == null) {
- taskResponse.setStatus( new Status(Status.STATUS_CODE_FAILURE, "No such task " + taskId + "is found "));
+ return notFoundResponse("Task [" + taskId + "] not found!");
}
- if (taskOperation.equals("delete")) {
- removeTask(task);
- taskResponse.setStatus(new Status(Status.STATUS_CODE_SUCCESS, "Task [" + taskId
- + "] removed successfully"));
- }
- return null;
- }
+
+ if(taskOperation == null || taskOperation.isEmpty()) {
+ return badRequestResponse("Parameter [" + FORM_PARAM_OPERATION + "] is missing in request!");
+ }
+
+ if(!taskOperation.equals(RESTConstants.TASK_STOP) && !taskOperation.equals(RESTConstants.TASK_DELETE)) {
+ return badRequestResponse("Invalid value [" + taskOperation + "] for parameter [" + FORM_PARAM_OPERATION
+ + "]");
+ }
+
+ try {
+ if (taskOperation.equals(RESTConstants.TASK_STOP)) {
+ task.stop();
+ // On successfully stopping the task, we can delete (forget) it as it is no more useful
+ taskOperation = RESTConstants.TASK_DELETE;
+ }
+ if (taskOperation.equals(RESTConstants.TASK_DELETE)) {
+ removeTask(task);
+ }
+
+ return noContentResponse();
+ } catch (Exception e) {
+ return errorResponse(e.getMessage());
+ }
+ }
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java
index 0326793b..0ccb4263 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java
@@ -18,6 +18,9 @@
*******************************************************************************/
package com.gluster.storage.management.server.resources;
+import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_USER;
+import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_USERS;
+
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
@@ -25,68 +28,60 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.PasswordEncoder;
-import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.stereotype.Component;
-import com.gluster.storage.management.core.model.Status;
import com.sun.jersey.spi.resource.Singleton;
@Singleton
@Component
-@Path("/users")
-public class UsersResource {
+@Path(RESOURCE_PATH_USERS)
+public class UsersResource extends AbstractResource {
@Autowired
private JdbcUserDetailsManager jdbcUserService;
@Autowired
private PasswordEncoder passwordEncoder;
- /**
- * Authenticates given user with given password for login on current system
- *
- * @param user
- * @param password
- * @return true is user can be successfully authenticated using given password, else false
- */
- /*
- * NOTE: This method is no more required as user authentication is performed on every request by the spring security
- * framework. Can be removed after testing.
- */
- /*
- * private boolean authenticate(String user, String password) { String tmpFileName = "tmp"; File saltFile = new
- * File(tmpFileName); ProcessResult result = new ProcessUtil().executeCommand("get-user-password.py", user,
- * tmpFileName); if (result.isSuccess()) { String salt = new FileUtil().readFileAsString(saltFile); String
- * encryptedPassword = MD5Crypt.crypt(password, salt); return encryptedPassword.equals(salt); }
- *
- * return false; }
- */
-
- @Path("{user}")
+ @Path("{" + PATH_PARAM_USER + "}")
@GET
@Produces(MediaType.APPLICATION_XML)
- public Status authenticate(@PathParam("user") String user) {
+ public Response authenticateXML(@PathParam("user") String user) {
+ // success only if the user passed in query is same as the one passed in security header
+ // spring security would have already authenticated the user credentials
+ return getAuthenticationResponse(user, MediaType.APPLICATION_XML);
+ }
+
+ @Path("{" + PATH_PARAM_USER + "}")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response authenticateJSON(@PathParam("user") String user) {
// success only if the user passed in query is same as the one passed in security header
// spring security would have already authenticated the user credentials
- return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? Status.STATUS_SUCCESS
- : Status.STATUS_FAILURE);
+ return getAuthenticationResponse(user, MediaType.APPLICATION_JSON);
}
- @Path("{user}")
+ public Response getAuthenticationResponse(String user, String mediaType) {
+ return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? okResponse(mediaType)
+ : unauthorizedResponse());
+ }
+
+ @Path("{" + PATH_PARAM_USER + "}")
@PUT
- @Produces(MediaType.APPLICATION_XML)
- public Status changePassword(@FormParam("oldpassword") String oldPassword,
+ public Response changePassword(@FormParam("oldpassword") String oldPassword,
@FormParam("newpassword") String newPassword) {
try {
jdbcUserService.changePassword(oldPassword, passwordEncoder.encodePassword(newPassword, null));
- } catch (AuthenticationException ex) {
+ } catch (Exception ex) {
+ // TODO: Log the exception
ex.printStackTrace();
- return new Status(Status.STATUS_CODE_FAILURE, "Could not change password: [" + ex.getMessage() + "]");
+ return errorResponse("Could not change password. Error: [" + ex.getMessage() + "]");
}
- return Status.STATUS_SUCCESS;
+ return noContentResponse();
}
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java
index 5d1f38e9..c9ae0fe5 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java
@@ -23,8 +23,12 @@ package com.gluster.storage.management.server.resources;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_ACCESS_PROTOCOLS;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_AUTO_COMMIT;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_BRICKS;
-import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_CLUSTER_NAME;
+import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FIX_LAYOUT;
+import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FORCED_DATA_MIGRATE;
+import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_MIGRATE_DATA;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPERATION;
+import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPTION_KEY;
+import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_OPTION_VALUE;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_REPLICA_COUNT;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SOURCE;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_STRIPE_COUNT;
@@ -33,7 +37,6 @@ import static com.gluster.storage.management.core.constants.RESTConstants.FORM_P
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_OPTIONS;
import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_VOLUME_TYPE;
-import static com.gluster.storage.management.core.constants.RESTConstants.*;
import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_VOLUME_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_BRICKS;
@@ -44,13 +47,13 @@ import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LINE_COUNT;
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LOG_SEVERITY;
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TO_TIMESTAMP;
-import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_VOLUME_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_BRICKS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DEFAULT_OPTIONS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_DOWNLOAD;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_LOGS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_OPTIONS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS;
+import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_VOLUMES;
import static com.gluster.storage.management.core.constants.RESTConstants.TASK_START;
import static com.gluster.storage.management.core.constants.RESTConstants.TASK_STOP;
@@ -91,16 +94,16 @@ import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE;
import com.gluster.storage.management.core.model.VolumeLogMessage;
import com.gluster.storage.management.core.response.GenericResponse;
import com.gluster.storage.management.core.response.LogMessageListResponse;
-import com.gluster.storage.management.core.response.TaskResponse;
import com.gluster.storage.management.core.response.VolumeListResponse;
import com.gluster.storage.management.core.response.VolumeOptionInfoListResponse;
import com.gluster.storage.management.core.utils.DateUtil;
import com.gluster.storage.management.core.utils.FileUtil;
-import com.gluster.storage.management.core.utils.GlusterCoreUtil;
import com.gluster.storage.management.core.utils.ProcessUtil;
import com.gluster.storage.management.server.constants.VolumeOptionsDefaults;
import com.gluster.storage.management.server.data.ClusterInfo;
import com.gluster.storage.management.server.services.ClusterService;
+import com.gluster.storage.management.server.tasks.MigrateDiskTask;
+import com.gluster.storage.management.server.tasks.RebalanceVolumeTask;
import com.gluster.storage.management.server.utils.GlusterUtil;
import com.gluster.storage.management.server.utils.ServerUtil;
import com.sun.jersey.api.core.InjectParam;
@@ -109,14 +112,10 @@ import com.sun.jersey.spi.resource.Singleton;
@Singleton
@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_VOLUMES)
public class VolumesResource extends AbstractResource {
- private static final String PREPARE_BRICK_SCRIPT = "create_volume_directory.py";
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";
@InjectParam
- private GlusterServersResource glusterServersResource;
-
- @InjectParam
private ServerUtil serverUtil;
@InjectParam
@@ -128,6 +127,9 @@ public class VolumesResource extends AbstractResource {
@InjectParam
private VolumeOptionsDefaults volumeOptionsDefaults;
+ @InjectParam
+ private TasksResource taskResource;
+
@GET
@Produces({MediaType.APPLICATION_XML})
public Response getVolumesXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) {
@@ -145,15 +147,21 @@ public class VolumesResource extends AbstractResource {
return badRequestResponse("Cluster name must not be empty!");
}
- if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ ClusterInfo cluster = clusterService.getCluster(clusterName);
+ if (cluster == null) {
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
+ }
+
+ if(cluster.getServers().size() == 0) {
+ // no server added yet. return an empty array.
+ return okResponse(new VolumeListResponse(), mediaType);
}
return okResponse(getVolumes(clusterName), mediaType);
}
public VolumeListResponse getVolumes(String clusterName) {
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
return new VolumeListResponse(new ArrayList<Volume>());
}
@@ -162,7 +170,7 @@ public class VolumesResource extends AbstractResource {
return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName()));
} catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
return new VolumeListResponse(new ArrayList<Volume>());
}
@@ -188,7 +196,7 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
if (volumeType.equals(VOLUME_TYPE.DISTRIBUTED_MIRROR) && replicaCount <= 0) {
@@ -199,7 +207,7 @@ public class VolumesResource extends AbstractResource {
return badRequestResponse("Stripe count must be a positive integer");
}
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -209,7 +217,7 @@ public class VolumesResource extends AbstractResource {
return createdResponse(volumeName);
} catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -274,7 +282,7 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
try {
@@ -287,7 +295,7 @@ public class VolumesResource extends AbstractResource {
private Volume getVolume(String clusterName, String volumeName) {
Volume volume;
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
}
@@ -296,7 +304,7 @@ public class VolumesResource extends AbstractResource {
volume = glusterUtil.getVolume(volumeName, onlineServer.getName());
} catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
}
@@ -309,7 +317,10 @@ public class VolumesResource extends AbstractResource {
@PUT
@Path("{" + PATH_PARAM_VOLUME_NAME + "}")
public Response performOperation(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName,
- @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_OPERATION) String operation) {
+ @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_OPERATION) String operation,
+ @FormParam(FORM_PARAM_FIX_LAYOUT) Boolean isFixLayout,
+ @FormParam(FORM_PARAM_MIGRATE_DATA) Boolean isMigrateData,
+ @FormParam(FORM_PARAM_FORCED_DATA_MIGRATE) Boolean isForcedDataMigrate) {
if (clusterName == null || clusterName.isEmpty()) {
return badRequestResponse("Cluster name must not be empty!");
}
@@ -319,31 +330,38 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
- if (onlineServer == null) {
- return errorResponse("No online servers found in cluster [" + clusterName + "]");
+ try {
+ if (operation.equals(RESTConstants.TASK_REBALANCE_START)) {
+ String taskId = rebalanceStart(clusterName, volumeName, isFixLayout, isMigrateData, isForcedDataMigrate);
+ return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS
+ + "/" + taskId);
+ } else if (operation.equals(RESTConstants.TASK_REBALANCE_STOP)) {
+ rebalanceStop(clusterName, volumeName);
+ } else {
+ performVolumeOperation(clusterName, volumeName, operation);
+ }
+ return noContentResponse();
+ } catch(Exception e) {
+ return errorResponse(e.getMessage());
}
-
+ }
+
+ private void performVolumeOperation(String clusterName, String volumeName, String operation) {
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
try {
- performOperation(volumeName, operation, onlineServer);
- } catch (ConnectionException e) {
- // online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
if (onlineServer == null) {
- return errorResponse("No online servers found in cluster [" + clusterName + "]");
- }
-
- try {
- performOperation(volumeName, operation, onlineServer);
- } catch(Exception e1) {
- // TODO: Log the exception
- return errorResponse(e1.getMessage());
+ throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
}
+
+ performOperation(volumeName, operation, onlineServer);
+ } catch (ConnectionException e) {
+ // online server has gone offline! try with a different one.
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
+ performOperation(volumeName, operation, onlineServer);
}
- return noContentResponse();
}
private Status performOperation(String volumeName, String operation, GlusterServer onlineServer) {
@@ -370,7 +388,7 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
if (deleteFlag == null) {
@@ -386,7 +404,7 @@ public class VolumesResource extends AbstractResource {
}
List<Brick> bricks = volume.getBricks();
- Status status = glusterUtil.deleteVolume(volumeName, glusterServersResource.getOnlineServer(clusterName)
+ Status status = glusterUtil.deleteVolume(volumeName, clusterService.getOnlineServer(clusterName)
.getName());
if(!status.isSuccess()) {
return errorResponse("Couldn't delete volume [" + volumeName + "]. Error: " + status);
@@ -423,14 +441,14 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
if(deleteFlag == null) {
deleteFlag = false;
}
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -456,7 +474,7 @@ public class VolumesResource extends AbstractResource {
glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName());
} catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]");
}
@@ -530,10 +548,10 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -542,7 +560,7 @@ public class VolumesResource extends AbstractResource {
glusterUtil.setOption(volumeName, key, value, onlineServer.getName());
} catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -572,10 +590,10 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -584,7 +602,7 @@ public class VolumesResource extends AbstractResource {
glusterUtil.resetOptions(volumeName, onlineServer.getName());
} catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -628,27 +646,20 @@ public class VolumesResource extends AbstractResource {
// Usage: get_volume_disk_log.py <volumeName> <diskName> <lineCount>
Object responseObj = serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_BRICK_LOG_SCRIPT + " "
+ logFilePath + " " + lineCount, LogMessageListResponse.class);
- Status status = null;
+
LogMessageListResponse response = null;
if (responseObj instanceof LogMessageListResponse) {
response = (LogMessageListResponse) responseObj;
- status = response.getStatus();
+ // populate disk and trim other fields
+ List<VolumeLogMessage> logMessages = response.getLogMessages();
+ for (VolumeLogMessage logMessage : logMessages) {
+ logMessage.setBrickDirectory(brick.getBrickDirectory());
+ }
+ return logMessages;
} else {
- status = (Status) responseObj;
- }
-
- if (!status.isSuccess()) {
+ Status status = (Status) responseObj;
throw new GlusterRuntimeException(status.toString());
}
-
- // populate disk and trim other fields
- List<VolumeLogMessage> logMessages = response.getLogMessages();
- for (VolumeLogMessage logMessage : logMessages) {
- logMessage.setBrickDirectory(brick.getBrickDirectory());
- logMessage.setMessage(logMessage.getMessage().trim());
- logMessage.setSeverity(logMessage.getSeverity().trim());
- }
- return logMessages;
}
@GET
@@ -665,7 +676,7 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
try {
@@ -757,7 +768,7 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
List<VolumeLogMessage> logMessages = null;
@@ -862,10 +873,10 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -875,7 +886,7 @@ public class VolumesResource extends AbstractResource {
glusterUtil.addBricks(volumeName, brickList, onlineServer.getName());
} catch (ConnectionException e) {
// online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
+ onlineServer = clusterService.getNewOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -915,10 +926,10 @@ public class VolumesResource extends AbstractResource {
}
if (clusterService.getCluster(clusterName) == null) {
- return badRequestResponse("Cluster [" + clusterName + "] not found!");
+ return notFoundResponse("Cluster [" + clusterName + "] not found!");
}
- GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName);
+ GlusterServer onlineServer = clusterService.getOnlineServer(clusterName);
if (onlineServer == null) {
return errorResponse("No online servers found in cluster [" + clusterName + "]");
}
@@ -929,23 +940,54 @@ public class VolumesResource extends AbstractResource {
String taskId = null;
try {
- taskId = glusterUtil.migrateBrickStart(volumeName, fromBrick, toBrick, autoCommit, onlineServer.getName());
- } catch (ConnectionException e) {
- // online server has gone offline! try with a different one.
- onlineServer = glusterServersResource.getNewOnlineServer(clusterName);
-
- try {
- taskId = glusterUtil.migrateBrickStart(volumeName, fromBrick, toBrick, autoCommit, onlineServer.getName());
- } catch(Exception e1) {
- return errorResponse(e1.getMessage());
- }
- } catch(Exception e1) {
- return errorResponse(e1.getMessage());
+ taskId = migrateBrickStart(clusterName, volumeName, fromBrick, toBrick, autoCommit);
+ }catch(Exception e) {
+ return errorResponse(e.getMessage());
}
- return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS, clusterName, RESOURCE_TASKS, taskId);
+ return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/"
+ + taskId);
}
-
+
+ private String migrateBrickStart(String clusterName, String volumeName, String fromBrick, String toBrick,
+ Boolean autoCommit) {
+ MigrateDiskTask migrateDiskTask = new MigrateDiskTask(clusterService, clusterName, volumeName, fromBrick,
+ toBrick);
+ migrateDiskTask.setAutoCommit(autoCommit);
+ migrateDiskTask.start();
+ taskResource.addTask(migrateDiskTask);
+ return migrateDiskTask.getTaskInfo().getName(); // Return Task ID
+ }
+
+ private String rebalanceStart(String clusterName, String volumeName, Boolean isFixLayout, Boolean isMigrateData,
+ Boolean isForcedDataMigrate) {
+ String layout = "";
+ if (isForcedDataMigrate) {
+ layout = "forced-data-migrate";
+ } else if (isMigrateData) {
+ layout = "migrate-data";
+ } else if (isFixLayout) {
+ layout = "fix-layout";
+ }
+
+ return rebalanceStart(clusterName, volumeName, layout);
+ }
+
+ public String rebalanceStart(String clusterName, String volumeName, String layout) {
+ RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName);
+ rebalanceTask.setLayout(layout);
+ rebalanceTask.start();
+ taskResource.addTask(rebalanceTask);
+ return rebalanceTask.getId();
+ }
+
+ public void rebalanceStop(String clusterName, String volumeName) {
+ // TODO: arrive at the task id and fetch it
+ String taskId = "";
+
+ taskResource.getTask(taskId).stop();
+ }
+
public static void main(String[] args) throws ClassNotFoundException {
VolumesResource vr = new VolumesResource();
// VolumeListResponse response = vr.getAllVolumes();
@@ -969,6 +1011,10 @@ public class VolumesResource extends AbstractResource {
// System.out.println("Code : " + status.getCode());
// System.out.println("Message " + status.getMessage());
- vr.removeBricks("testCluster", "test", "192.168.1.210:sdb", true);
+ // 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);
+
}
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java
index 0aabb714..b622c3a1 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java
@@ -33,15 +33,17 @@ 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.GlusterServer;
-import com.gluster.storage.management.core.model.Status;
+import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS;
+import com.gluster.storage.management.core.utils.LRUCache;
import com.gluster.storage.management.server.data.ClusterInfo;
import com.gluster.storage.management.server.data.PersistenceDao;
import com.gluster.storage.management.server.data.ServerInfo;
import com.gluster.storage.management.server.utils.GlusterUtil;
+import com.gluster.storage.management.server.utils.ServerUtil;
import com.gluster.storage.management.server.utils.SshUtil;
-import com.sun.jersey.api.core.InjectParam;
/**
* Service class for functionality related to clusters
@@ -60,12 +62,70 @@ public class ClusterService {
@Autowired
private SshUtil sshUtil;
+ @Autowired
+ private ServerUtil serverUtil;
+
+ private LRUCache<String, GlusterServer> onlineServerCache = new LRUCache<String, GlusterServer>(3);
+
+ public void addOnlineServer(String clusterName, GlusterServer server) {
+ onlineServerCache.put(clusterName, server);
+ }
+
+ public void removeOnlineServer(String clusterName) {
+ onlineServerCache.remove(clusterName);
+ }
+
+ // uses cache
+ public GlusterServer getOnlineServer(String clusterName, String exceptServerName) {
+ GlusterServer server = onlineServerCache.get(clusterName);
+ if (server != null && !server.getName().equals(exceptServerName)) {
+ return server;
+ }
+
+ return getNewOnlineServer(clusterName, exceptServerName);
+ }
+
+ public GlusterServer getNewOnlineServer(String clusterName) {
+ return getNewOnlineServer(clusterName, "");
+ }
+
+ public GlusterServer getOnlineServer(String clusterName) {
+ return getOnlineServer(clusterName, "");
+ }
+
+ // Doesn't use cache
+ public GlusterServer getNewOnlineServer(String clusterName, String exceptServerName) {
+ ClusterInfo cluster = getCluster(clusterName);
+ if (cluster == null) {
+ throw new GlusterRuntimeException("Cluster [" + clusterName + "] is not found!");
+ }
+
+ for (ServerInfo serverInfo : cluster.getServers()) {
+ GlusterServer server = new GlusterServer(serverInfo.getName());
+ server.setStatus(SERVER_STATUS.ONLINE);
+ try {
+ serverUtil.fetchServerDetails(server);
+ if (server.isOnline() && !server.getName().equals(exceptServerName)) {
+ // server is online. add it to cache and return
+ addOnlineServer(clusterName, server);
+ return server;
+ }
+ } catch(ConnectionException e) {
+ // server is offline. continue checking next one.
+ continue;
+ }
+ }
+
+ // no online server found.
+ throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]");
+ }
+
public List<ClusterInfo> getAllClusters() {
return clusterDao.findAll();
}
public ClusterInfo getCluster(String clusterName) {
- List<ClusterInfo> clusters = clusterDao.findBy("name = ?1", clusterName);
+ List<ClusterInfo> clusters = clusterDao.findBy("UPPER(name) = ?1", clusterName.toUpperCase());
if(clusters.size() == 0) {
return null;
}
@@ -74,7 +134,7 @@ public class ClusterService {
}
public ClusterInfo getClusterForServer(String serverName) {
- List<ServerInfo> servers = serverDao.findBy("name = ?1", serverName);
+ List<ServerInfo> servers = serverDao.findBy("UPPER(name) = ?1", serverName.toUpperCase());
if(servers.size() == 0) {
return null;
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java
new file mode 100644
index 00000000..5f3f8e30
--- /dev/null
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java
@@ -0,0 +1,114 @@
+/**
+ * InitializeDiskTask.java
+ *
+ * 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.tasks;
+
+import com.gluster.storage.management.core.model.Status;
+import com.gluster.storage.management.core.model.TaskInfo;
+import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE;
+import com.gluster.storage.management.core.model.TaskStatus;
+import com.gluster.storage.management.server.services.ClusterService;
+import com.gluster.storage.management.server.utils.SshUtil;
+
+public class InitializeDiskTask extends Task {
+
+ private static final String INITIALIZE_DISK_SCRIPT = "initialize_disk.py";
+ private static final String INITIALIZE_DISK_STATUS_SCRIPT = "initialize_disk_status.py";
+
+ private String serverName;
+ private String diskName;
+ private SshUtil sshUtil = new SshUtil();
+
+ public InitializeDiskTask(ClusterService clusterService, String clusterName, String serverName, String diskName) {
+ super(clusterService, clusterName, TASK_TYPE.DISK_FORMAT, diskName, "Initialize disk " + serverName + ":"
+ + diskName, false, false, false);
+
+ setServerName(serverName);
+ setDiskName(diskName);
+ }
+
+ public InitializeDiskTask(ClusterService clusterService, String clusterName, TaskInfo info) {
+ super(clusterService, clusterName, info);
+ }
+
+ @Override
+ public String getId() {
+ return taskInfo.getType() + "-" + serverName + ":" + diskName;
+ }
+
+ @Override
+ public void resume() {
+ getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not resume disk initialization")));
+ }
+
+ @Override
+ public void stop() {
+ getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not stop disk initialization")));
+ }
+
+ @Override
+ public void pause() {
+ getTaskInfo().setStatus( new TaskStatus( new Status(Status.STATUS_CODE_FAILURE, "Can not suspend disk initialization")));
+ }
+
+ @Override
+ public void commit() {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ public TASK_TYPE getType() {
+ return TASK_TYPE.DISK_FORMAT;
+ }
+
+ @Override
+ public TaskInfo getTaskInfo() {
+ return getTaskInfo();
+ }
+
+ @Override
+ public void start() {
+ getTaskInfo().setStatus(
+ new TaskStatus(new Status(sshUtil.executeRemote(getServerName(), INITIALIZE_DISK_SCRIPT + " "
+ + getDiskName()))));
+ }
+
+ @Override
+ public TaskStatus checkStatus() {
+ return new TaskStatus(new Status(sshUtil.executeRemote(getServerName(), INITIALIZE_DISK_STATUS_SCRIPT + " "
+ + getDiskName())));
+ }
+
+ public void setDiskName(String diskName) {
+ this.diskName = diskName;
+ }
+
+ public String getDiskName() {
+ return diskName;
+ }
+
+ public void setServerName(String serverName) {
+ this.serverName = serverName;
+ }
+
+ public String getServerName() {
+ return serverName;
+ }
+}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java
index df637ab1..9bdc9c94 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateDiskTask.java
@@ -20,13 +20,16 @@
*/
package com.gluster.storage.management.server.tasks;
-import org.springframework.beans.factory.annotation.Autowired;
-
+import com.gluster.storage.management.core.exceptions.ConnectionException;
+import com.gluster.storage.management.core.exceptions.GlusterRuntimeException;
import com.gluster.storage.management.core.model.Status;
-import com.gluster.storage.management.core.model.Task;
import com.gluster.storage.management.core.model.TaskInfo;
+import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE;
import com.gluster.storage.management.core.model.TaskStatus;
+import com.gluster.storage.management.core.utils.ProcessResult;
+import com.gluster.storage.management.server.services.ClusterService;
import com.gluster.storage.management.server.utils.SshUtil;
+import com.sun.jersey.core.util.Base64;
public class MigrateDiskTask extends Task {
@@ -60,67 +63,176 @@ public class MigrateDiskTask extends Task {
this.autoCommit = autoCommit;
}
- public MigrateDiskTask(TASK_TYPE type, String volumeName, String fromBrick, String toBrick) {
- super(type, volumeName);
+ public MigrateDiskTask(ClusterService clusterService, String clusterName, String volumeName, String fromBrick, String toBrick) {
+ super(clusterService, clusterName, TASK_TYPE.BRICK_MIGRATE, volumeName, "Brick Migration on volume ["
+ + volumeName + "] from [" + fromBrick + "] to [" + toBrick + "]", true, true, true);
setFromBrick(fromBrick);
setToBrick(toBrick);
- setTaskDescription();
- getTaskInfo().setCanPause(true);
- getTaskInfo().setCanStop(true);
+ taskInfo.setName(getId());
}
- public MigrateDiskTask(TaskInfo info) {
- super(info);
- setTaskDescription();
+ public MigrateDiskTask(ClusterService clusterService, String clusterName, TaskInfo info) {
+ super(clusterService, clusterName, info);
}
@Override
public String getId() {
- return getTaskInfo().getId();
+ return new String( Base64.encode( taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" + toBrick ));
}
@Override
- public TaskInfo start() {
- getTaskInfo().setStatus(
- new TaskStatus(new Status(sshUtil.executeRemote(getOnlineServer(), "gluster volume replace-brick "
- + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() + " start" ) )));
- return getTaskInfo();
+ public void start() {
+ try {
+ startMigration(getOnlineServer().getName());
+ } catch(ConnectionException e) {
+ // online server might have gone offline. try with a new one.
+ startMigration(getNewOnlineServer().getName());
+ }
+ }
+
+ private void startMigration(String onlineServerName) {
+ String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " "
+ + getToBrick() + " start";
+ ProcessResult processResult = sshUtil.executeRemote(onlineServerName, command);
+ if (processResult.isSuccess()) {
+ if (processResult.getOutput().trim().matches(".*started successfully$")) {
+ getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput().trim())));
+ return;
+ }
+ }
+
+ // if we come here, it means task couldn't be started successfully.
+ throw new GlusterRuntimeException(processResult.toString());
}
@Override
- public TaskInfo resume() {
- return start();
+ public void pause() {
+ try {
+ pauseMigration(getOnlineServer().getName());
+ } catch(ConnectionException e) {
+ // online server might have gone offline. try with a new one.
+ pauseMigration(getNewOnlineServer().getName());
+ }
}
+ private void pauseMigration(String onlineServer) {
+ String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick()
+ + " pause";
+
+ ProcessResult processResult = sshUtil.executeRemote(onlineServer, command);
+ TaskStatus taskStatus = new TaskStatus();
+ if (processResult.isSuccess()) {
+ if (processResult.getOutput().matches("*pause")) { //TODO replace correct pattern to identify the pause status
+ taskStatus.setCode(Status.STATUS_CODE_PAUSE);
+ taskStatus.setMessage(processResult.getOutput());
+ getTaskInfo().setStatus(taskStatus);
+ return;
+ }
+ }
+
+ // if we reach here, it means rebalance start failed.
+ throw new GlusterRuntimeException(processResult.toString());
+ }
+
+
+ @Override
+ public void resume() {
+ start();
+ }
+
@Override
- public TaskInfo stop() {
- getTaskInfo().setStatus(
- new TaskStatus(new Status(sshUtil.executeRemote(getOnlineServer(), "gluster volume replace-brick "
- + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() + " abort" ) )));
- return getTaskInfo();
+ public void commit() {
+ try {
+ commitMigration(getOnlineServer().getName());
+ } catch(ConnectionException e) {
+ // online server might have gone offline. try with a new one.
+ commitMigration(getNewOnlineServer().getName());
+ }
}
@Override
- public TaskInfo pause() {
- getTaskInfo().setStatus(
- new TaskStatus(new Status(sshUtil.executeRemote(getOnlineServer(), "gluster volume replace-brick "
- + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick() + " pause" ) )));
- return getTaskInfo();
+ public void stop() {
+ try {
+ stopMigration(getOnlineServer().getName());
+ } catch(ConnectionException e) {
+ // online server might have gone offline. try with a new one.
+ stopMigration(getNewOnlineServer().getName());
+ }
+ }
+
+ private void stopMigration(String serverName) {
+ String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " " + getToBrick()
+ + " abort";
+
+ ProcessResult processResult = sshUtil.executeRemote(serverName, command);
+ TaskStatus taskStatus = new TaskStatus();
+ if (processResult.isSuccess()) {
+ if (processResult.getOutput().trim().matches(".*aborted successfully$")) {
+ taskStatus.setCode(Status.STATUS_CODE_SUCCESS);
+ taskStatus.setMessage(processResult.getOutput());
+ getTaskInfo().setStatus(taskStatus);
+ return;
+ }
+ }
+ // if we reach here, it means rebalance start failed.
+ throw new GlusterRuntimeException(processResult.toString());
}
@Override
- public void setTaskDescription() {
- TaskInfo taskInfo = getTaskInfo();
- getTaskInfo().setDescription(
- getTypeStr() + " on volume [" + taskInfo.getReference() + "] from [" + getFromBrick()
- + "] to [" + getToBrick() + "]");
+ public TaskStatus checkStatus() {
+ try {
+ return checkMigrationStatus(getOnlineServer().getName());
+ } catch(ConnectionException e) {
+ // online server might have gone offline. try with a new one.
+ return checkMigrationStatus(getNewOnlineServer().getName());
+ }
}
-
- @Override
- public TaskInfo status() {
- return getTaskInfo();
+
+ public void commitMigration(String serverName) {
+ String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " "
+ + getToBrick() + " commit";
+
+ ProcessResult processResult = sshUtil.executeRemote(serverName, command);
+ TaskStatus taskStatus = new TaskStatus();
+ if (processResult.isSuccess()) {
+ if (processResult.getOutput().trim().matches(".*commit successful$")) {
+ taskStatus.setCode(Status.STATUS_CODE_SUCCESS);
+ taskStatus.setMessage(processResult.getOutput()); // Common
+ getTaskInfo().setStatus(taskStatus);
+ return;
+ }
+ }
+
+ // if we reach here, it means rebalance start failed.
+ throw new GlusterRuntimeException(processResult.toString());
+ }
+
+
+ private TaskStatus checkMigrationStatus(String serverName) {
+ String command = "gluster volume replace-brick " + getTaskInfo().getReference() + " " + getFromBrick() + " "
+ + getToBrick() + " status";
+ ProcessResult processResult = sshUtil.executeRemote(serverName, command);
+ TaskStatus taskStatus = new TaskStatus();
+ if (processResult.isSuccess()) {
+ if (processResult.getOutput().trim().matches("^Number of files migrated.*Migration complete$")) {
+ taskStatus.setCode(Status.STATUS_CODE_COMMIT_PENDING);
+ if (autoCommit) {
+ commitMigration(serverName);
+ }
+ } else if ( processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) {
+ taskStatus.setCode(Status.STATUS_CODE_RUNNING);
+ } else {
+ taskStatus.setCode(Status.STATUS_CODE_FAILURE);
+ }
+ } else {
+ taskStatus.setCode(Status.STATUS_CODE_FAILURE);
+ }
+
+ taskStatus.setMessage(processResult.getOutput()); // common
+ taskInfo.setStatus(taskStatus); // Update the task status
+ return taskStatus;
}
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java
new file mode 100644
index 00000000..7f9fb6bf
--- /dev/null
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java
@@ -0,0 +1,153 @@
+/**
+ * RebalanceVolumeTask.java
+ *
+ * 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.tasks;
+
+import com.gluster.storage.management.core.exceptions.ConnectionException;
+import com.gluster.storage.management.core.exceptions.GlusterRuntimeException;
+import com.gluster.storage.management.core.model.Status;
+import com.gluster.storage.management.core.model.TaskInfo;
+import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE;
+import com.gluster.storage.management.core.model.TaskStatus;
+import com.gluster.storage.management.core.utils.ProcessResult;
+import com.gluster.storage.management.server.services.ClusterService;
+import com.gluster.storage.management.server.utils.SshUtil;
+
+public class RebalanceVolumeTask extends Task {
+
+ private String layout;
+ private SshUtil sshUtil = new SshUtil();
+
+ public RebalanceVolumeTask(ClusterService clusterService, String clusterName, TaskInfo taskInfo) {
+ super(clusterService, clusterName, taskInfo);
+ }
+
+ public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName) {
+ super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume rebalance running on " + volumeName, false, true, false);
+ }
+
+ @Override
+ public String getId() {
+ return taskInfo.getType() + "-" + taskInfo.getReference();
+ }
+
+ @Override
+ public void start() {
+ try {
+ startRebalance(getOnlineServer().getName());
+ } catch(ConnectionException e) {
+ // online server might have gone offline. try with a new one
+ startRebalance(getNewOnlineServer().getName());
+ }
+ }
+
+ private void startRebalance(String serverName) {
+ String command = "gluster volume rebalance " + getTaskInfo().getReference() + " " + getLayout() + " start";
+ ProcessResult processResult = sshUtil.executeRemote(serverName, command);
+ if (processResult.isSuccess()) {
+ if (processResult.getOutput().trim().matches(".*has been successful$")) {
+ getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput())));
+ }
+ }
+
+ // if we reach here, it means rebalance start failed.
+ throw new GlusterRuntimeException(processResult.toString());
+ }
+
+ @Override
+ public void resume() {
+ getTaskInfo().setStatus(
+ new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, "Pause/Resume is not supported in Volume Rebalance")));
+ }
+
+ @Override
+ public void stop() {
+ try {
+ stopRebalance(getOnlineServer().getName());
+ } catch(ConnectionException e) {
+ // online server might have gone offline. try with a new one
+ stopRebalance(getNewOnlineServer().getName());
+ }
+ }
+
+ private void stopRebalance(String serverName) {
+ String command = "gluster volume rebalance " + getTaskInfo().getReference() + " stop";
+ ProcessResult processResult = sshUtil.executeRemote(serverName, command);
+ TaskStatus taskStatus = new TaskStatus();
+ if (processResult.isSuccess()) {
+ if (processResult.getOutput().trim().matches(".*has been successful$")) {
+ taskStatus.setCode(Status.STATUS_CODE_SUCCESS);
+ } else {
+ taskStatus.setCode(Status.STATUS_CODE_FAILURE);
+ }
+ } else {
+ taskStatus.setCode(Status.STATUS_CODE_FAILURE);
+ }
+ taskStatus.setMessage(processResult.getOutput()); // Common
+ getTaskInfo().setStatus(taskStatus);
+ }
+
+ @Override
+ public void pause() {
+ getTaskInfo().setStatus(
+ new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, "Pause/Resume is not supported in Volume Rebalance")));
+ }
+
+ @Override
+ public TaskStatus checkStatus() {
+ try {
+ return checkRebalanceStatus(getOnlineServer().getName());
+ } catch(ConnectionException e) {
+ // online server might have gone offline. try with a new one.
+ return checkRebalanceStatus(getNewOnlineServer().getName());
+ }
+ }
+
+ // TODO: This method should move to glusterUtil
+ private TaskStatus checkRebalanceStatus(String serverName) {
+ String command = "gluster volume rebalance " + getTaskInfo().getReference() + " status";
+ ProcessResult processResult = sshUtil.executeRemote(serverName, command);
+ TaskStatus taskStatus = new TaskStatus();
+ if (processResult.isSuccess()) {
+ if (processResult.getOutput().trim().matches(".*rebalance completed$")) {
+ taskStatus.setCode(Status.STATUS_CODE_SUCCESS);
+ } else {
+ taskStatus.setCode(Status.STATUS_CODE_RUNNING);
+ }
+ } else {
+ taskStatus.setCode(Status.STATUS_CODE_FAILURE);
+ }
+ taskStatus.setMessage(processResult.getOutput()); // Common
+ return taskStatus;
+ }
+
+ public void setLayout(String layout) {
+ this.layout = layout;
+ }
+
+ public String getLayout() {
+ return layout;
+ }
+
+ @Override
+ public void commit() {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java
new file mode 100644
index 00000000..49cd0b8b
--- /dev/null
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java
@@ -0,0 +1,111 @@
+/**
+ * Task.java
+ *
+ * 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.tasks;
+
+import com.gluster.storage.management.core.model.GlusterServer;
+import com.gluster.storage.management.core.model.TaskInfo;
+import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE;
+import com.gluster.storage.management.core.model.TaskStatus;
+import com.gluster.storage.management.server.services.ClusterService;
+
+public abstract class Task {
+ public String[] TASK_TYPE_STR = { "Format Disk", "Migrate Brick", "Volume Rebalance" };
+
+ protected TaskInfo taskInfo;
+ protected String clusterName;
+ private ClusterService clusterService;
+
+ public Task(ClusterService clusterService, String clusterName, TASK_TYPE type, String reference, String desc, boolean canPause, boolean canStop, boolean canCommit) {
+ TaskInfo taskInfo = new TaskInfo();
+ taskInfo.setType(type);
+ taskInfo.setReference(reference);
+ taskInfo.setDescription(desc);
+ taskInfo.setCanPause(canPause);
+ taskInfo.setCanStop(canStop);
+ taskInfo.setCanCommit(canCommit);
+
+ init(clusterService, clusterName, taskInfo);
+
+ }
+
+ public Task(ClusterService clusterService, String clusterName, TaskInfo taskInfo) {
+ init(clusterService, clusterName, taskInfo);
+ }
+
+ private void init(ClusterService clusterService, String clusterName, TaskInfo taskInfo) {
+ this.clusterService = clusterService;
+ setClusterName(clusterName);
+ setTaskInfo(taskInfo);
+ }
+
+ protected GlusterServer getOnlineServer() {
+ return clusterService.getOnlineServer(clusterName);
+ }
+
+ protected GlusterServer getNewOnlineServer() {
+ return clusterService.getNewOnlineServer(clusterName);
+ }
+
+ protected GlusterServer getNewOnlineServer(String exceptServerName) {
+ return clusterService.getNewOnlineServer(clusterName, exceptServerName);
+ }
+
+ public String getTypeStr() {
+ return TASK_TYPE_STR[taskInfo.getType().ordinal()];
+ }
+
+ public TASK_TYPE getType() {
+ return getTaskInfo().getType();
+ }
+
+ public String getClusterName() {
+ return clusterName;
+ }
+
+ public void setClusterName(String clusterName) {
+ this.clusterName = clusterName;
+ }
+
+ public TaskInfo getTaskInfo() {
+ return taskInfo;
+ }
+
+ public void setTaskInfo(TaskInfo info) {
+ this.taskInfo = info;
+ }
+
+ public abstract String getId();
+
+ public abstract void start();
+
+ public abstract void resume();
+
+ public abstract void stop();
+
+ public abstract void pause();
+
+ public abstract void commit();
+
+ /**
+ * This method should check current status of the task and update it's taskInfo accordingly
+ */
+ public abstract TaskStatus checkStatus();
+}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java
index 670ffb5c..788e3eab 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java
@@ -36,7 +36,6 @@ import com.gluster.storage.management.core.model.Brick.BRICK_STATUS;
import com.gluster.storage.management.core.model.GlusterServer;
import com.gluster.storage.management.core.model.GlusterServer.SERVER_STATUS;
import com.gluster.storage.management.core.model.Status;
-import com.gluster.storage.management.core.model.Task.TASK_TYPE;
import com.gluster.storage.management.core.model.TaskInfo;
import com.gluster.storage.management.core.model.Volume;
import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE;
@@ -47,6 +46,7 @@ import com.gluster.storage.management.core.utils.ProcessResult;
import com.gluster.storage.management.core.utils.StringUtil;
import com.gluster.storage.management.server.resources.TasksResource;
import com.gluster.storage.management.server.tasks.MigrateDiskTask;
+import com.gluster.storage.management.server.tasks.RebalanceVolumeTask;
import com.sun.jersey.api.core.InjectParam;
@Component
@@ -536,21 +536,6 @@ public class GlusterUtil {
return logFileName;
}
-
- public String migrateBrickStart(String volumeName, String fromBrick, String toBrick, Boolean autoCommit,
- String knownServer) {
- MigrateDiskTask migrateDiskTask = new MigrateDiskTask(TASK_TYPE.BRICK_MIGRATE, volumeName, fromBrick, toBrick);
- migrateDiskTask.setOnlineServer(knownServer);
- migrateDiskTask.setAutoCommit(autoCommit);
-
- TaskInfo taskInfo = migrateDiskTask.start();
- if (taskInfo.isSuccess()) {
- taskResource.addTask(migrateDiskTask);
- }
-
- return taskInfo.getId();
- }
-
public Status removeBricks(String volumeName, List<String> bricks, String knownServer) {
StringBuilder command = new StringBuilder("gluster --mode=script volume remove-brick " + volumeName);
for (String brickDir : bricks) {
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 ed1aea75..ed77def3 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
@@ -42,6 +42,7 @@ 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.Server;
import com.gluster.storage.management.core.model.Status;
import com.gluster.storage.management.core.response.GenericResponse;
import com.gluster.storage.management.core.utils.ProcessResult;
@@ -76,6 +77,21 @@ public class ServerUtil {
String scriptPath = servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName;
return scriptPath;
}
+
+ /**
+ * Fetch details of the given server. The server name must be populated in the object before calling this method.
+ *
+ * @param server
+ * Server whose details are to be fetched
+ */
+ public void fetchServerDetails(Server server) {
+ // fetch standard server details like cpu, disk, memory details
+ Object response = executeOnServer(true, server.getName(), "get_server_details.py --only-data-disks", Server.class);
+ if (response instanceof Status) {
+ throw new GlusterRuntimeException(((Status)response).getMessage());
+ }
+ server.copyFrom((Server) response); // Update the details in <Server> object
+ }
/**
* Executes given command on given server
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java
index 5f8b88f6..d56cd47c 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java
@@ -20,14 +20,14 @@ package com.gluster.storage.management.server.utils;
import java.io.BufferedReader;
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
-import java.util.Date;
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import ch.ethz.ssh2.ChannelCondition;
@@ -61,6 +61,15 @@ public class SshUtil {
private static final String USER_NAME = "root";
// TODO: Make default password configurable
private static final String DEFAULT_PASSWORD = "syst3m";
+
+ private static final Logger logger = Logger.getLogger(SshUtil.class);
+
+ @Autowired
+ private Integer sshConnectTimeout;
+ @Autowired
+ private Integer sshKexTimeout;
+ @Autowired
+ private Integer sshExecTimeout;
public boolean hasDefaultPassword(String serverName) {
try {
@@ -209,29 +218,28 @@ public class SshUtil {
Connection conn;
conn = new Connection(serverName);
try {
- // tcp connection timeout = 3 sec, ssh connection timeout = 10 sec
- conn.connect(null, 3000, 10000);
+ conn.connect(null, sshConnectTimeout, sshKexTimeout);
} catch (IOException e) {
- e.printStackTrace();
+ logger.error("Couldn't establish SSH connection with server [" + serverName + "]", e);
throw new ConnectionException("Exception while creating SSH connection with server [" + serverName + "]", e);
}
return conn;
}
- private boolean wasTerminated(int condition) {
- return ((condition | ChannelCondition.EXIT_SIGNAL) == condition);
- }
-
private boolean hasErrors(int condition, Session session) {
return (hasErrorStream(condition) || (exitedGracefully(condition) && exitedWithError(session)));
}
+
+ private boolean timedOut(int condition) {
+ return (condition == ChannelCondition.TIMEOUT);
+ }
private boolean exitedWithError(Session session) {
return session.getExitStatus() != ProcessResult.SUCCESS;
}
private boolean exitedGracefully(int condition) {
- return (condition | ChannelCondition.EXIT_STATUS) == condition;
+ return (condition == ChannelCondition.EXIT_STATUS);
}
private boolean hasErrorStream(int condition) {
@@ -250,8 +258,10 @@ public class SshUtil {
session.close();
return result;
} catch (IOException e) {
- throw new GlusterRuntimeException("Exception while executing command [" + command + "] on ["
- + sshConnection.getHostname() + "]", e);
+ String errMsg = "Exception while executing command [" + command + "] on [" + sshConnection.getHostname()
+ + "]";
+ logger.error(errMsg, e);
+ throw new GlusterRuntimeException(errMsg, e);
}
}
@@ -259,41 +269,51 @@ public class SshUtil {
// Wait for program to come out either
// a) gracefully with an exit status, OR
// b) because of a termination signal
- int condition = session.waitForCondition(ChannelCondition.EXIT_SIGNAL | ChannelCondition.EXIT_STATUS, 5000);
+ // c) command takes to long to exit (timeout)
+ int condition = session.waitForCondition(ChannelCondition.EXIT_SIGNAL | ChannelCondition.EXIT_STATUS,
+ sshExecTimeout);
StringBuilder output = new StringBuilder();
try {
- readFromStream(stdoutReader, output);
- if (hasErrors(condition, session)) {
- readFromStream(stderrReader, output);
+ if(!timedOut(condition)) {
+ readFromStream(stdoutReader, output);
+ if (hasErrors(condition, session)) {
+ readFromStream(stderrReader, output);
+ }
}
- return prepareProcessResult(session, condition, output);
+ return prepareProcessResult(session, condition, output.toString().trim());
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return null;
+ String errMsg = "Error while reading output stream from SSH connection!";
+ logger.error(errMsg, e);
+ return new ProcessResult(ProcessResult.FAILURE, errMsg);
}
}
- private ProcessResult prepareProcessResult(Session session, int condition, StringBuilder output) {
+ private ProcessResult prepareProcessResult(Session session, int condition, String output) {
ProcessResult result = null;
- if (wasTerminated(condition)) {
- result = new ProcessResult(ProcessResult.FAILURE, output.toString());
- } else {
+ switch(condition) {
+ case ChannelCondition.TIMEOUT:
+ result = new ProcessResult(ProcessResult.FAILURE, "Command timed out!");
+ break;
+ case ChannelCondition.EXIT_SIGNAL:
+ // terminated
+ result = new ProcessResult(ProcessResult.FAILURE, output);
+ break;
+ default:
if (hasErrors(condition, session)) {
Integer exitStatus = session.getExitStatus();
int statusCode = (exitStatus == null ? ProcessResult.FAILURE : exitStatus);
- result = new ProcessResult(statusCode, output.toString());
+ result = new ProcessResult(statusCode, output);
} else {
- result = new ProcessResult(ProcessResult.SUCCESS, output.toString());
+ result = new ProcessResult(ProcessResult.SUCCESS, output);
}
+ break;
}
return result;
}
- private void readFromStream(BufferedReader streamReader, StringBuilder output) throws IOException,
- UnsupportedEncodingException {
+ private void readFromStream(BufferedReader streamReader, StringBuilder output) throws IOException {
while (true) {
String line = streamReader.readLine();
if (line == null) {
diff --git a/src/com.gluster.storage.management.server/src/log4j.properties b/src/com.gluster.storage.management.server/src/log4j.properties
index d7712c96..f84009d3 100644
--- a/src/com.gluster.storage.management.server/src/log4j.properties
+++ b/src/com.gluster.storage.management.server/src/log4j.properties
@@ -7,6 +7,13 @@ log4j.appender.CONSOLE.threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{dd MMM, yyyy HH:mm:ss} %p: %c %t - %m%n
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=${catalina.home}/logs/tomcat.log
+log4j.appender.R.MaxFileSize=10MB
+log4j.appender.R.MaxBackupIndex=10
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
+
log4j.logger.org.springframework=ERROR
log4j.logger.org.springframework.aop=DEBUG
log4j.logger.com.gluster=INFO \ No newline at end of file
diff --git a/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml
index 3c7d6436..700d996f 100644
--- a/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml
+++ b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml
@@ -21,6 +21,20 @@
<constructor-arg value="vmware" />
</bean>
+ <!-- SSH timeouts - all in milliseconds. zero means no timeout. -->
+ <!-- Connect the underlying TCP socket to the server with the given timeout value (SSH) -->
+ <bean id="sshConnectTimeout" class="java.lang.Integer">
+ <constructor-arg value="10000" />
+ </bean>
+ <!-- Timeout for complete connection establishment (SSH) -->
+ <bean id="sshKexTimeout" class="java.lang.Integer">
+ <constructor-arg value="60000" />
+ </bean>
+ <!-- Command execution timeout (SSH) -->
+ <bean id="sshExecTimeout" class="java.lang.Integer">
+ <constructor-arg value="120000" />
+ </bean>
+
<!-- Gluster Management Gateway Version -->
<bean id="appVersion" class="java.lang.String">
<constructor-arg value="1.0.0" />