diff options
| author | Shireesh Anjal <shireesh@gluster.com> | 2011-06-21 17:44:47 +0530 |
|---|---|---|
| committer | Shireesh Anjal <shireesh@gluster.com> | 2011-06-21 17:46:22 +0530 |
| commit | e0ac946f71010ab1ff1497c6a5ef0b9aac2be359 (patch) | |
| tree | 57dd2329d4b8aa6cb85e99d8e3d1f3a9dc20ccd5 /src | |
| parent | c9bbd766a562b0623f0fc970f42dc778cbd72c71 (diff) | |
Modified ClustersResource to return appropriate HTTP response codes
Diffstat (limited to 'src')
5 files changed, 304 insertions, 104 deletions
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/ClusterNameListResponse.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/ClusterNameListResponse.java new file mode 100644 index 00000000..3b10ac86 --- /dev/null +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/response/ClusterNameListResponse.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.core.response; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Response object for transferring cluster names during REST communication. This is just a wrapper over a list of + * Strings, and is required because the jersey rest framework can't transfer lists directly. + */ +@XmlRootElement(name="clusters") +public class ClusterNameListResponse { +private List<String> clusterNames = new ArrayList<String>(); + + public ClusterNameListResponse() { + } + + public ClusterNameListResponse(List<String> clusterNames) { + this.clusterNames = clusterNames; + } + + @XmlElement(name = "cluster", type = String.class) + public List<String> getClusterNames() { + return clusterNames; + } +} 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 new file mode 100644 index 00000000..200bd24b --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/AbstractResource.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com> + * This file is part of Gluster Management Console. + * + * Gluster Management Console is free software; you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Gluster Management Console is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License + * for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see + * <http://www.gnu.org/licenses/>. + *******************************************************************************/ +package com.gluster.storage.management.server.resources; + +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; + +/** + * + */ +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 + * path to be used for creating the URI to be set in the "location" header of response. + * @return the {@link Response} object + */ + protected Response createdResponse(String relativePath) { + return Response.created(uriInfo.getAbsolutePathBuilder().path(relativePath).build()).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 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().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).entity(errMessage).build(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java index e1971322..a5bfe5ff 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/ClustersResource.java @@ -26,7 +26,6 @@ import static com.gluster.storage.management.core.constants.RESTConstants.RESOUR import java.util.ArrayList; import java.util.List; -import javax.persistence.EntityTransaction; import javax.ws.rs.DELETE; import javax.ws.rs.FormParam; import javax.ws.rs.GET; @@ -36,21 +35,13 @@ 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.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.response.GlusterServerResponse; -import com.gluster.storage.management.core.response.StringListResponse; +import com.gluster.storage.management.core.response.ClusterNameListResponse; import com.gluster.storage.management.server.data.ClusterInfo; -import com.gluster.storage.management.server.data.PersistenceDao; -import com.gluster.storage.management.server.data.ServerInfo; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.SshUtil; +import com.gluster.storage.management.server.services.ClusterService; import com.sun.jersey.api.core.InjectParam; import com.sun.jersey.spi.resource.Singleton; @@ -60,128 +51,92 @@ import com.sun.jersey.spi.resource.Singleton; @Component @Singleton @Path(RESOURCE_PATH_CLUSTERS) -public class ClustersResource { - - @InjectParam - private PersistenceDao clusterDao; - - @InjectParam - private GlusterServersResource glusterServersResource; - +public class ClustersResource extends AbstractResource { @InjectParam - private GlusterUtil glusterUtil; + private ClusterService clusterService; - @Autowired - private SshUtil sshUtil; - - public void setClusterDao(PersistenceDao clusterDao) { - this.clusterDao = clusterDao; - } - - public PersistenceDao getClusterDao() { - return clusterDao; - } - @GET - @Produces(MediaType.TEXT_XML) - public StringListResponse getClusters() { - List<ClusterInfo> clusters = getClusterDao().findAll(); + @Produces(MediaType.APPLICATION_XML) + public ClusterNameListResponse getClusters() { + List<ClusterInfo> clusters = clusterService.getAllClusters(); List<String> clusterList = new ArrayList<String>(); for (ClusterInfo cluster : clusters) { clusterList.add(cluster.getName()); } - return new StringListResponse(clusterList); + return new ClusterNameListResponse(clusterList); } @POST - @Produces(MediaType.TEXT_XML) - public Status createCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = new ClusterInfo(); - cluster.setName(clusterName); - + 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 { - clusterDao.save(cluster); - txn.commit(); - return Status.STATUS_SUCCESS; + clusterService.createCluster(clusterName); + return createdResponse(clusterName); } catch (Exception e) { - txn.rollback(); - return new Status(Status.STATUS_CODE_FAILURE, "Exception while trying to save cluster [" + clusterName - + "]: [" + e.getMessage() + "]"); + // TODO: Log the exception + return errorResponse("Exception while trying to save cluster [" + clusterName + "]: [" + e.getMessage() + + "]"); } } - @PUT - @Produces(MediaType.TEXT_XML) - public Status registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, + public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = new ClusterInfo(); - cluster.setName(clusterName); + if(clusterName == null || clusterName.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } - GlusterServer server = new GlusterServer(knownServer); - try { - List<GlusterServer> glusterServers = glusterUtil.getGlusterServers(server); - List<ServerInfo> servers = new ArrayList<ServerInfo>(); - for(GlusterServer glusterServer : glusterServers) { - String serverName = glusterServer.getName(); - - checkAndSetupPublicKey(serverName); - - ServerInfo serverInfo = new ServerInfo(serverName); - serverInfo.setCluster(cluster); - clusterDao.save(serverInfo); - servers.add(serverInfo); - } - cluster.setServers(servers); - clusterDao.save(cluster); - txn.commit(); - return Status.STATUS_SUCCESS; - } catch(Exception e) { - txn.rollback(); - return new Status(e); + if(knownServer == null || knownServer.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); } - } - - private void checkAndSetupPublicKey(String serverName) { - if(sshUtil.isPublicKeyInstalled(serverName)) { - return; + + if(clusterService.getCluster(clusterName) != null) { + return badRequestResponse("Cluster [" + clusterName + "] already exists!"); } - if(!sshUtil.hasDefaultPassword(serverName)) { - // public key not installed, default password doesn't work. can't install public key - throw new GlusterRuntimeException( - "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."); + ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); + if(mappedCluster != null) { + return badRequestResponse("Server [" + knownServer + "] is already present in cluster [" + + mappedCluster.getName() + "]!"); } + - // install public key (this will also disable password based ssh login) - sshUtil.installPublicKey(serverName); + try { + clusterService.registerCluster(clusterName, knownServer); + return noContentResponse(); + } catch(Exception e) { + // TODO: Log the exception + return errorResponse("Exception while trying to register cluster [" + clusterName + "] using server [" + + knownServer + "]: [" + e.getMessage() + "]"); + } } - @SuppressWarnings("unchecked") @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") @DELETE - @Produces(MediaType.TEXT_XML) - public Status deleteCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - List<ClusterInfo> clusters = clusterDao.findBy("name = ?1", clusterName); - if (clusters == null || clusters.size() == 0) { - return new Status(Status.STATUS_CODE_FAILURE, "Cluster [" + clusterName + "] doesn't exist!"); + 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 = clusters.get(0); - EntityTransaction txn = clusterDao.startTransaction(); + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if(cluster == null) { + return badRequestResponse("Cluster [" + clusterName + "] does not exist!"); + } + try { - clusterDao.delete(cluster); - txn.commit(); - return Status.STATUS_SUCCESS; + clusterService.unregisterCluster(cluster); + return noContentResponse(); } catch (Exception e) { - txn.rollback(); - return new Status(Status.STATUS_CODE_FAILURE, "Exception while trying to delete cluster [" + clusterName - + "]: [" + e.getMessage() + "]"); + // 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/services/ClusterService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java index d043278c..0aabb714 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java @@ -18,17 +18,30 @@ *******************************************************************************/ package com.gluster.storage.management.server.services; +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 java.util.ArrayList; import java.util.List; import javax.persistence.EntityTransaction; +import javax.ws.rs.FormParam; +import javax.ws.rs.PathParam; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.gluster.storage.management.core.constants.CoreConstants; import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.server.data.ClusterInfo; import com.gluster.storage.management.server.data.PersistenceDao; import com.gluster.storage.management.server.data.ServerInfo; +import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.SshUtil; +import com.sun.jersey.api.core.InjectParam; /** * Service class for functionality related to clusters @@ -38,6 +51,19 @@ public class ClusterService { @Autowired private PersistenceDao<ClusterInfo> clusterDao; + @Autowired + private PersistenceDao<ServerInfo> serverDao; + + @Autowired + private GlusterUtil glusterUtil; + + @Autowired + private SshUtil sshUtil; + + public List<ClusterInfo> getAllClusters() { + return clusterDao.findAll(); + } + public ClusterInfo getCluster(String clusterName) { List<ClusterInfo> clusters = clusterDao.findBy("name = ?1", clusterName); if(clusters.size() == 0) { @@ -47,6 +73,97 @@ public class ClusterService { return clusters.get(0); } + public ClusterInfo getClusterForServer(String serverName) { + List<ServerInfo> servers = serverDao.findBy("name = ?1", serverName); + if(servers.size() == 0) { + return null; + } + + return servers.get(0).getCluster(); + } + + public void createCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = new ClusterInfo(); + cluster.setName(clusterName); + + try { + clusterDao.save(cluster); + txn.commit(); + } catch (RuntimeException e) { + txn.rollback(); + throw e; + } + } + + public void registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, + @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = new ClusterInfo(); + cluster.setName(clusterName); + + GlusterServer server = new GlusterServer(knownServer); + try { + List<GlusterServer> glusterServers = glusterUtil.getGlusterServers(server); + List<ServerInfo> servers = new ArrayList<ServerInfo>(); + for(GlusterServer glusterServer : glusterServers) { + String serverName = glusterServer.getName(); + + checkAndSetupPublicKey(serverName); + + ServerInfo serverInfo = new ServerInfo(serverName); + serverInfo.setCluster(cluster); + clusterDao.save(serverInfo); + servers.add(serverInfo); + } + cluster.setServers(servers); + clusterDao.save(cluster); + txn.commit(); + } catch(RuntimeException e) { + txn.rollback(); + throw e; + } + } + + private void checkAndSetupPublicKey(String serverName) { + if(sshUtil.isPublicKeyInstalled(serverName)) { + return; + } + + if(!sshUtil.hasDefaultPassword(serverName)) { + // public key not installed, default password doesn't work. can't install public key + throw new GlusterRuntimeException( + "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."); + } + + // install public key (this will also disable password based ssh login) + sshUtil.installPublicKey(serverName); + } + + public void unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + ClusterInfo cluster = getCluster(clusterName); + + if (cluster == null) { + throw new GlusterRuntimeException("Cluster [" + clusterName + "] doesn't exist!"); + } + + unregisterCluster(cluster); + } + + public void unregisterCluster(ClusterInfo cluster) { + EntityTransaction txn = clusterDao.startTransaction(); + try { + clusterDao.delete(cluster); + txn.commit(); + } catch (RuntimeException e) { + txn.rollback(); + throw e; + } + } + public void mapServerToCluster(String clusterName, String serverName) { EntityTransaction txn = clusterDao.startTransaction(); ClusterInfo cluster = getCluster(clusterName); diff --git a/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml index e65ef3a9..3c7d6436 100644 --- a/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml +++ b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml @@ -54,6 +54,12 @@ </constructor-arg> </bean> + <bean id="serverDao" class="com.gluster.storage.management.server.data.PersistenceDao"> + <constructor-arg type="java.lang.Class"> + <value>com.gluster.storage.management.server.data.ServerInfo</value> + </constructor-arg> + </bean> + <!-- bean id="dataSourceFactory" class="com.gluster.storage.management.server.data.GlusterDataSource" /> <bean id="dataSource" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="targetObject"> |
