From 429d3149d5cf042f1aabc5836d7df451c7da06bd Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Tue, 5 Jul 2011 13:16:45 +0530 Subject: Changed base URI of REST resources to include the API version --- .../storage/management/client/UsersClient.java | 41 +- .../client/constants/ClientConstants.java | 2 +- .../management/client/utils/ClientUtil.java | 2 +- src/com.gluster.storage.management.core/.classpath | 1 + .../META-INF/MANIFEST.MF | 5 +- .../build.properties | 5 +- .../lib/log4j-1.2.16.jar | Bin 0 -> 481534 bytes .../storage/management/core/model/User.java | 3 + .../WebContent/WEB-INF/web.xml | 8 +- .../server/resources/AbstractResource.java | 184 ---- .../server/resources/AbstractServersResource.java | 38 - .../server/resources/AlertsResource.java | 82 -- .../server/resources/ClustersResource.java | 141 --- .../resources/DiscoveredServersResource.java | 141 --- .../server/resources/GlusterServersResource.java | 444 --------- .../management/server/resources/TasksResource.java | 175 ---- .../management/server/resources/UsersResource.java | 87 -- .../server/resources/VolumesResource.java | 1025 -------------------- .../server/resources/v1_0/AbstractResource.java | 173 ++++ .../resources/v1_0/AbstractServersResource.java | 38 + .../server/resources/v1_0/AlertsResource.java | 82 ++ .../server/resources/v1_0/ClustersResource.java | 141 +++ .../resources/v1_0/DiscoveredServersResource.java | 141 +++ .../resources/v1_0/GlusterServersResource.java | 444 +++++++++ .../server/resources/v1_0/TasksResource.java | 175 ++++ .../server/resources/v1_0/UsersResource.java | 91 ++ .../server/resources/v1_0/VolumesResource.java | 1025 ++++++++++++++++++++ .../server/tasks/ServerDiscoveryTask.java | 2 +- .../management/server/utils/GlusterUtil.java | 2 +- .../src/spring/gluster-server-security.xml | 2 +- 30 files changed, 2353 insertions(+), 2347 deletions(-) create mode 100644 src/com.gluster.storage.management.core/lib/log4j-1.2.16.jar delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AlertsResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AlertsResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java (limited to 'src') diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java index c839a15a..6dc251dc 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/UsersClient.java @@ -22,6 +22,8 @@ import java.net.ConnectException; import javax.ws.rs.core.Response; +import org.apache.log4j.Logger; + import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; import com.gluster.storage.management.core.model.Status; import com.sun.jersey.api.client.UniformInterfaceException; @@ -32,6 +34,7 @@ public class UsersClient extends AbstractClient { private static final String RESOURCE_NAME = "users"; private static final String FORM_PARAM_OLD_PASSWORD = "oldpassword"; private static final String FORM_PARAM_NEW_PASSWORD = "newpassword"; + private static final Logger logger = Logger.getLogger(UsersClient.class); private String generateSecurityToken(String user, String password) { return new String(Base64.encode(user + ":" + password)); @@ -44,7 +47,7 @@ public class UsersClient extends AbstractClient { public void authenticate(String user, String password) { setSecurityToken(generateSecurityToken(user, password)); try { - fetchSubResource(user, String.class); + fetchSubResource(user, Status.class); } catch (RuntimeException e) { Throwable cause = e.getCause(); if(cause == null) { @@ -58,14 +61,16 @@ public class UsersClient extends AbstractClient { setSecurityToken(null); throw new GlusterRuntimeException("Invalid user id or password!"); } else { - // TODO: Log the exception - throw new GlusterRuntimeException("Exception during authentication: [" - + e1.getResponse().getStatus() + "]"); + String errMsg = "Exception during authentication: [" + e1.getResponse().getStatus() + "]"; + logger.error(errMsg); + throw new GlusterRuntimeException(errMsg); } } else if(cause instanceof ConnectException) { throw new GlusterRuntimeException("Couldn't connect to Gluster Management Gateway!"); } else { - throw new GlusterRuntimeException("Exception during authentication: [" + e.getMessage() + "]"); + String errMsg = "Exception during authentication: [" + e.getMessage() + "]"; + logger.error(errMsg); + throw new GlusterRuntimeException(errMsg); } } } @@ -80,20 +85,18 @@ public class UsersClient extends AbstractClient { } public static void main(String[] args) { -// UsersClient authClient = new UsersClient(); -// -// // authenticate user -// authClient.authenticate("gluster", "gluster"); -// -// // change password to gluster1 -// authClient.changePassword("gluster", "gluster", "gluster1"); -// -// // change it back to gluster -// authClient.changePassword("gluster", "gluster1", "gluster"); -// -// System.out.println("success"); - System.out.println(new String(Base64.encode("abcdefghijklmnopqrstuvwxyz"))); - System.out.println(new String(Base64.decode("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo="))); + UsersClient authClient = new UsersClient(); + + // authenticate user + authClient.authenticate("gluster", "gluster"); + + // change password to gluster1 + authClient.changePassword("gluster", "gluster", "gluster1"); + + // change it back to gluster + authClient.changePassword("gluster", "gluster1", "gluster"); + + System.out.println("success"); } /* diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java index 4726fc36..765735fb 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/constants/ClientConstants.java @@ -27,7 +27,7 @@ public class ClientConstants { public static final String SYS_PROP_SERVER_URL = "gluster.server.url"; public static final String DEFAULT_SERVER_URL = "https://localhost:8443/glustermg/linux.gtk.x86_64"; public static final String CONTEXT_ROOT = "glustermg"; - public static final String WEB_RESOURCE_BASE_PATH = "resources"; + public static final String REST_API_VERSION = "1.0"; // SSL related public static final String TRUSTED_KEYSTORE = "gmc-trusted.keystore"; diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java index 4f7ea64e..3f87fd27 100644 --- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java +++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/utils/ClientUtil.java @@ -9,7 +9,7 @@ import com.gluster.storage.management.client.constants.ClientConstants; public class ClientUtil { public static URI getServerBaseURI() { - return UriBuilder.fromUri(getBaseURL()).path(ClientConstants.WEB_RESOURCE_BASE_PATH).build(); + return UriBuilder.fromUri(getBaseURL()).path(ClientConstants.REST_API_VERSION).build(); } private static String getBaseURL() { diff --git a/src/com.gluster.storage.management.core/.classpath b/src/com.gluster.storage.management.core/.classpath index b41cbcdb..221aeec4 100644 --- a/src/com.gluster.storage.management.core/.classpath +++ b/src/com.gluster.storage.management.core/.classpath @@ -1,5 +1,6 @@ + diff --git a/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF index a32970c8..fae660fb 100644 --- a/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF +++ b/src/com.gluster.storage.management.core/META-INF/MANIFEST.MF @@ -9,5 +9,8 @@ Export-Package: com.gluster.storage.management.core.constants, com.gluster.storage.management.core.exceptions, com.gluster.storage.management.core.model, com.gluster.storage.management.core.response, - com.gluster.storage.management.core.utils + com.gluster.storage.management.core.utils, + org.apache.log4j Require-Bundle: org.eclipse.core.runtime;bundle-version="3.6.0" +Bundle-ClassPath: lib/log4j-1.2.16.jar, + . diff --git a/src/com.gluster.storage.management.core/build.properties b/src/com.gluster.storage.management.core/build.properties index 34d2e4d2..89d32a46 100644 --- a/src/com.gluster.storage.management.core/build.properties +++ b/src/com.gluster.storage.management.core/build.properties @@ -1,4 +1,7 @@ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ - . + .,\ + lib/ +src.includes = lib/,\ + src/ diff --git a/src/com.gluster.storage.management.core/lib/log4j-1.2.16.jar b/src/com.gluster.storage.management.core/lib/log4j-1.2.16.jar new file mode 100644 index 00000000..3f9d8476 Binary files /dev/null and b/src/com.gluster.storage.management.core/lib/log4j-1.2.16.jar differ diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java index da92ca14..ed5d12f7 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/User.java @@ -19,6 +19,7 @@ package com.gluster.storage.management.core.model; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; @XmlRootElement public class User { @@ -31,6 +32,8 @@ public class User { public void setUserId(String userId) { this.userId = userId; } + + @XmlTransient public String getPassword() { return password; } diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml index 4aaa3c9b..7c20d6c7 100644 --- a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml +++ b/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml @@ -30,12 +30,12 @@ - gluster-resources + gluster-resources-1.0 com.sun.jersey.spi.spring.container.servlet.SpringServlet com.sun.jersey.config.property.packages - com.gluster.storage.management.server.resources + com.gluster.storage.management.server.resources.v1_0 com.sun.jersey.spi.container.ResourceFilters @@ -44,8 +44,8 @@ 1 - gluster-resources - /resources/* + gluster-resources-1.0 + /1.0/* 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 deleted file mode 100644 index feef8b3e..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java +++ /dev/null @@ -1,184 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -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; - -/** - * - */ -public class AbstractResource { - @Context - protected UriInfo uriInfo; - - /** - * Creates a response with HTTP status code of 201 (created) and sets the "location" header to the URI created using - * the given path relative to current path. - * - * @param relativePath - * relative path of the created resource - will be set in the "location" header of response. - * @return the {@link Response} object - */ - protected Response createdResponse(String relativePath) { - return Response.created(createRelatriveURI(relativePath)).build(); - } - - /** - * Creates a response with HTTP status code of 204 (no content) - * @return the {@link Response} object - */ - protected Response noContentResponse() { - return Response.noContent().build(); - } - - /** - * 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 locationURI - * URI to be appended to the base URI - * @return the {@link Response} object - */ - 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 base URI of the application - * @param uriString URI String to be appended to the base URI - * @return newly created URI - */ - private URI createAbsoluteURI(String uriString) { - return uriInfo.getBaseUriBuilder().path(uriString).build(); - } - - /** - * Creates a response with HTTP status code of 204 (no content), also setting the location header to given location - * @param location path of the location to be set relative to current path - * @return the {@link Response} object - */ - protected Response noContentResponse(String location) { - return Response.noContent().location(createRelatriveURI(location)).build(); - } - - /** - * Creates a URI relative to current URI - * @param location path relative to current URI - * @return newly created URI - */ - protected URI createRelatriveURI(String location) { - return uriInfo.getAbsolutePathBuilder().path(location).build(); - } - - /** - * Creates a response with HTTP status code of 500 (internal server error) and sets the error message in the - * response body - * - * @param errMessage - * Error message to be set in the response body - * @return the {@link Response} object - */ - protected Response errorResponse(String errMessage) { - return Response.serverError().type(MediaType.TEXT_HTML).entity(errMessage).build(); - } - - /** - * Creates a response with HTTP status code of 400 (bad request) and sets the error message in the - * response body - * - * @param errMessage - * Error message to be set in the response body - * @return the {@link Response} object - */ - 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. - * - * @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 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 - * - * @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/AbstractServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java deleted file mode 100644 index dd6e2804..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractServersResource.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * AbstractServersResource.java - * - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - */ -package com.gluster.storage.management.server.resources; - -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.ServerUtil; -import com.sun.jersey.api.core.InjectParam; - -/** - * Abstract resource class for servers. Abstracts basic server related functionality like "get server details". - */ -public class AbstractServersResource extends AbstractResource { - @InjectParam - protected ServerUtil serverUtil; - - @InjectParam - protected GlusterUtil glusterUtil; - - // TODO: Remove this class! -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AlertsResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AlertsResource.java deleted file mode 100644 index 3c70beec..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AlertsResource.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.*; - -import java.util.ArrayList; -import java.util.List; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.model.AlertListResponse; -import com.gluster.storage.management.core.model.Alert; - -@Component -@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_ALERTS) -public class AlertsResource { - - @GET - @Produces(MediaType.APPLICATION_XML) - public AlertListResponse getAlerts() { - - List alerts = new ArrayList(); - - // TODO To implement the following dummy alerts - // Alert #1 - Alert alert = new Alert(); - alert.setId("0001"); - alert.setReference("Server1"); // Server - alert.setType(Alert.ALERT_TYPES.CPU_USAGE_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " in server [" + alert.getReference() + "]"); - alerts.add(alert); - - // Alert #2 - alert = new Alert(); - alert.setId("0002"); - alert.setReference("Server2"); // server:Disk - brick - alert.setType(Alert.ALERT_TYPES.MEMORY_USAGE_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " in server [" + alert.getReference() + "]"); - alerts.add(alert); - - // Alert #3 - alert = new Alert(); - alert.setId("0003"); - alert.setReference("server1:sda1"); // Disk name - alert.setType(Alert.ALERT_TYPES.DISK_USAGE_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " in disk [" + alert.getReference() + "]"); - alerts.add(alert); - - // Alert #4 - alert = new Alert(); - alert.setId("0004"); - alert.setReference("Volume3:server2:sda1"); // volume:[Disk name] - alert.setType(Alert.ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " in volume [" + alert.getReference().split(":")[0] - + "] disk [" + alert.getReference().split(":")[1] + ":" + alert.getReference().split(":")[2] + "]"); - alerts.add(alert); - - // Alert #5 - alert = new Alert(); - alert.setId("0005"); - alert.setReference("Server2"); // Server name - alert.setType(Alert.ALERT_TYPES.OFFLINE_SERVERS_ALERT); - alert.setMessage(alert.getAlertType(alert.getType()) + " [" + alert.getReference() + "]"); - alerts.add(alert); - - return new AlertListResponse(alerts); - - } - - public static void main(String[] args) { - /* - * // Unit test code AlertsResource alertResource = new AlertsResource(); AlertsListResponse alertResponse = - * alertResource.getAlerts(); List alerts = alertResponse.getAlerts(); for (Alert alert: alerts) { - * System.out.println(alert.getMessage()); } - */ - } - -} 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 deleted file mode 100644 index 4c834973..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -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.PATH_PARAM_CLUSTER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; - -import java.util.ArrayList; -import java.util.List; - -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; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.response.ClusterNameListResponse; -import com.gluster.storage.management.server.data.ClusterInfo; -import com.gluster.storage.management.server.services.ClusterService; -import com.sun.jersey.api.core.InjectParam; -import com.sun.jersey.spi.resource.Singleton; - -/** - * - */ -@Component -@Singleton -@Path(RESOURCE_PATH_CLUSTERS) -public class ClustersResource extends AbstractResource { - @InjectParam - private ClusterService clusterService; - - @GET - @Produces(MediaType.APPLICATION_XML) - public ClusterNameListResponse getClusters() { - List clusters = clusterService.getAllClusters(); - List clusterList = new ArrayList(); - for (ClusterInfo cluster : clusters) { - clusterList.add(cluster.getName()); - } - return new ClusterNameListResponse(clusterList); - } - - @POST - public Response createCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String 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 + "] already exists!"); - } - - try { - clusterService.createCluster(clusterName); - return createdResponse(clusterName); - } catch (Exception e) { - // TODO: Log the exception - return errorResponse("Exception while trying to save cluster [" + clusterName + "]: [" + e.getMessage() - + "]"); - } - } - - @PUT - public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, - @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { - if(clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - if(knownServer == null || knownServer.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); - } - - if(clusterService.getCluster(clusterName) != null) { - return badRequestResponse("Cluster [" + clusterName + "] already exists!"); - } - - ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); - if(mappedCluster != null) { - return badRequestResponse("Server [" + knownServer + "] is already present in cluster [" - + mappedCluster.getName() + "]!"); - } - - try { - clusterService.registerCluster(clusterName, knownServer); - return noContentResponse(clusterName); - } catch(Exception e) { - // TODO: Log the exception - return errorResponse("Exception while trying to register cluster [" + clusterName + "] using server [" - + knownServer + "]: [" + e.getMessage() + "]"); - } - } - - @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") - @DELETE - public Response unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - if(clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if(cluster == null) { - return badRequestResponse("Cluster [" + clusterName + "] does not exist!"); - } - - try { - clusterService.unregisterCluster(cluster); - return noContentResponse(); - } catch (Exception e) { - // TODO: Log the exception - return errorResponse("Exception while trying to unregister cluster [" + clusterName + "]: [" - + e.getMessage() + "]"); - } - } -} 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 deleted file mode 100644 index 283ab147..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/DiscoveredServersResource.java +++ /dev/null @@ -1,141 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -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; -import java.util.List; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.model.Server; -import com.gluster.storage.management.core.response.ServerListResponse; -import com.gluster.storage.management.core.response.ServerNameListResponse; -import com.sun.jersey.spi.resource.Singleton; - -@Component -@Singleton -@Path(RESOURCE_PATH_DISCOVERED_SERVERS) -public class DiscoveredServersResource extends AbstractServersResource { - private List discoveredServerNames = new ArrayList(); - - public List getDiscoveredServerNames() { - return discoveredServerNames; - } - - public void setDiscoveredServerNames(List discoveredServerNames) { - synchronized (discoveredServerNames) { - this.discoveredServerNames = discoveredServerNames; - } - } - - public void removeDiscoveredServer(String serverName) { - discoveredServerNames.remove(serverName); - } - - public void addDiscoveredServer(String serverName) { - discoveredServerNames.add(serverName); - } - - @GET - @Produces(MediaType.APPLICATION_XML) - 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 discoveredServers = getDiscoveredServerDetails(); - return okResponse(new ServerListResponse(discoveredServers), mediaType); - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - } else { - return okResponse(new ServerNameListResponse(getDiscoveredServerNames()), mediaType); - } - } - - private List getDiscoveredServerDetails() { - List discoveredServers = new ArrayList(); - for (String serverName : getDiscoveredServerNames()) { - try { - discoveredServers.add(getDiscoveredServer(serverName)); - } catch(Exception e) { - // TODO: Log the exception - // continue with next discovered server - } - } - return discoveredServers; - } - - @Path("{" + PATH_PARAM_SERVER_NAME + "}") - @GET - @Produces(MediaType.APPLICATION_XML) - 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 { - return okResponse(getDiscoveredServer(serverName), mediaType); - } catch (Exception e) { - // TODO: Log the exception - return errorResponse(e.getMessage()); - } - } - - private Server getDiscoveredServer(String serverName) { - Server server = new Server(serverName); - serverUtil.fetchServerDetails(server); - return server; - } - - public static void main(String[] args) { - 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 deleted file mode 100644 index 1f4b15de..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/GlusterServersResource.java +++ /dev/null @@ -1,444 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -package com.gluster.storage.management.server.resources; - -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_CLUSTER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_DISK_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.PATH_PARAM_SERVER_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.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; - -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; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -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.response.GlusterServerListResponse; -import com.gluster.storage.management.server.data.ClusterInfo; -import com.gluster.storage.management.server.data.ServerInfo; -import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.tasks.InitializeDiskTask; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.SshUtil; -import com.sun.jersey.api.core.InjectParam; -import com.sun.jersey.spi.resource.Singleton; - -@Component -@Singleton -@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_SERVERS) -public class GlusterServersResource extends AbstractServersResource { - - public static final String HOSTNAMETAG = "hostname:"; - - @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); - serverUtil.fetchServerDetails(server); - } catch (ConnectionException e) { - server.setStatus(SERVER_STATUS.OFFLINE); - } - } - - - @GET - @Produces(MediaType.APPLICATION_JSON) - 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) { - return getGlusterServers(clusterName, MediaType.APPLICATION_XML); - } - - public Response getGlusterServers(String clusterName, String mediaType) { - List glusterServers = new ArrayList(); - - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if (cluster.getServers().size() == 0) { - return okResponse(new GlusterServerListResponse(glusterServers), mediaType); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterServers = getGlusterServers(clusterName, onlineServer); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - try { - glusterServers = getGlusterServers(clusterName, onlineServer); - } catch (Exception e1) { - return errorResponse(e1.getMessage()); - } - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - - String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); - if (!errMsg.isEmpty()) { - return errorResponse("Couldn't fetch details for server(s): " + errMsg); - } - - return okResponse(new GlusterServerListResponse(glusterServers), mediaType); - } - - public String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { - String errMsg = ""; - - for (GlusterServer server : glusterServers) { - if (server.getStatus() == SERVER_STATUS.ONLINE && !server.getName().equals(onlineServer.getName())) { - try { - fetchServerDetails(server); - } catch (Exception e) { - errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; - } - } - } - return errMsg; - } - - public List getGlusterServers(String clusterName, GlusterServer onlineServer) { - List glusterServers; - try { - glusterServers = glusterUtil.getGlusterServers(onlineServer); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - glusterServers = glusterUtil.getGlusterServers(onlineServer); - } - return glusterServers; - } - - @GET - @Path("{serverName}") - @Produces(MediaType.APPLICATION_XML) - public Response getGlusterServerXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { - return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_XML); - } - - @GET - @Path("{serverName}") - @Produces(MediaType.APPLICATION_JSON) - public Response getGlusterServerJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { - return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_JSON); - } - - private Response getGlusterServerResponse(String clusterName, String serverName, String mediaType) { - try { - return okResponse(getGlusterServer(clusterName, serverName), mediaType); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - private GlusterServer getGlusterServer(String clusterName, String serverName) { - if (clusterName == null || clusterName.isEmpty()) { - throw new GlusterRuntimeException("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - throw new GlusterRuntimeException("Server name must not be empty!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - throw new GlusterRuntimeException("Cluster [" + clusterName + "] not found!"); - } - - 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) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - server = glusterUtil.getGlusterServer(onlineServer, serverName); - } - - if (server.isOnline()) { - fetchServerDetails(server); - } - return server; - } - - private void performAddServer(String clusterName, String serverName) { - 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) { - // online server has gone offline! try with a different one. - 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()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - 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 notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - boolean publicKeyInstalled = sshUtil.isPublicKeyInstalled(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 servers = cluster.getServers(); - 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) { - 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); - - if (!publicKeyInstalled) { - try { - // install public key (this will also disable password based ssh login) - sshUtil.installPublicKey(serverName); - } catch (Exception e) { - return errorResponse("Public key could not be installed on [" + serverName + "]! Error: [" - + e.getMessage() + "]"); - } - } - - return createdResponse(serverName); - } - - @DELETE - @Path("{" + PATH_PARAM_SERVER_NAME + "}") - public Response removeServer(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { - 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!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - List servers = cluster.getServers(); - if (servers == null || servers.isEmpty() || !containsServer(servers, serverName)) { - return badRequestResponse("Server [" + serverName + "] is not attached to cluster [" + clusterName + "]!"); - } - - 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 - clusterService.removeOnlineServer(clusterName); - } else { - try { - removeServerFromCluster(clusterName, serverName); - } 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 = clusterService.getOnlineServer(clusterName, serverName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.removeServer(onlineServer.getName(), serverName); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - 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)) { - // since the cached server has been removed from the cluster, remove it from the cache - 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. - // Hence add it back to the discovered servers list. - discoveredServersResource.addDiscoveredServer(serverName); - } - - private boolean containsServer(List servers, String serverName) { - 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, serverName, diskName); - try { - initializeTask.start(); - taskResource.addTask(initializeTask); - - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" - + initializeTask.getId()); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - private void setGlusterUtil(GlusterUtil glusterUtil) { - this.glusterUtil = glusterUtil; - } - - public static void main(String[] args) { - GlusterServersResource glusterServersResource = new GlusterServersResource(); - GlusterUtil glusterUtil = new GlusterUtil(); - glusterUtil.setSshUtil(new SshUtil()); - glusterServersResource.setGlusterUtil(glusterUtil); - // System.out.println(glusterServersResource.getServerDetails("127.0.0.1").size()); - - // To add a server - // GlusterServerResponse response = glusterServersResource.addServer("my-server"); - // System.out.println(response.getData().getName()); - } -} 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 deleted file mode 100644 index 53122f11..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/TasksResource.java +++ /dev/null @@ -1,175 +0,0 @@ -/** - * TaskResource.java - * - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - */ -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.RESOURCE_PATH_CLUSTERS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.ws.rs.DELETE; -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import com.gluster.storage.management.core.constants.RESTConstants; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.exceptions.GlusterValidationException; -import com.gluster.storage.management.core.model.TaskInfo; -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 extends AbstractResource { - private Map tasksMap = new HashMap(); - - public TasksResource() { - } - - public void addTask(Task task) { - tasksMap.put(task.getId(), task); - } - - public void removeTask(Task task) { - tasksMap.remove(task.getId()); - } - - public List getAllTasksInfo() { - List allTasksInfo = new ArrayList(); - for (Map.Entry entry : tasksMap.entrySet()) { - checkTaskStatus(entry.getKey()); - allTasksInfo.add(entry.getValue().getTaskInfo()); // TaskInfo with latest status - } - return allTasksInfo; - } - - public Task getTask(String taskId) { - for (Map.Entry entry : tasksMap.entrySet()) { - if (entry.getValue().getId().equals(taskId)) { - return entry.getValue(); - } - } - return null; - } - - @GET - @Produces(MediaType.APPLICATION_XML) - 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 { - Task task = checkTaskStatus(taskId); - return okResponse(task.getTaskInfo(), MediaType.APPLICATION_XML); - } catch (GlusterRuntimeException e) { - return errorResponse(e.getMessage()); - } - } - - 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 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); - - try { - if (taskOperation.equals(RESTConstants.TASK_RESUME)) { - 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(); - } - return (Response) noContentResponse(); - } catch(GlusterValidationException ve) { - return badRequestResponse(ve.getMessage()); - } catch (GlusterRuntimeException e) { - return errorResponse(e.getMessage()); - } - } - - @DELETE - @Path("/{" + PATH_PARAM_TASK_ID + "}") - @Produces(MediaType.APPLICATION_XML) - public Response deleteTask(@PathParam(PATH_PARAM_TASK_ID) String taskId, - @QueryParam(FORM_PARAM_OPERATION) String taskOperation) { - Task task = getTask(taskId); - if (task == null) { - return notFoundResponse("Task [" + taskId + "] not found!"); - } - - 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 deleted file mode 100644 index 0ccb4263..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/UsersResource.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - *******************************************************************************/ -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; -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.context.SecurityContextHolder; -import org.springframework.security.provisioning.JdbcUserDetailsManager; -import org.springframework.stereotype.Component; - -import com.sun.jersey.spi.resource.Singleton; - -@Singleton -@Component -@Path(RESOURCE_PATH_USERS) -public class UsersResource extends AbstractResource { - @Autowired - private JdbcUserDetailsManager jdbcUserService; - - @Autowired - private PasswordEncoder passwordEncoder; - - @Path("{" + PATH_PARAM_USER + "}") - @GET - @Produces(MediaType.APPLICATION_XML) - 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 getAuthenticationResponse(user, MediaType.APPLICATION_JSON); - } - - public Response getAuthenticationResponse(String user, String mediaType) { - return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? okResponse(mediaType) - : unauthorizedResponse()); - } - - @Path("{" + PATH_PARAM_USER + "}") - @PUT - public Response changePassword(@FormParam("oldpassword") String oldPassword, - @FormParam("newpassword") String newPassword) { - try { - jdbcUserService.changePassword(oldPassword, passwordEncoder.encodePassword(newPassword, null)); - } catch (Exception ex) { - // TODO: Log the exception - ex.printStackTrace(); - return errorResponse("Could not change password. Error: [" + ex.getMessage() + "]"); - } - 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 deleted file mode 100644 index 7ccd2f3c..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java +++ /dev/null @@ -1,1025 +0,0 @@ -/** - * VolumesResource.java - * - * Copyright (c) 2011 Gluster, Inc. - * 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 - * . - */ -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_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; -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_TARGET; -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.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; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_BRICK_NAME; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DELETE_OPTION; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DOWNLOAD; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_FROM_TIMESTAMP; -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.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; - -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.List; - -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; -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; -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.Brick; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Status; -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; -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.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.MigrateBrickTask; -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; -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 VOLUME_DIRECTORY_CLEANUP_SCRIPT = "clear_volume_directory.py"; - private static final String VOLUME_BRICK_LOG_SCRIPT = "get_volume_brick_log.py"; - - @InjectParam - private ServerUtil serverUtil; - - @InjectParam - private GlusterUtil glusterUtil; - - @InjectParam - private ClusterService clusterService; - - @InjectParam - private VolumeOptionsDefaults volumeOptionsDefaults; - - @InjectParam - private TasksResource taskResource; - - @GET - @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("Cluster name must not be empty!"); - } - - 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 = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return new VolumeListResponse(new ArrayList()); - } - - try { - return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return new VolumeListResponse(new ArrayList()); - } - - return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); - } - } - - @POST - @Produces(MediaType.APPLICATION_XML) - 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) { - if(clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - String missingParam = checkMissingParamsForCreateVolume(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 notFoundResponse("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"); - } - - try { - performCreateVolume(clusterName, volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, - options); - return createdResponse(volumeName); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - public void performCreateVolume(String clusterName, String volumeName, String volumeType, String transportType, Integer replicaCount, - Integer stripeCount, String bricks, String accessProtocols, String options) { - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); - } - } - - /** - * Returns name of the missing parameter if any. If all parameters are present, - * @param volumeName - * @param volumeType - * @param transportType - * @param replicaCount - * @param stripeCount - * @param bricks - * @param accessProtocols - * @param options - * @return - */ - private String checkMissingParamsForCreateVolume(String volumeName, String volumeType, - String transportType, Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, - String options) { - - return (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 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("Cluster name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("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 = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - try { - volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); - } - return volume; - } - - @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, - @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!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - 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 { - if (onlineServer == null) { - 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); - } - } - - private Status performOperation(String volumeName, String operation, GlusterServer onlineServer) { - if (operation.equals(TASK_START)) { - return glusterUtil.startVolume(volumeName, onlineServer.getName()); - } else if (operation.equals(TASK_STOP)) { - return glusterUtil.stopVolume(volumeName, onlineServer.getName()); - } else { - return new Status(Status.STATUS_CODE_FAILURE, "Invalid operation code [" + operation + "]"); - } - } - - @DELETE - @Path("{" + PATH_PARAM_VOLUME_NAME + "}") - public Response deleteVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, - @QueryParam(QUERY_PARAM_DELETE_OPTION) Boolean deleteFlag) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if (deleteFlag == null) { - deleteFlag = false; - } - - Volume volume = null; - try { - volume = getVolume(clusterName, volumeName); - } catch (Exception e) { - // TODO: Log the exception - return errorResponse(e.getMessage()); - } - - List bricks = volume.getBricks(); - Status status = glusterUtil.deleteVolume(volumeName, clusterService.getOnlineServer(clusterName) - .getName()); - if(!status.isSuccess()) { - return errorResponse("Couldn't delete volume [" + volumeName + "]. Error: " + 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("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - public Response removeBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICKS) String bricks, - @QueryParam(QUERY_PARAM_DELETE_OPTION) Boolean deleteFlag) { - List brickList = Arrays.asList(bricks.split(",")); // Convert from comma separated string (query - // parameter) - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (bricks == null || bricks.isEmpty()) { - return badRequestResponse("Parameter [" + QUERY_PARAM_BRICKS + "] is missing in request!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if(deleteFlag == null) { - deleteFlag = false; - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - 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 brickList, GlusterServer onlineServer) { - try { - glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); - } - } - - @SuppressWarnings("rawtypes") - private void cleanupDirectories(List 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; - } - } - if(!errors.trim().isEmpty()) { - throw new GlusterRuntimeException("Volume directory cleanup errors: " + errors.trim()); - } - } - - private void postDelete(String volumeName, List bricks, boolean deleteFlag) { - Status result; - for (Brick brick : bricks) { - String brickDirectory = brick.getBrickDirectory(); - String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); - - result = (Status) serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_DIRECTORY_CLEANUP_SCRIPT - + " " + mountPoint + " " + volumeName + (deleteFlag ? " -d" : ""), Status.class); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Error in post-delete operation of volume [" + volumeName + "]: " - + result); - } - } - } - - @POST - @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) - 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("Cluster name must not be empty!"); - } - - if(volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - 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 notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); - } catch(Exception e1) { - return errorResponse(e1.getMessage()); - } - } catch(Exception e) { - return errorResponse(e.getMessage()); - } - - return createdResponse(key); - } - - @PUT - @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) - public Response resetOptions(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if(volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.resetOptions(volumeName, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - 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 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()); - } - - @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 getBrickLogs(Volume volume, Brick brick, Integer lineCount) - throws GlusterRuntimeException { - String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), brick.getServerName()); - String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getBrickDirectory()); - String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; - - // Usage: get_volume_disk_log.py - Object responseObj = serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_BRICK_LOG_SCRIPT + " " - + logFilePath + " " + lineCount, LogMessageListResponse.class); - - LogMessageListResponse response = null; - if (responseObj instanceof LogMessageListResponse) { - response = (LogMessageListResponse) responseObj; - // populate disk and trim other fields - List logMessages = response.getLogMessages(); - for (VolumeLogMessage logMessage : logMessages) { - logMessage.setBrickDirectory(brick.getBrickDirectory()); - } - return logMessages; - } else { - Status status = (Status) responseObj; - throw new GlusterRuntimeException(status.toString()); - } - } - - @GET - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS + "/" + RESOURCE_DOWNLOAD) - public Response downloadLogs(@PathParam(PATH_PARAM_CLUSTER_NAME) final String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) final String volumeName) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - 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) { - // create temporary directory - File tempDir = FileUtil.createTempDir(); - String tempDirPath = tempDir.getPath(); - - for (Brick brick : volume.getBricks()) { - String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), - brick.getServerName()); - String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getBrickDirectory()); - String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; - - serverUtil.getFileFromServer(brick.getServerName(), logFilePath, tempDirPath); - - String fetchedLogFile = tempDirPath + File.separator + logFileName; - // append log file name with server name so that log files don't overwrite each other - // in cases where the brick log file names are same on multiple servers - String localLogFile = tempDirPath + File.separator + brick.getServerName() + "-" + logFileName; - - FileUtil.renameFile(fetchedLogFile, localLogFile); - } - - String gzipPath = FileUtil.getTempDirName() + CoreConstants.FILE_SEPARATOR + volume.getName() + "-logs.tar.gz"; - new ProcessUtil().executeCommand("tar", "czvf", gzipPath, "-C", tempDir.getParent(), tempDir.getName()); - - // delete the temp directory - FileUtil.recursiveDelete(tempDir); - - return gzipPath; - } - - @GET - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS) - @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) { - return getLogs(clusterName, volumeName, brickName, severity, fromTimestamp, toTimestamp, lineCount, MediaType.APPLICATION_XML); - } - - @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("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - List logMessages = null; - Volume volume = null; - try { - 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; - } - } - } - - filterLogsBySeverity(logMessages, severity); - filterLogsByTime(logMessages, fromTimestamp, toTimestamp); - - return okResponse(new LogMessageListResponse(logMessages), mediaType); - } - - private void filterLogsByTime(List logMessages, String fromTimestamp, String toTimestamp) { - Date fromTime = null, toTime = null; - - if (fromTimestamp != null && !fromTimestamp.isEmpty()) { - fromTime = DateUtil.stringToDate(fromTimestamp); - } - - if (toTimestamp != null && !toTimestamp.isEmpty()) { - toTime = DateUtil.stringToDate(toTimestamp); - } - - List messagesToRemove = new ArrayList(); - for (VolumeLogMessage logMessage : logMessages) { - Date logTimestamp = logMessage.getTimestamp(); - if (fromTime != null && logTimestamp.before(fromTime)) { - messagesToRemove.add(logMessage); - continue; - } - - if (toTime != null && logTimestamp.after(toTime)) { - messagesToRemove.add(logMessage); - } - } - logMessages.removeAll(messagesToRemove); - } - - private void filterLogsBySeverity(List logMessages, String severity) { - if (severity == null || severity.isEmpty()) { - return; - } - - List messagesToRemove = new ArrayList(); - for (VolumeLogMessage logMessage : logMessages) { - if (!logMessage.getSeverity().equals(severity)) { - messagesToRemove.add(logMessage); - } - } - logMessages.removeAll(messagesToRemove); - } - - private List getLogsForAllBricks(Volume volume, Integer lineCount) { - List logMessages; - logMessages = new ArrayList(); - // fetch logs for every brick of the volume - for (Brick brick : volume.getBricks()) { - logMessages.addAll(getBrickLogs(volume, brick, lineCount)); - } - - // Sort the log messages based on log timestamp - Collections.sort(logMessages, new Comparator() { - @Override - public int compare(VolumeLogMessage message1, VolumeLogMessage message2) { - return message1.getTimestamp().compareTo(message2.getTimestamp()); - } - }); - - return logMessages; - } - - @POST - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - public Response addBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_BRICKS) String bricks) { - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (bricks == null || bricks.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_BRICKS + "] is missing in request!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - List brickList = Arrays.asList(bricks.split(",")); - try { - glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); - } catch (ConnectionException e) { - // online server has gone offline! try with a different one. - onlineServer = clusterService.getNewOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); - } catch(Exception e1) { - return errorResponse(e1.getMessage()); - } - } catch(Exception e1) { - return errorResponse(e1.getMessage()); - } - - return createdResponse(""); - } - - @PUT - @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) - 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) { - - if (clusterName == null || clusterName.isEmpty()) { - return badRequestResponse("Cluster name must not be empty!"); - } - - if (volumeName == null || volumeName.isEmpty()) { - return badRequestResponse("Volume name must not be empty!"); - } - - if (fromBrick == null || fromBrick.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_SOURCE + "] is missing in request!"); - } - - if (toBrick == null || toBrick.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_TARGET + "] is missing in request!"); - } - - if (clusterService.getCluster(clusterName) == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - return errorResponse("No online servers found in cluster [" + clusterName + "]"); - } - - if(autoCommit == null) { - autoCommit = false; - } - - String taskId = null; - try { - taskId = migrateBrickStart(clusterName, volumeName, fromBrick, toBrick, autoCommit); - }catch(Exception e) { - return errorResponse(e.getMessage()); - } - - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" - + taskId); - } - - private String migrateBrickStart(String clusterName, String volumeName, String fromBrick, String toBrick, - Boolean autoCommit) { - MigrateBrickTask migrateDiskTask = new MigrateBrickTask(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); - } - - private 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(); - // for (Volume volume : response.getVolumes()) { - // System.out.println("\nName:" + volume.getName() + "\nType: " + volume.getVolumeTypeStr() + "\nStatus: " - // + volume.getStatusStr()); - // } - // Volume volume = new Volume(); - // volume.setName("vol3"); - // volume.setTransportType(TRANSPORT_TYPE.ETHERNET); - // List disks = new ArrayList(); - // disks.add("192.168.1.210:sdb"); - // volume.addDisks(disks); - // volume.setAccessControlList("192.168.*"); - // // Status status = vr.createVolume(volume); - // // System.out.println(status.getMessage()); - // Form form = new Form(); - // form.add("volumeName", volume.getName()); - // form.add(RESTConstants.FORM_PARAM_DELETE_OPTION, 1); - // Status status = vr.deleteVolume("Vol2", true); - // System.out.println("Code : " + status.getCode()); - // System.out.println("Message " + status.getMessage()); - - // 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/resources/v1_0/AbstractResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java new file mode 100644 index 00000000..c28c0da0 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * 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 + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +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; + +/** + * + */ +public class AbstractResource { + @Context + protected UriInfo uriInfo; + + /** + * Creates a response with HTTP status code of 201 (created) and sets the "location" header to the URI created using + * the given path relative to current path. + * + * @param relativePath + * relative path of the created resource - will be set in the "location" header of response. + * @return the {@link Response} object + */ + protected Response createdResponse(String relativePath) { + return Response.created(createRelatriveURI(relativePath)).build(); + } + + /** + * Creates a response with HTTP status code of 204 (no content) + * @return the {@link Response} object + */ + protected Response noContentResponse() { + return Response.noContent().build(); + } + + /** + * 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 locationURI + * URI to be appended to the base URI + * @return the {@link Response} object + */ + 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 base URI of the application + * @param uriString URI String to be appended to the base URI + * @return newly created URI + */ + private URI createAbsoluteURI(String uriString) { + return uriInfo.getBaseUriBuilder().path(uriString).build(); + } + + /** + * Creates a response with HTTP status code of 204 (no content), also setting the location header to given location + * @param location path of the location to be set relative to current path + * @return the {@link Response} object + */ + protected Response noContentResponse(String location) { + return Response.noContent().location(createRelatriveURI(location)).build(); + } + + /** + * Creates a URI relative to current URI + * @param location path relative to current URI + * @return newly created URI + */ + protected URI createRelatriveURI(String location) { + return uriInfo.getAbsolutePathBuilder().path(location).build(); + } + + /** + * Creates a response with HTTP status code of 500 (internal server error) and sets the error message in the + * response body + * + * @param errMessage + * Error message to be set in the response body + * @return the {@link Response} object + */ + protected Response errorResponse(String errMessage) { + return Response.serverError().type(MediaType.TEXT_HTML).entity(errMessage).build(); + } + + /** + * Creates a response with HTTP status code of 400 (bad request) and sets the error message in the + * response body + * + * @param errMessage + * Error message to be set in the response body + * @return the {@link Response} object + */ + 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. + * + * @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/v1_0/AbstractServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractServersResource.java new file mode 100644 index 00000000..8b4b6d99 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractServersResource.java @@ -0,0 +1,38 @@ +/** + * AbstractServersResource.java + * + * Copyright (c) 2011 Gluster, Inc. + * 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 + * . + */ +package com.gluster.storage.management.server.resources.v1_0; + +import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.ServerUtil; +import com.sun.jersey.api.core.InjectParam; + +/** + * Abstract resource class for servers. Abstracts basic server related functionality like "get server details". + */ +public class AbstractServersResource extends AbstractResource { + @InjectParam + protected ServerUtil serverUtil; + + @InjectParam + protected GlusterUtil glusterUtil; + + // TODO: Remove this class! +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AlertsResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AlertsResource.java new file mode 100644 index 00000000..91eeef1a --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AlertsResource.java @@ -0,0 +1,82 @@ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.*; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.AlertListResponse; +import com.gluster.storage.management.core.model.Alert; + +@Component +@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_ALERTS) +public class AlertsResource { + + @GET + @Produces(MediaType.APPLICATION_XML) + public AlertListResponse getAlerts() { + + List alerts = new ArrayList(); + + // TODO To implement the following dummy alerts + // Alert #1 + Alert alert = new Alert(); + alert.setId("0001"); + alert.setReference("Server1"); // Server + alert.setType(Alert.ALERT_TYPES.CPU_USAGE_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " in server [" + alert.getReference() + "]"); + alerts.add(alert); + + // Alert #2 + alert = new Alert(); + alert.setId("0002"); + alert.setReference("Server2"); // server:Disk - brick + alert.setType(Alert.ALERT_TYPES.MEMORY_USAGE_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " in server [" + alert.getReference() + "]"); + alerts.add(alert); + + // Alert #3 + alert = new Alert(); + alert.setId("0003"); + alert.setReference("server1:sda1"); // Disk name + alert.setType(Alert.ALERT_TYPES.DISK_USAGE_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " in disk [" + alert.getReference() + "]"); + alerts.add(alert); + + // Alert #4 + alert = new Alert(); + alert.setId("0004"); + alert.setReference("Volume3:server2:sda1"); // volume:[Disk name] + alert.setType(Alert.ALERT_TYPES.OFFLINE_VOLUME_BRICKS_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " in volume [" + alert.getReference().split(":")[0] + + "] disk [" + alert.getReference().split(":")[1] + ":" + alert.getReference().split(":")[2] + "]"); + alerts.add(alert); + + // Alert #5 + alert = new Alert(); + alert.setId("0005"); + alert.setReference("Server2"); // Server name + alert.setType(Alert.ALERT_TYPES.OFFLINE_SERVERS_ALERT); + alert.setMessage(alert.getAlertType(alert.getType()) + " [" + alert.getReference() + "]"); + alerts.add(alert); + + return new AlertListResponse(alerts); + + } + + public static void main(String[] args) { + /* + * // Unit test code AlertsResource alertResource = new AlertsResource(); AlertsListResponse alertResponse = + * alertResource.getAlerts(); List alerts = alertResponse.getAlerts(); for (Alert alert: alerts) { + * System.out.println(alert.getMessage()); } + */ + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java new file mode 100644 index 00000000..431de952 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * 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 + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +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.PATH_PARAM_CLUSTER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_CLUSTERS; + +import java.util.ArrayList; +import java.util.List; + +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; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.response.ClusterNameListResponse; +import com.gluster.storage.management.server.data.ClusterInfo; +import com.gluster.storage.management.server.services.ClusterService; +import com.sun.jersey.api.core.InjectParam; +import com.sun.jersey.spi.resource.Singleton; + +/** + * + */ +@Component +@Singleton +@Path(RESOURCE_PATH_CLUSTERS) +public class ClustersResource extends AbstractResource { + @InjectParam + private ClusterService clusterService; + + @GET + @Produces(MediaType.APPLICATION_XML) + public ClusterNameListResponse getClusters() { + List clusters = clusterService.getAllClusters(); + List clusterList = new ArrayList(); + for (ClusterInfo cluster : clusters) { + clusterList.add(cluster.getName()); + } + return new ClusterNameListResponse(clusterList); + } + + @POST + public Response createCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String 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 + "] already exists!"); + } + + try { + clusterService.createCluster(clusterName); + return createdResponse(clusterName); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse("Exception while trying to save cluster [" + clusterName + "]: [" + e.getMessage() + + "]"); + } + } + + @PUT + public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, + @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { + if(clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(knownServer == null || knownServer.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); + } + + if(clusterService.getCluster(clusterName) != null) { + return badRequestResponse("Cluster [" + clusterName + "] already exists!"); + } + + ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); + if(mappedCluster != null) { + return badRequestResponse("Server [" + knownServer + "] is already present in cluster [" + + mappedCluster.getName() + "]!"); + } + + try { + clusterService.registerCluster(clusterName, knownServer); + return noContentResponse(clusterName); + } catch(Exception e) { + // TODO: Log the exception + return errorResponse("Exception while trying to register cluster [" + clusterName + "] using server [" + + knownServer + "]: [" + e.getMessage() + "]"); + } + } + + @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") + @DELETE + public Response unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + if(clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if(cluster == null) { + return badRequestResponse("Cluster [" + clusterName + "] does not exist!"); + } + + try { + clusterService.unregisterCluster(cluster); + return noContentResponse(); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse("Exception while trying to unregister cluster [" + clusterName + "]: [" + + e.getMessage() + "]"); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java new file mode 100644 index 00000000..cb39746c --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * 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 + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +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; +import java.util.List; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.response.ServerListResponse; +import com.gluster.storage.management.core.response.ServerNameListResponse; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path(RESOURCE_PATH_DISCOVERED_SERVERS) +public class DiscoveredServersResource extends AbstractServersResource { + private List discoveredServerNames = new ArrayList(); + + public List getDiscoveredServerNames() { + return discoveredServerNames; + } + + public void setDiscoveredServerNames(List discoveredServerNames) { + synchronized (discoveredServerNames) { + this.discoveredServerNames = discoveredServerNames; + } + } + + public void removeDiscoveredServer(String serverName) { + discoveredServerNames.remove(serverName); + } + + public void addDiscoveredServer(String serverName) { + discoveredServerNames.add(serverName); + } + + @GET + @Produces(MediaType.APPLICATION_XML) + 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 discoveredServers = getDiscoveredServerDetails(); + return okResponse(new ServerListResponse(discoveredServers), mediaType); + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + } else { + return okResponse(new ServerNameListResponse(getDiscoveredServerNames()), mediaType); + } + } + + private List getDiscoveredServerDetails() { + List discoveredServers = new ArrayList(); + for (String serverName : getDiscoveredServerNames()) { + try { + discoveredServers.add(getDiscoveredServer(serverName)); + } catch(Exception e) { + // TODO: Log the exception + // continue with next discovered server + } + } + return discoveredServers; + } + + @Path("{" + PATH_PARAM_SERVER_NAME + "}") + @GET + @Produces(MediaType.APPLICATION_XML) + 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 { + return okResponse(getDiscoveredServer(serverName), mediaType); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse(e.getMessage()); + } + } + + private Server getDiscoveredServer(String serverName) { + Server server = new Server(serverName); + serverUtil.fetchServerDetails(server); + return server; + } + + public static void main(String[] args) { + 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/v1_0/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java new file mode 100644 index 00000000..619e4f55 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java @@ -0,0 +1,444 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * 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 + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_SERVER_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.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; + +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; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +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.response.GlusterServerListResponse; +import com.gluster.storage.management.server.data.ClusterInfo; +import com.gluster.storage.management.server.data.ServerInfo; +import com.gluster.storage.management.server.services.ClusterService; +import com.gluster.storage.management.server.tasks.InitializeDiskTask; +import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.SshUtil; +import com.sun.jersey.api.core.InjectParam; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_SERVERS) +public class GlusterServersResource extends AbstractServersResource { + + public static final String HOSTNAMETAG = "hostname:"; + + @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); + serverUtil.fetchServerDetails(server); + } catch (ConnectionException e) { + server.setStatus(SERVER_STATUS.OFFLINE); + } + } + + + @GET + @Produces(MediaType.APPLICATION_JSON) + 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) { + return getGlusterServers(clusterName, MediaType.APPLICATION_XML); + } + + public Response getGlusterServers(String clusterName, String mediaType) { + List glusterServers = new ArrayList(); + + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if (cluster.getServers().size() == 0) { + return okResponse(new GlusterServerListResponse(glusterServers), mediaType); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterServers = getGlusterServers(clusterName, onlineServer); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + try { + glusterServers = getGlusterServers(clusterName, onlineServer); + } catch (Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + + String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); + if (!errMsg.isEmpty()) { + return errorResponse("Couldn't fetch details for server(s): " + errMsg); + } + + return okResponse(new GlusterServerListResponse(glusterServers), mediaType); + } + + public String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { + String errMsg = ""; + + for (GlusterServer server : glusterServers) { + if (server.getStatus() == SERVER_STATUS.ONLINE && !server.getName().equals(onlineServer.getName())) { + try { + fetchServerDetails(server); + } catch (Exception e) { + errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; + } + } + } + return errMsg; + } + + public List getGlusterServers(String clusterName, GlusterServer onlineServer) { + List glusterServers; + try { + glusterServers = glusterUtil.getGlusterServers(onlineServer); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + glusterServers = glusterUtil.getGlusterServers(onlineServer); + } + return glusterServers; + } + + @GET + @Path("{serverName}") + @Produces(MediaType.APPLICATION_XML) + public Response getGlusterServerXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { + return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_XML); + } + + @GET + @Path("{serverName}") + @Produces(MediaType.APPLICATION_JSON) + public Response getGlusterServerJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { + return getGlusterServerResponse(clusterName, serverName, MediaType.APPLICATION_JSON); + } + + private Response getGlusterServerResponse(String clusterName, String serverName, String mediaType) { + try { + return okResponse(getGlusterServer(clusterName, serverName), mediaType); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + private GlusterServer getGlusterServer(String clusterName, String serverName) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterRuntimeException("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + throw new GlusterRuntimeException("Server name must not be empty!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + throw new GlusterRuntimeException("Cluster [" + clusterName + "] not found!"); + } + + 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) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + server = glusterUtil.getGlusterServer(onlineServer, serverName); + } + + if (server.isOnline()) { + fetchServerDetails(server); + } + return server; + } + + private void performAddServer(String clusterName, String serverName) { + 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) { + // online server has gone offline! try with a different one. + 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()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + 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 notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + boolean publicKeyInstalled = sshUtil.isPublicKeyInstalled(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 servers = cluster.getServers(); + 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) { + 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); + + if (!publicKeyInstalled) { + try { + // install public key (this will also disable password based ssh login) + sshUtil.installPublicKey(serverName); + } catch (Exception e) { + return errorResponse("Public key could not be installed on [" + serverName + "]! Error: [" + + e.getMessage() + "]"); + } + } + + return createdResponse(serverName); + } + + @DELETE + @Path("{" + PATH_PARAM_SERVER_NAME + "}") + public Response removeServer(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_SERVER_NAME) String serverName) { + 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!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + List servers = cluster.getServers(); + if (servers == null || servers.isEmpty() || !containsServer(servers, serverName)) { + return badRequestResponse("Server [" + serverName + "] is not attached to cluster [" + clusterName + "]!"); + } + + 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 + clusterService.removeOnlineServer(clusterName); + } else { + try { + removeServerFromCluster(clusterName, serverName); + } 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 = clusterService.getOnlineServer(clusterName, serverName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.removeServer(onlineServer.getName(), serverName); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + 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)) { + // since the cached server has been removed from the cluster, remove it from the cache + 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. + // Hence add it back to the discovered servers list. + discoveredServersResource.addDiscoveredServer(serverName); + } + + private boolean containsServer(List servers, String serverName) { + 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, serverName, diskName); + try { + initializeTask.start(); + taskResource.addTask(initializeTask); + + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" + + initializeTask.getId()); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + private void setGlusterUtil(GlusterUtil glusterUtil) { + this.glusterUtil = glusterUtil; + } + + public static void main(String[] args) { + GlusterServersResource glusterServersResource = new GlusterServersResource(); + GlusterUtil glusterUtil = new GlusterUtil(); + glusterUtil.setSshUtil(new SshUtil()); + glusterServersResource.setGlusterUtil(glusterUtil); + // System.out.println(glusterServersResource.getServerDetails("127.0.0.1").size()); + + // To add a server + // GlusterServerResponse response = glusterServersResource.addServer("my-server"); + // System.out.println(response.getData().getName()); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java new file mode 100644 index 00000000..777565eb --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java @@ -0,0 +1,175 @@ +/** + * TaskResource.java + * + * Copyright (c) 2011 Gluster, Inc. + * 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 + * . + */ +package com.gluster.storage.management.server.resources.v1_0; + +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.RESOURCE_PATH_CLUSTERS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.model.TaskInfo; +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 extends AbstractResource { + private Map tasksMap = new HashMap(); + + public TasksResource() { + } + + public void addTask(Task task) { + tasksMap.put(task.getId(), task); + } + + public void removeTask(Task task) { + tasksMap.remove(task.getId()); + } + + public List getAllTasksInfo() { + List allTasksInfo = new ArrayList(); + for (Map.Entry entry : tasksMap.entrySet()) { + checkTaskStatus(entry.getKey()); + allTasksInfo.add(entry.getValue().getTaskInfo()); // TaskInfo with latest status + } + return allTasksInfo; + } + + public Task getTask(String taskId) { + for (Map.Entry entry : tasksMap.entrySet()) { + if (entry.getValue().getId().equals(taskId)) { + return entry.getValue(); + } + } + return null; + } + + @GET + @Produces(MediaType.APPLICATION_XML) + 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 { + Task task = checkTaskStatus(taskId); + return okResponse(task.getTaskInfo(), MediaType.APPLICATION_XML); + } catch (GlusterRuntimeException e) { + return errorResponse(e.getMessage()); + } + } + + 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 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); + + try { + if (taskOperation.equals(RESTConstants.TASK_RESUME)) { + 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(); + } + return (Response) noContentResponse(); + } catch(GlusterValidationException ve) { + return badRequestResponse(ve.getMessage()); + } catch (GlusterRuntimeException e) { + return errorResponse(e.getMessage()); + } + } + + @DELETE + @Path("/{" + PATH_PARAM_TASK_ID + "}") + @Produces(MediaType.APPLICATION_XML) + public Response deleteTask(@PathParam(PATH_PARAM_TASK_ID) String taskId, + @QueryParam(FORM_PARAM_OPERATION) String taskOperation) { + Task task = getTask(taskId); + if (task == null) { + return notFoundResponse("Task [" + taskId + "] not found!"); + } + + 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/v1_0/UsersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java new file mode 100644 index 00000000..1b5e8fad --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. + * 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 + * . + *******************************************************************************/ +package com.gluster.storage.management.server.resources.v1_0; + +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; +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.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.encoding.PasswordEncoder; +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(RESOURCE_PATH_USERS) +public class UsersResource extends AbstractResource { + @Autowired + private JdbcUserDetailsManager jdbcUserService; + + @Autowired + private PasswordEncoder passwordEncoder; + + private static final Logger logger = Logger.getLogger(UsersResource.class); + + @Path("{" + PATH_PARAM_USER + "}") + @GET + @Produces(MediaType.APPLICATION_XML) + 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 getAuthenticationResponse(user, MediaType.APPLICATION_JSON); + } + + public Response getAuthenticationResponse(String user, String mediaType) { + return (SecurityContextHolder.getContext().getAuthentication().getName().equals(user) ? okResponse( + Status.STATUS_SUCCESS, mediaType) : unauthorizedResponse()); + } + + @Path("{" + PATH_PARAM_USER + "}") + @PUT + public Response changePassword(@FormParam("oldpassword") String oldPassword, + @FormParam("newpassword") String newPassword) { + try { + jdbcUserService.changePassword(oldPassword, passwordEncoder.encodePassword(newPassword, null)); + } catch (Exception ex) { + String errMsg = "Could not change password. Error: [" + ex.getMessage() + "]"; + logger.error(errMsg, ex); + return errorResponse(errMsg); + } + return noContentResponse(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java new file mode 100644 index 00000000..a09b7f08 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java @@ -0,0 +1,1025 @@ +/** + * VolumesResource.java + * + * Copyright (c) 2011 Gluster, Inc. + * 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 + * . + */ +package com.gluster.storage.management.server.resources.v1_0; + +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_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; +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_TARGET; +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.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; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_BRICK_NAME; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DELETE_OPTION; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DOWNLOAD; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_FROM_TIMESTAMP; +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.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; + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +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; +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; +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.Brick; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Status; +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; +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.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.MigrateBrickTask; +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; +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 VOLUME_DIRECTORY_CLEANUP_SCRIPT = "clear_volume_directory.py"; + private static final String VOLUME_BRICK_LOG_SCRIPT = "get_volume_brick_log.py"; + + @InjectParam + private ServerUtil serverUtil; + + @InjectParam + private GlusterUtil glusterUtil; + + @InjectParam + private ClusterService clusterService; + + @InjectParam + private VolumeOptionsDefaults volumeOptionsDefaults; + + @InjectParam + private TasksResource taskResource; + + @GET + @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("Cluster name must not be empty!"); + } + + 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 = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return new VolumeListResponse(new ArrayList()); + } + + try { + return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return new VolumeListResponse(new ArrayList()); + } + + return new VolumeListResponse(glusterUtil.getAllVolumes(onlineServer.getName())); + } + } + + @POST + @Produces(MediaType.APPLICATION_XML) + 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) { + if(clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + String missingParam = checkMissingParamsForCreateVolume(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 notFoundResponse("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"); + } + + try { + performCreateVolume(clusterName, volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, + options); + return createdResponse(volumeName); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + public void performCreateVolume(String clusterName, String volumeName, String volumeType, String transportType, Integer replicaCount, + Integer stripeCount, String bricks, String accessProtocols, String options) { + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + glusterUtil.createVolume(onlineServer.getName(), volumeName, volumeType, transportType, replicaCount, stripeCount, bricks, accessProtocols, options); + } + } + + /** + * Returns name of the missing parameter if any. If all parameters are present, + * @param volumeName + * @param volumeType + * @param transportType + * @param replicaCount + * @param stripeCount + * @param bricks + * @param accessProtocols + * @param options + * @return + */ + private String checkMissingParamsForCreateVolume(String volumeName, String volumeType, + String transportType, Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, + String options) { + + return (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 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("Cluster name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("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 = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + try { + volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + volume = glusterUtil.getVolume(volumeName, onlineServer.getName()); + } + return volume; + } + + @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, + @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!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + 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 { + if (onlineServer == null) { + 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); + } + } + + private Status performOperation(String volumeName, String operation, GlusterServer onlineServer) { + if (operation.equals(TASK_START)) { + return glusterUtil.startVolume(volumeName, onlineServer.getName()); + } else if (operation.equals(TASK_STOP)) { + return glusterUtil.stopVolume(volumeName, onlineServer.getName()); + } else { + return new Status(Status.STATUS_CODE_FAILURE, "Invalid operation code [" + operation + "]"); + } + } + + @DELETE + @Path("{" + PATH_PARAM_VOLUME_NAME + "}") + public Response deleteVolume(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, + @QueryParam(QUERY_PARAM_DELETE_OPTION) Boolean deleteFlag) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if (deleteFlag == null) { + deleteFlag = false; + } + + Volume volume = null; + try { + volume = getVolume(clusterName, volumeName); + } catch (Exception e) { + // TODO: Log the exception + return errorResponse(e.getMessage()); + } + + List bricks = volume.getBricks(); + Status status = glusterUtil.deleteVolume(volumeName, clusterService.getOnlineServer(clusterName) + .getName()); + if(!status.isSuccess()) { + return errorResponse("Couldn't delete volume [" + volumeName + "]. Error: " + 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("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) + public Response removeBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @QueryParam(QUERY_PARAM_BRICKS) String bricks, + @QueryParam(QUERY_PARAM_DELETE_OPTION) Boolean deleteFlag) { + List brickList = Arrays.asList(bricks.split(",")); // Convert from comma separated string (query + // parameter) + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (bricks == null || bricks.isEmpty()) { + return badRequestResponse("Parameter [" + QUERY_PARAM_BRICKS + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if(deleteFlag == null) { + deleteFlag = false; + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + 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 brickList, GlusterServer onlineServer) { + try { + glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); + } + } + + @SuppressWarnings("rawtypes") + private void cleanupDirectories(List 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; + } + } + if(!errors.trim().isEmpty()) { + throw new GlusterRuntimeException("Volume directory cleanup errors: " + errors.trim()); + } + } + + private void postDelete(String volumeName, List bricks, boolean deleteFlag) { + Status result; + for (Brick brick : bricks) { + String brickDirectory = brick.getBrickDirectory(); + String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); + + result = (Status) serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_DIRECTORY_CLEANUP_SCRIPT + + " " + mountPoint + " " + volumeName + (deleteFlag ? " -d" : ""), Status.class); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Error in post-delete operation of volume [" + volumeName + "]: " + + result); + } + } + } + + @POST + @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) + 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("Cluster name must not be empty!"); + } + + if(volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + 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 notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.setOption(volumeName, key, value, onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch(Exception e) { + return errorResponse(e.getMessage()); + } + + return createdResponse(key); + } + + @PUT + @Path("{" + PATH_PARAM_VOLUME_NAME + " }/" + RESOURCE_OPTIONS) + public Response resetOptions(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if(volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.resetOptions(volumeName, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + 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 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()); + } + + @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 getBrickLogs(Volume volume, Brick brick, Integer lineCount) + throws GlusterRuntimeException { + String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), brick.getServerName()); + String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getBrickDirectory()); + String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; + + // Usage: get_volume_disk_log.py + Object responseObj = serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_BRICK_LOG_SCRIPT + " " + + logFilePath + " " + lineCount, LogMessageListResponse.class); + + LogMessageListResponse response = null; + if (responseObj instanceof LogMessageListResponse) { + response = (LogMessageListResponse) responseObj; + // populate disk and trim other fields + List logMessages = response.getLogMessages(); + for (VolumeLogMessage logMessage : logMessages) { + logMessage.setBrickDirectory(brick.getBrickDirectory()); + } + return logMessages; + } else { + Status status = (Status) responseObj; + throw new GlusterRuntimeException(status.toString()); + } + } + + @GET + @Produces(MediaType.APPLICATION_OCTET_STREAM) + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS + "/" + RESOURCE_DOWNLOAD) + public Response downloadLogs(@PathParam(PATH_PARAM_CLUSTER_NAME) final String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) final String volumeName) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + 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) { + // create temporary directory + File tempDir = FileUtil.createTempDir(); + String tempDirPath = tempDir.getPath(); + + for (Brick brick : volume.getBricks()) { + String logDir = glusterUtil.getLogLocation(volume.getName(), brick.getQualifiedName(), + brick.getServerName()); + String logFileName = glusterUtil.getLogFileNameForBrickDir(brick.getBrickDirectory()); + String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName; + + serverUtil.getFileFromServer(brick.getServerName(), logFilePath, tempDirPath); + + String fetchedLogFile = tempDirPath + File.separator + logFileName; + // append log file name with server name so that log files don't overwrite each other + // in cases where the brick log file names are same on multiple servers + String localLogFile = tempDirPath + File.separator + brick.getServerName() + "-" + logFileName; + + FileUtil.renameFile(fetchedLogFile, localLogFile); + } + + String gzipPath = FileUtil.getTempDirName() + CoreConstants.FILE_SEPARATOR + volume.getName() + "-logs.tar.gz"; + new ProcessUtil().executeCommand("tar", "czvf", gzipPath, "-C", tempDir.getParent(), tempDir.getName()); + + // delete the temp directory + FileUtil.recursiveDelete(tempDir); + + return gzipPath; + } + + @GET + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_LOGS) + @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) { + return getLogs(clusterName, volumeName, brickName, severity, fromTimestamp, toTimestamp, lineCount, MediaType.APPLICATION_XML); + } + + @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("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + List logMessages = null; + Volume volume = null; + try { + 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; + } + } + } + + filterLogsBySeverity(logMessages, severity); + filterLogsByTime(logMessages, fromTimestamp, toTimestamp); + + return okResponse(new LogMessageListResponse(logMessages), mediaType); + } + + private void filterLogsByTime(List logMessages, String fromTimestamp, String toTimestamp) { + Date fromTime = null, toTime = null; + + if (fromTimestamp != null && !fromTimestamp.isEmpty()) { + fromTime = DateUtil.stringToDate(fromTimestamp); + } + + if (toTimestamp != null && !toTimestamp.isEmpty()) { + toTime = DateUtil.stringToDate(toTimestamp); + } + + List messagesToRemove = new ArrayList(); + for (VolumeLogMessage logMessage : logMessages) { + Date logTimestamp = logMessage.getTimestamp(); + if (fromTime != null && logTimestamp.before(fromTime)) { + messagesToRemove.add(logMessage); + continue; + } + + if (toTime != null && logTimestamp.after(toTime)) { + messagesToRemove.add(logMessage); + } + } + logMessages.removeAll(messagesToRemove); + } + + private void filterLogsBySeverity(List logMessages, String severity) { + if (severity == null || severity.isEmpty()) { + return; + } + + List messagesToRemove = new ArrayList(); + for (VolumeLogMessage logMessage : logMessages) { + if (!logMessage.getSeverity().equals(severity)) { + messagesToRemove.add(logMessage); + } + } + logMessages.removeAll(messagesToRemove); + } + + private List getLogsForAllBricks(Volume volume, Integer lineCount) { + List logMessages; + logMessages = new ArrayList(); + // fetch logs for every brick of the volume + for (Brick brick : volume.getBricks()) { + logMessages.addAll(getBrickLogs(volume, brick, lineCount)); + } + + // Sort the log messages based on log timestamp + Collections.sort(logMessages, new Comparator() { + @Override + public int compare(VolumeLogMessage message1, VolumeLogMessage message2) { + return message1.getTimestamp().compareTo(message2.getTimestamp()); + } + }); + + return logMessages; + } + + @POST + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) + public Response addBricks(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @PathParam(PATH_PARAM_VOLUME_NAME) String volumeName, @FormParam(FORM_PARAM_BRICKS) String bricks) { + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (bricks == null || bricks.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_BRICKS + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + List brickList = Arrays.asList(bricks.split(",")); + try { + glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); + } catch (ConnectionException e) { + // online server has gone offline! try with a different one. + onlineServer = clusterService.getNewOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterUtil.addBricks(volumeName, brickList, onlineServer.getName()); + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + } catch(Exception e1) { + return errorResponse(e1.getMessage()); + } + + return createdResponse(""); + } + + @PUT + @Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + RESOURCE_BRICKS) + 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) { + + if (clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Cluster name must not be empty!"); + } + + if (volumeName == null || volumeName.isEmpty()) { + return badRequestResponse("Volume name must not be empty!"); + } + + if (fromBrick == null || fromBrick.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_SOURCE + "] is missing in request!"); + } + + if (toBrick == null || toBrick.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_TARGET + "] is missing in request!"); + } + + if (clusterService.getCluster(clusterName) == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + return errorResponse("No online servers found in cluster [" + clusterName + "]"); + } + + if(autoCommit == null) { + autoCommit = false; + } + + String taskId = null; + try { + taskId = migrateBrickStart(clusterName, volumeName, fromBrick, toBrick, autoCommit); + }catch(Exception e) { + return errorResponse(e.getMessage()); + } + + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" + + taskId); + } + + private String migrateBrickStart(String clusterName, String volumeName, String fromBrick, String toBrick, + Boolean autoCommit) { + MigrateBrickTask migrateDiskTask = new MigrateBrickTask(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); + } + + private 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(); + // for (Volume volume : response.getVolumes()) { + // System.out.println("\nName:" + volume.getName() + "\nType: " + volume.getVolumeTypeStr() + "\nStatus: " + // + volume.getStatusStr()); + // } + // Volume volume = new Volume(); + // volume.setName("vol3"); + // volume.setTransportType(TRANSPORT_TYPE.ETHERNET); + // List disks = new ArrayList(); + // disks.add("192.168.1.210:sdb"); + // volume.addDisks(disks); + // volume.setAccessControlList("192.168.*"); + // // Status status = vr.createVolume(volume); + // // System.out.println(status.getMessage()); + // Form form = new Form(); + // form.add("volumeName", volume.getName()); + // form.add(RESTConstants.FORM_PARAM_DELETE_OPTION, 1); + // Status status = vr.deleteVolume("Vol2", true); + // System.out.println("Code : " + status.getCode()); + // System.out.println("Message " + status.getMessage()); + + // 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/tasks/ServerDiscoveryTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java index b0959445..e5b8d726 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java @@ -30,7 +30,7 @@ import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.server.data.ClusterInfo; import com.gluster.storage.management.server.data.PersistenceDao; -import com.gluster.storage.management.server.resources.DiscoveredServersResource; +import com.gluster.storage.management.server.resources.v1_0.DiscoveredServersResource; import com.gluster.storage.management.server.utils.ServerUtil; /** 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 2a86a690..a24e147c 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 @@ -44,7 +44,7 @@ import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; import com.gluster.storage.management.core.utils.GlusterCoreUtil; 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.resources.v1_0.TasksResource; import com.sun.jersey.api.core.InjectParam; @Component diff --git a/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml b/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml index 59714c87..c8301c7b 100644 --- a/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml +++ b/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml @@ -16,7 +16,7 @@ - -- cgit