diff options
| author | Shireesh Anjal <shireesh@gluster.com> | 2011-06-21 21:17:09 +0530 |
|---|---|---|
| committer | Shireesh Anjal <shireesh@gluster.com> | 2011-06-22 18:33:12 +0530 |
| commit | 5bb44641bf7b40f048e71281885efea68a3fbcbd (patch) | |
| tree | 77819aab61ec66e0f7a798c186c2170aeaa11e62 /src/com.gluster.storage.management.server | |
| parent | 8c5c224a98f194402f1ce413d6d1dd59946e2d52 (diff) | |
REST API enhancements
Diffstat (limited to 'src/com.gluster.storage.management.server')
4 files changed, 558 insertions, 264 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 2fcf3875..d96ea5f5 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 @@ -19,12 +19,21 @@ package com.gluster.storage.management.server.resources; import java.net.URI; +import java.util.ArrayList; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.UriInfo; +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.response.VolumeListResponse; + /** * */ @@ -74,7 +83,7 @@ public class AbstractResource { * @return the {@link Response} object */ protected Response errorResponse(String errMessage) { - return Response.serverError().entity(errMessage).build(); + return Response.serverError().type(MediaType.TEXT_HTML).entity(errMessage).build(); } /** @@ -86,6 +95,33 @@ public class AbstractResource { * @return the {@link Response} object */ protected Response badRequestResponse(String errMessage) { - return Response.status(Status.BAD_REQUEST).entity(errMessage).build(); + return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_HTML).entity(errMessage).build(); + } + + /** + * Creates an OK response and sets the entity in the response body. + * + * @param entity + * Entity to be set in the response body + * @param mediaType + * Media type to be set on the response + * @return the {@link Response} object + */ + protected Response okResponse(Object entity, String mediaType) { + return Response.ok(entity).type(mediaType).build(); + } + + /** + * Creates a streaming output response and sets the given streaming output in the response. Typically used for + * "download" requests + * + * @param entity + * Entity to be set in the response body + * @param mediaType + * Media type to be set on the response + * @return the {@link Response} object + */ + protected Response streamingOutputResponse(StreamingOutput output) { + return Response.ok(output).type(MediaType.APPLICATION_OCTET_STREAM).build(); } } 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 740f7cfa..4359b7d5 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 @@ -37,12 +37,14 @@ 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 static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_FORMAT; import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_DISCOVERED_SERVERS; import com.sun.jersey.spi.resource.Singleton; @Component @Singleton -@Path(RESOURCE_PATH_DISCOVERED_SERVERS) +@Path(RESOURCE_PATH_DISCOVERED_SERVERS + ".{" + PATH_PARAM_FORMAT + "}") public class DiscoveredServersResource extends AbstractServersResource { private List<String> discoveredServerNames = new ArrayList<String>(); 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 71dc3579..369ef349 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 @@ -20,13 +20,20 @@ */ 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_OPERATION; +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; import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_TARGET; -import static com.gluster.storage.management.core.constants.RESTConstants.TASK_START; -import static com.gluster.storage.management.core.constants.RESTConstants.TASK_STOP; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_AUTO_COMMIT; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_TRANSPORT_TYPE; +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; @@ -45,6 +52,8 @@ import static com.gluster.storage.management.core.constants.RESTConstants.RESOUR 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_VOLUMES; +import static com.gluster.storage.management.core.constants.RESTConstants.TASK_START; +import static com.gluster.storage.management.core.constants.RESTConstants.TASK_STOP; import java.io.File; import java.io.IOException; @@ -56,7 +65,6 @@ import java.util.Comparator; import java.util.Date; import java.util.List; -import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.FormParam; import javax.ws.rs.GET; @@ -68,6 +76,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; import com.gluster.storage.management.core.constants.CoreConstants; @@ -77,9 +86,8 @@ import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; import com.gluster.storage.management.core.model.Brick; import com.gluster.storage.management.core.model.GlusterServer; 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.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; @@ -93,7 +101,6 @@ 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.utils.GlusterUtil; import com.gluster.storage.management.server.utils.ServerUtil; import com.sun.jersey.api.core.InjectParam; @@ -101,7 +108,7 @@ import com.sun.jersey.spi.resource.Singleton; @Singleton @Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_VOLUMES) -public class VolumesResource { +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"; @@ -122,101 +129,215 @@ public class VolumesResource { private VolumeOptionsDefaults volumeOptionsDefaults; @GET - @Produces(MediaType.APPLICATION_XML) - public VolumeListResponse getAllVolumes(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + @Produces({MediaType.APPLICATION_XML}) + public Response getVolumesXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + return getVolumes(clusterName, MediaType.APPLICATION_XML); + } + + @GET + @Produces({MediaType.APPLICATION_JSON}) + public Response getVolumesJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + return getVolumes(clusterName, MediaType.APPLICATION_JSON); + } + + public Response getVolumes(String clusterName, String mediaType) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } + + return okResponse(getVolumes(clusterName), mediaType); + } + + public VolumeListResponse getVolumes(String clusterName) { GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - return new VolumeListResponse(Status.STATUS_SUCCESS, new ArrayList<Volume>()); + return new VolumeListResponse(new ArrayList<Volume>()); } try { - return new VolumeListResponse(Status.STATUS_SUCCESS, glusterUtil.getAllVolumes(onlineServer.getName())); + return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); } catch (ConnectionException e) { // online server has gone offline! try with a different one. onlineServer = glusterServersResource.getNewOnlineServer(clusterName); if (onlineServer == null) { - return new VolumeListResponse(Status.STATUS_SUCCESS, new ArrayList<Volume>()); + return new VolumeListResponse(new ArrayList<Volume>()); } - return new VolumeListResponse(Status.STATUS_SUCCESS, glusterUtil.getAllVolumes(onlineServer.getName())); + return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); } } @POST - @Consumes(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_XML) - public Status createVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, Volume volume) { - List<String> brickDirectories = GlusterCoreUtil.getQualifiedBrickList(volume.getBricks()); + public Response createVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @FormParam(FORM_PARAM_VOLUME_NAME) String volumeName, + @FormParam(FORM_PARAM_VOLUME_TYPE) String volumeType, @FormParam(FORM_PARAM_TRANSPORT_TYPE) String transportType, + @FormParam(FORM_PARAM_REPLICA_COUNT) Integer replicaCount, @FormParam(FORM_PARAM_STRIPE_COUNT) Integer stripeCount, + @FormParam(FORM_PARAM_BRICKS) String bricks, @FormParam(FORM_PARAM_ACCESS_PROTOCOLS) String accessProtocols, + @FormParam(FORM_PARAM_VOLUME_OPTIONS) String options) { + String missingParam = checkMissingParamsForCreateVolume(clusterName, volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); + if(missingParam != null) { + return badRequestResponse("Parameter [" + missingParam + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } + + if (volumeType.equals(VOLUME_TYPE.DISTRIBUTED_MIRROR) && replicaCount <= 0) { + return badRequestResponse("Replica count must be a positive integer"); + } + + if (volumeType.equals(VOLUME_TYPE.DISTRIBUTED_STRIPE) && stripeCount <= 0) { + return badRequestResponse("Stripe count must be a positive integer"); + } GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } - Status status = null; try { - status = glusterUtil.createVolume(volume, brickDirectories, onlineServer.getName()); + glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); + return createdResponse(volumeName); } catch (ConnectionException e) { // online server has gone offline! try with a different one. onlineServer = glusterServersResource.getNewOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName - + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); + return createdResponse(volumeName); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); } - status = glusterUtil.createVolume(volume, brickDirectories, onlineServer.getName()); } - return status; } - @SuppressWarnings("rawtypes") + /** + * Returns name of the missing parameter if any. If all parameters are present, + * @param clusterName + * @param volumeName + * @param volumeType + * @param transportType + * @param replicaCount + * @param stripeCount + * @param bricks + * @param accessProtocols + * @param options + * @return + */ + private String checkMissingParamsForCreateVolume(String clusterName, String volumeName, String volumeType, + String transportType, Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, + String options) { + + return (clusterName == null || clusterName.isEmpty()) ? FORM_PARAM_CLUSTER_NAME : + (volumeName == null || volumeName.isEmpty()) ? FORM_PARAM_VOLUME_NAME : + (volumeType == null || volumeType.isEmpty()) ? FORM_PARAM_VOLUME_TYPE : + (transportType == null || transportType.isEmpty()) ? FORM_PARAM_TRANSPORT_TYPE : + (replicaCount == null) ? FORM_PARAM_REPLICA_COUNT : + (stripeCount == null) ? FORM_PARAM_STRIPE_COUNT : + (bricks == null || bricks.isEmpty()) ? FORM_PARAM_BRICKS : + (accessProtocols == null || accessProtocols.isEmpty()) ? FORM_PARAM_ACCESS_PROTOCOLS : + (options == null || options.isEmpty()) ? FORM_PARAM_VOLUME_OPTIONS : + null; + } + @GET @Path("{" + PATH_PARAM_VOLUME_NAME + "}") @Produces(MediaType.APPLICATION_XML) - public GenericResponse getVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + public Response getVolumeXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + return getVolume(clusterName, volumeName, MediaType.APPLICATION_XML); + } + + @GET + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + @Produces(MediaType.APPLICATION_JSON) + public Response getVolumeJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + return getVolume(clusterName, volumeName, MediaType.APPLICATION_JSON); + } + + private Response getVolume(String clusterName, String volumeName, String mediaType) { + Volume volume = null; + + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } + + try { + volume = getVolume(clusterName, volumeName); + return okResponse(volume, mediaType); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + } + + private Volume getVolume(String clusterName, String volumeName) { + Volume volume; GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - return new GenericResponse<Volume>(new Status(Status.STATUS_CODE_FAILURE, - "No online servers found in cluster [" + clusterName + "]"), null); + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } try { - return new GenericResponse<Volume>(Status.STATUS_SUCCESS, glusterUtil.getVolume(volumeName, - onlineServer.getName())); + volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); } catch (ConnectionException e) { // online server has gone offline! try with a different one. onlineServer = glusterServersResource.getNewOnlineServer(clusterName); if (onlineServer == null) { - return new GenericResponse<Volume>(new Status(Status.STATUS_CODE_FAILURE, - "No online servers found in cluster [" + clusterName + "]"), null); + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } - return new GenericResponse<Volume>(Status.STATUS_SUCCESS, glusterUtil.getVolume(volumeName, - onlineServer.getName())); + volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); } + return volume; } @PUT @Path("{" + PATH_PARAM_VOLUME_NAME + "}") - @Produces(MediaType.APPLICATION_XML) - public Status performOperation(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + public Response performOperation(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_OPERATION) String operation) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } + GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } try { - return performOperation(volumeName, operation, onlineServer); + 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 new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName - + "]"); + 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()); } - return performOperation(volumeName, operation, onlineServer); } + return noContentResponse(); } private Status performOperation(String volumeName, String operation, GlusterServer onlineServer) { @@ -231,79 +352,121 @@ public class VolumesResource { @DELETE @Path("{" + PATH_PARAM_VOLUME_NAME + "}") - @Produces(MediaType.APPLICATION_XML) - public Status deleteVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + public Response deleteVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_DELETE_OPTION) boolean deleteFlag) { - GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); - if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName + "]"); + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); } + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } + Volume volume = null; try { - volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = glusterServersResource.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName - + "]"); - } - volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); + volume = getVolume(clusterName, volumeName); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse(e.getMessage()); } + List<Brick> bricks = volume.getBricks(); - Status status = glusterUtil.deleteVolume(volumeName, onlineServer.getName()); - - if (status.isSuccess()) { - Status postDeleteStatus = postDelete(volumeName, bricks, deleteFlag); - - if (!postDeleteStatus.isSuccess()) { - status.setCode(Status.STATUS_CODE_PART_SUCCESS); - status.setMessage("Error in post-delete operation: " + postDeleteStatus); - } + Status status = glusterUtil.deleteVolume(volumeName, glusterServersResource.getOnlineServer(clusterName) + .getName()); + if(!status.isSuccess()) { + return errorResponse("Couldn't delete volume [" + volumeName + "]. Error: " + status); } - return status; + + try { + postDelete(volumeName, bricks, deleteFlag); + } catch(Exception e) { + return errorResponse("Volume [" + volumeName + + "] deleted from cluster, however following errors happened: " + CoreConstants.NEWLINE + + e.getMessage()); + } + + return noContentResponse(); } @DELETE @Path("{" + QUERY_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - @Produces(MediaType.APPLICATION_XML) - public Status removeBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + public Response removeBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(QUERY_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICKS) String bricks, @QueryParam(QUERY_PARAM_DELETE_OPTION) boolean deleteFlag) { List<String> brickList = Arrays.asList(bricks.split(",")); // Convert from comma separated string (query // parameter) + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } - Status status = null; try { - status = glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); + removeBricks(clusterName, volumeName, brickList, onlineServer); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + + try { + cleanupDirectories(brickList, volumeName, brickList.size(), deleteFlag); + } catch(Exception e) { + // append cleanup error to prepare brick error + return errorResponse(e.getMessage()); + } + + return noContentResponse(); + } + + public void removeBricks(String clusterName, String volumeName, List<String> brickList, GlusterServer onlineServer) { + try { + glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); } catch (ConnectionException e) { // online server has gone offline! try with a different one. onlineServer = glusterServersResource.getNewOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName - + "]"); + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); } - status = glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); + glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); } + } - if (status.isSuccess()) { - Status cleanupStatus = cleanupDirectories(brickList, volumeName, brickList.size(), deleteFlag); - if (!cleanupStatus.isSuccess()) { - // append cleanup error to prepare brick error - status.setMessage(status.getMessage() + CoreConstants.NEWLINE + cleanupStatus.getMessage()); + @SuppressWarnings("rawtypes") + private void cleanupDirectories(List<String> bricks, String volumeName, int maxIndex, boolean deleteFlag) { + Status result; + String errors = ""; + for (int i = 0; i < maxIndex; i++) { + String[] brickInfo = bricks.get(i).split(":"); + String serverName = brickInfo[0]; + String brickDirectory = brickInfo[1]; + + String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); + Object response = serverUtil.executeOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " + + mountPoint + " " + volumeName + " " + (deleteFlag ? "-d" : ""), GenericResponse.class); + if (response instanceof GenericResponse) { + result = ((GenericResponse) response).getStatus(); + if (!result.isSuccess()) { + errors += "[" + mountPoint + "][" + volumeName + "] => " + result + + CoreConstants.NEWLINE; + } + } else { + Status errStatus = (Status) response; + errors += "[" + mountPoint + "][" + volumeName + "] => " + errStatus + CoreConstants.NEWLINE; } } - return status; + if(!errors.trim().isEmpty()) { + throw new GlusterRuntimeException("Volume directory cleanup errors: " + errors.trim()); + } } - private Status postDelete(String volumeName, List<Brick> bricks, boolean deleteFlag) { + private void postDelete(String volumeName, List<Brick> bricks, boolean deleteFlag) { Status result; for (Brick brick : bricks) { String brickDirectory = brick.getBrickDirectory(); @@ -312,93 +475,122 @@ public class VolumesResource { result = (Status) serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " + mountPoint + " " + volumeName + (deleteFlag ? " -d" : ""), Status.class); if (!result.isSuccess()) { - return result; + throw new GlusterRuntimeException("Error in post-delete operation of volume [" + volumeName + "]: " + + result); } } - return new Status(Status.STATUS_CODE_SUCCESS, "Post volume delete operation successfully initiated"); } @POST @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) - @Produces(MediaType.APPLICATION_XML) - public Status setOption(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + public Response setOption(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(RESTConstants.FORM_PARAM_OPTION_KEY) String key, @FormParam(RESTConstants.FORM_PARAM_OPTION_VALUE) String value) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_VOLUME_NAME + "] is missing in request!"); + } + + if(key == null || key.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_OPTION_KEY + "] is missing in request!"); + } + + if(value == null || value.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_OPTION_VALUE + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } + GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } - + try { - return glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); + glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); } catch (ConnectionException e) { // online server has gone offline! try with a different one. onlineServer = glusterServersResource.getNewOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName - + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); } - return glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); + } catch(Exception e) { + return errorResponse(e.getMessage()); } + + return noContentResponse(); } @PUT @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) - @Produces(MediaType.APPLICATION_XML) - public Status resetOptions(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + public Response resetOptions(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_VOLUME_NAME + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } + GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } try { - return glusterUtil.resetOptions(volumeName, onlineServer.getName()); + glusterUtil.resetOptions(volumeName, onlineServer.getName()); } catch (ConnectionException e) { // online server has gone offline! try with a different one. onlineServer = glusterServersResource.getNewOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName - + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } - return glusterUtil.resetOptions(volumeName, onlineServer.getName()); + + try { + glusterUtil.resetOptions(volumeName, onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch(Exception e) { + return errorResponse(e.getMessage()); } + + return noContentResponse(); } @GET @Path(RESOURCE_DEFAULT_OPTIONS) @Produces(MediaType.APPLICATION_XML) - public VolumeOptionInfoListResponse getDefaultOptions(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + public VolumeOptionInfoListResponse getDefaultOptionsXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { // TODO: Fetch all volume options with their default values from GlusterFS // whenever such a CLI command is made available in GlusterFS return new VolumeOptionInfoListResponse(Status.STATUS_SUCCESS, volumeOptionsDefaults.getDefaults()); } - @SuppressWarnings("rawtypes") - private Status cleanupDirectories(List<String> bricks, String volumeName, int maxIndex, boolean deleteFlag) { - Status result; - for (int i = 0; i < maxIndex; i++) { - String[] brickInfo = bricks.get(i).split(":"); - String serverName = brickInfo[0]; - String brickDirectory = brickInfo[1]; - - String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); - Object response = serverUtil.executeOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " - + mountPoint + " " + volumeName + " " + (deleteFlag ? "-d" : ""), GenericResponse.class); - if (response instanceof GenericResponse) { - result = ((GenericResponse) response).getStatus(); - if (!result.isSuccess()) { - // TODO: append error and continue with cleaning up of other directories - return result; - } - } else { - // TODO: append error and continue with cleaning up of other directories - // In case of script execution failure, a Status object will be returned. - return (Status) response; - } - } - return new Status(Status.STATUS_CODE_SUCCESS, "Directories cleaned up successfully!"); + @GET + @Path(RESOURCE_DEFAULT_OPTIONS) + @Produces(MediaType.APPLICATION_JSON) + public VolumeOptionInfoListResponse getDefaultOptionsJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + // TODO: Fetch all volume options with their default values from GlusterFS + // whenever such a CLI command is made available in GlusterFS + return new VolumeOptionInfoListResponse(Status.STATUS_SUCCESS, volumeOptionsDefaults.getDefaults()); } private List<VolumeLogMessage> getBrickLogs(Volume volume, Brick brick, Integer lineCount) @@ -436,34 +628,38 @@ public class VolumesResource { @GET @Produces(MediaType.APPLICATION_OCTET_STREAM) @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS + "/" + RESOURCE_DOWNLOAD) - public StreamingOutput downloadLogs(@PathParam(PATH_PARAM_CLUSTER_NAME) final String clusterName, + public Response downloadLogs(@PathParam(PATH_PARAM_CLUSTER_NAME) final String clusterName, @PathParam(PATH_PARAM_VOLUME_NAME) final String volumeName) { - final ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - throw new GlusterRuntimeException("Cluster [" + clusterName + "] doesn't exist!"); + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); } - - final Volume volume = (Volume) getVolume(clusterName, volumeName).getData(); - if (volume == null) { - throw new GlusterRuntimeException("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName - + "]!"); + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); } - - return new StreamingOutput() { - - @Override - public void write(OutputStream output) throws IOException, WebApplicationException { - try { - File archiveFile = new File(downloadLogs(volume)); - output.write(FileUtil.readFileAsByteArray(archiveFile)); - archiveFile.delete(); - } catch (Exception e) { - // TODO: Log the exception - e.printStackTrace(); - throw new GlusterRuntimeException("Exception while downloading/archiving volume log files!", e); + + try { + final Volume volume = getVolume(clusterName, volumeName); + StreamingOutput output = new StreamingOutput() { + + @Override + public void write(OutputStream output) throws IOException, WebApplicationException { + try { + File archiveFile = new File(downloadLogs(volume)); + output.write(FileUtil.readFileAsByteArray(archiveFile)); + archiveFile.delete(); + } catch (Exception e) { + // TODO: Log the exception + e.printStackTrace(); + String errMsg = "Exception while downloading/archiving volume log files : " + e.getMessage(); + output.write(errMsg.getBytes()); + } } - } - }; + }; + return streamingOutputResponse(output); + } catch(Exception e) { + return errorResponse("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]!"); + } } private String downloadLogs(Volume volume) { @@ -498,45 +694,66 @@ public class VolumesResource { @GET @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS) - public LogMessageListResponse getLogs(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @Produces(MediaType.APPLICATION_XML) + public Response getLogsXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICK_NAME) String brickName, @QueryParam(QUERY_PARAM_LOG_SEVERITY) String severity, @QueryParam(QUERY_PARAM_FROM_TIMESTAMP) String fromTimestamp, @QueryParam(QUERY_PARAM_TO_TIMESTAMP) String toTimestamp, @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount, @QueryParam(QUERY_PARAM_DOWNLOAD) Boolean download) { - List<VolumeLogMessage> logMessages = null; + return getLogs(clusterName, volumeName, brickName, severity, fromTimestamp, toTimestamp, lineCount, MediaType.APPLICATION_XML); + } - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return new LogMessageListResponse(new Status(Status.STATUS_CODE_FAILURE, "Cluster [" + clusterName - + "] doesn't exist!"), null); + @GET + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS) + @Produces(MediaType.APPLICATION_JSON) + public Response getLogsJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICK_NAME) String brickName, + @QueryParam(QUERY_PARAM_LOG_SEVERITY) String severity, + @QueryParam(QUERY_PARAM_FROM_TIMESTAMP) String fromTimestamp, + @QueryParam(QUERY_PARAM_TO_TIMESTAMP) String toTimestamp, + @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount, @QueryParam(QUERY_PARAM_DOWNLOAD) Boolean download) { + return getLogs(clusterName, volumeName, brickName, severity, fromTimestamp, toTimestamp, lineCount, MediaType.APPLICATION_JSON); + } + + public Response getLogs(String clusterName, String volumeName, String brickName, String severity, + String fromTimestamp, String toTimestamp, Integer lineCount, String mediaType) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_VOLUME_NAME + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); } + List<VolumeLogMessage> logMessages = null; + Volume volume = null; try { - Volume volume = (Volume) getVolume(clusterName, volumeName).getData(); - if (volume == null) { - return new LogMessageListResponse(new Status(Status.STATUS_CODE_FAILURE, "Volume [" + volumeName - + "] doesn't exist in cluster [" + clusterName + "]!"), null); - } + volume = (Volume) getVolume(clusterName, volumeName); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } - if (brickName == null || brickName.isEmpty() || brickName.equals(CoreConstants.ALL)) { - logMessages = getLogsForAllBricks(volume, lineCount); - } else { - // fetch logs for given brick of the volume - for (Brick brick : volume.getBricks()) { - if (brick.getQualifiedName().equals(brickName)) { - logMessages = getBrickLogs(volume, brick, lineCount); - break; - } + if (brickName == null || brickName.isEmpty() || brickName.equals(CoreConstants.ALL)) { + logMessages = getLogsForAllBricks(volume, lineCount); + } else { + // fetch logs for given brick of the volume + for (Brick brick : volume.getBricks()) { + if (brick.getQualifiedName().equals(brickName)) { + logMessages = getBrickLogs(volume, brick, lineCount); + break; } } - } catch (Exception e) { - return new LogMessageListResponse(new Status(e), null); } filterLogsBySeverity(logMessages, severity); filterLogsByTime(logMessages, fromTimestamp, toTimestamp); - return new LogMessageListResponse(Status.STATUS_SUCCESS, logMessages); + + return okResponse(new LogMessageListResponse(logMessages), mediaType); } private void filterLogsByTime(List<VolumeLogMessage> logMessages, String fromTimestamp, String toTimestamp) { @@ -600,71 +817,87 @@ public class VolumesResource { @POST @Path("{" + QUERY_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - public Status addBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + public Response addBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(QUERY_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_BRICKS) String bricks) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_VOLUME_NAME + "] is missing in request!"); + } + + if (bricks == null || bricks.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_BRICKS + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return badRequestResponse("Cluster [" + clusterName + "] not found!"); + } + GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } try { - return glusterUtil.addBricks(volumeName, Arrays.asList(bricks.split(",")), onlineServer.getName()); + glusterUtil.addBricks(volumeName, Arrays.asList(bricks.split(",")), onlineServer.getName()); } catch (ConnectionException e) { // online server has gone offline! try with a different one. onlineServer = glusterServersResource.getNewOnlineServer(clusterName); if (onlineServer == null) { - return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName - + "]"); + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } - return glusterUtil.addBricks(volumeName, Arrays.asList(bricks.split(",")), onlineServer.getName()); - } - } - -// @PUT -// @Path("{" + QUERY_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) -// public Status replaceBrick(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, -// @PathParam(QUERY_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_SOURCE) String diskFrom, -// @FormParam(FORM_PARAM_TARGET) String diskTo, @FormParam(FORM_PARAM_OPERATION) String operation) { -// GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); -// if (onlineServer == null) { -// return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName + "]"); -// } -// -// try { -// -// return glusterUtil.migrateDisk(volumeName, diskFrom, diskTo, "start", onlineServer.getName()); -// } catch (ConnectionException e) { -// // online server has gone offline! try with a different one. -// onlineServer = glusterServersResource.getNewOnlineServer(clusterName); -// if (onlineServer == null) { -// return new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" + clusterName -// + "]"); -// } -// return glusterUtil.migrateDisk(volumeName, diskFrom, diskTo, operation, onlineServer.getName()); -// } -// } - + + try { + glusterUtil.addBricks(volumeName, Arrays.asList(bricks.split(",")), onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + + return noContentResponse(); + } + @PUT @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - public TaskResponse migrateBrick(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + public Response migrateBrick(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_SOURCE) String fromBrick, @FormParam(FORM_PARAM_TARGET) String toBrick, @FormParam(FORM_PARAM_AUTO_COMMIT) Boolean autoCommit) { - TaskResponse taskResponse = new TaskResponse(); + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_VOLUME_NAME + "] is missing in request!"); + } + GlusterServer onlineServer = glusterServersResource.getOnlineServer(clusterName); if (onlineServer == null) { - taskResponse.setData(null); - taskResponse.setStatus(new Status(Status.STATUS_CODE_FAILURE, "No online servers found in cluster [" - + clusterName + "]")); - return taskResponse; + return errorResponse("No online servers found in cluster [" + clusterName + "]"); } - + + String taskId = null; try { - return glusterUtil.migrateBrick(volumeName, fromBrick, toBrick, "start", autoCommit, onlineServer.getName()); + 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); - return glusterUtil.migrateBrick(volumeName, fromBrick, toBrick, "start", autoCommit, onlineServer.getName()); + + try { + taskId = glusterUtil.migrateBrickStart(volumeName, fromBrick, toBrick, autoCommit, onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch(Exception e1) { + return errorResponse(e1.getMessage()); } + + return noContentResponse(uriInfo.getBaseUri() + "/" + RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + + "/" + RESOURCE_TASKS + "/" + taskId); } public static void main(String[] args) throws ClassNotFoundException { @@ -690,8 +923,6 @@ public class VolumesResource { // System.out.println("Code : " + status.getCode()); // System.out.println("Message " + status.getMessage()); - Status status1 = vr.removeBricks("testCluster", "test", "192.168.1.210:sdb", true); - System.out.println("Code : " + status1.getCode()); - System.out.println("Message " + status1.getMessage()); + vr.removeBricks("testCluster", "test", "192.168.1.210:sdb", true); } } 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 6b4bdb35..3472745e 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 @@ -23,12 +23,14 @@ package com.gluster.storage.management.server.utils; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Map.Entry; 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.GlusterRuntimeException; import com.gluster.storage.management.core.model.Brick; import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; @@ -43,6 +45,7 @@ import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; import com.gluster.storage.management.core.model.VolumeOptions; import com.gluster.storage.management.core.response.TaskResponse; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.server.resources.TasksResource; import com.gluster.storage.management.server.tasks.MigrateDiskTask; @@ -68,6 +71,8 @@ public class GlusterUtil { private static final String VOLUME_LOG_LOCATION_PFX = "log file location:"; private static final String VOLUME_TYPE_DISTRIBUTE = "Distribute"; private static final String VOLUME_TYPE_REPLICATE = "Replicate"; + + private static final GlusterCoreUtil glusterCoreUtil = new GlusterCoreUtil(); @Autowired private SshUtil sshUtil; @@ -203,41 +208,52 @@ public class GlusterUtil { return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume stop " + volumeName)); } - public Status resetOptions(String volumeName, String knownServer) { - return new Status(sshUtil.executeRemote(knownServer, "gluster volume reset " + volumeName)); + public void resetOptions(String volumeName, String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume reset " + volumeName); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't reset options for volume [" + volumeName + "]! Error: " + + result); + } } - public Status createVolume(Volume volume, List<String> brickDirectories, String knownServer) { + public void createVolume(String knownServer, String volumeName, String volumeTypeStr, String transportTypeStr, + Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, String options) { + int count = 1; // replica or stripe count - String volumeType = null; - VOLUME_TYPE volType = volume.getVolumeType(); + + VOLUME_TYPE volType = Volume.getVolumeTypeByStr(volumeTypeStr); + String volTypeArg = null; if (volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { - volumeType = "replica"; - count = volume.getReplicaCount(); + volTypeArg = "replica"; + count = replicaCount; } else if (volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { - volumeType = "stripe"; - count = volume.getStripeCount(); + volTypeArg = "stripe"; + count = stripeCount; } - String transportTypeStr = null; - TRANSPORT_TYPE transportType = volume.getTransportType(); - transportTypeStr = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; - String command = prepareVolumeCreateCommand(volume, brickDirectories, count, volumeType, transportTypeStr); + String transportTypeArg = null; + TRANSPORT_TYPE transportType = Volume.getTransportTypeByStr(transportTypeStr); + transportTypeArg = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; + + String command = prepareVolumeCreateCommand(volumeName, glusterCoreUtil.extractList(bricks, ","), count, + volTypeArg, transportTypeArg); ProcessResult result = sshUtil.executeRemote(knownServer, command); if (!result.isSuccess()) { - return new Status(result); + throw new GlusterRuntimeException("Error in creating volume [" + volumeName + "]: " + result); } - Status status = createOptions(volume, knownServer); - if (!status.isSuccess()) { // Return partial success if set volume option failed. - status.setCode(Status.STATUS_CODE_PART_SUCCESS); - status.setMessage("Error while setting volume options: " + status); + + try { + createOptions(volumeName, glusterCoreUtil.extractMap(options, ",", "="), knownServer); + } catch(Exception e) { + throw new GlusterRuntimeException( + "Volume created successfully, however following errors occurred while setting options: " + + CoreConstants.NEWLINE + e.getMessage()); } - return status; } - private String prepareVolumeCreateCommand(Volume volume, List<String> brickDirectories, int count, + private String prepareVolumeCreateCommand(String volumeName, List<String> brickDirectories, int count, String volumeType, String transportTypeStr) { - StringBuilder command = new StringBuilder("gluster volume create " + volume.getName() + " "); + StringBuilder command = new StringBuilder("gluster volume create " + volumeName + " "); if (volumeType != null) { command.append(volumeType + " " + count + " "); } @@ -248,24 +264,34 @@ public class GlusterUtil { return command.toString(); } - public Status createOptions(Volume volume, String knownServer) { - VolumeOptions options = volume.getOptions(); + public void createOptions(String volumeName, Map<String, String> options, String knownServer) { + String errors = ""; if (options != null) { for (Entry<String, String> option : options.entrySet()) { String key = option.getKey(); String value = option.getValue(); - Status status = setOption(volume.getName(), key, value, knownServer); - if (!status.isSuccess()) { - return status; + + try { + setOption(volumeName, key, value, knownServer); + } catch(Exception e) { + // append error + errors += e.getMessage() + CoreConstants.NEWLINE; } } } - return Status.STATUS_SUCCESS; + if (!errors.trim().isEmpty()) { + throw new GlusterRuntimeException("Errors while setting option(s) on volume [" + volumeName + "] : " + + errors.trim()); + } } - public Status setOption(String volumeName, String key, String value, String knownServer) { - return new Status(sshUtil.executeRemote(knownServer, "gluster volume set " + volumeName + " " + key + " " - + "\"" + value + "\"")); + public void setOption(String volumeName, String key, String value, String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume set " + volumeName + " " + key + " " + + "\"" + value + "\""); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Volume [" + volumeName + "] set [" + key + "=" + value + "] => " + + result); + } } public Status deleteVolume(String volumeName, String knownServer) { @@ -275,8 +301,8 @@ public class GlusterUtil { private String getVolumeInfo(String volumeName, String knownServer) { ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info " + volumeName); if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [gluster volume info] failed on [" + knownServer - + "] with error: " + result); + throw new GlusterRuntimeException("Command [gluster volume info " + volumeName + "] failed on [" + + knownServer + "] with error: " + result); } return result.getOutput(); } @@ -393,11 +419,7 @@ public class GlusterUtil { } public Volume getVolume(String volumeName, String knownServer) { - List<Volume> volumes = parseVolumeInfo(getVolumeInfo(volumeName, knownServer)); - if (volumes.size() > 0) { - return volumes.get(0); - } - return null; + return parseVolumeInfo(getVolumeInfo(volumeName, knownServer)).get(0); } public List<Volume> getAllVolumes(String knownServer) { @@ -467,12 +489,17 @@ public class GlusterUtil { return volumes; } - public Status addBricks(String volumeName, List<String> bricks, String knownServer) { + public void addBricks(String volumeName, List<String> bricks, String knownServer) { StringBuilder command = new StringBuilder("gluster volume add-brick " + volumeName); for (String brickDir : bricks) { command.append(" " + brickDir); } - return new Status(sshUtil.executeRemote(knownServer, command.toString())); + + ProcessResult result = sshUtil.executeRemote(knownServer, command.toString()); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Error in volume [" + volumeName + "] add-brick [" + bricks + "]: " + + result); + } } public String getLogLocation(String volumeName, String brickName, String knownServer) { @@ -501,19 +528,18 @@ public class GlusterUtil { } - public TaskResponse migrateBrick(String volumeName, String fromBrick, String toBrick, String operation, - Boolean autoCommit, String knownServer) { - TaskResponse taskResponse = new TaskResponse(); + 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); } - taskResponse.setData(taskInfo); - taskResponse.setStatus(new Status(Status.STATUS_CODE_SUCCESS, "")); - return taskResponse; + + return taskInfo.getId(); } public Status removeBricks(String volumeName, List<String> bricks, String knownServer) { @@ -534,7 +560,6 @@ public class GlusterUtil { List<String> disks = new ArrayList<String>(); disks.add("server1:sda"); disks.add("server1:sdb"); - Status status = new GlusterUtil().addBricks("Volume3", disks, "localhost"); - System.out.println(status); + new GlusterUtil().addBricks("Volume3", disks, "localhost"); } } |
